Telegram¶
aegis serve includes a built-in Telegram bot that lets you drive the
full substrate from your phone. v0.10 extends the original session-spawn
verbs with a substrate command surface: nine new commands that expose
queues, schedules, budgets, peers, and help — every resource the
substrate has grown since v0.2 is now reachable from the chat.
Setup¶
- Create a bot via @BotFather and copy the token.
- Find your personal chat ID (send any message to the bot and call
getUpdates, or use the@userinfobothelper). - Add to
.aegis.yaml:
# .aegis.yaml
telegram:
token: "..." # or set AEGIS_TELEGRAM_TOKEN (env wins)
chat_id: 123456789 # the single allowed chat
# Optional: append a brevity hint to every bare-text message.
# Set to "" to disable.
# auto_prompt: "Be concise. Reply in one paragraph."
- Start the serve:
A systemd unit template lives at scripts/aegis-serve.service.
Bot account requirements¶
- A private bot — only the single
telegram.chat_idis accepted. Any message from a different chat ID is silently dropped. - The bot needs no special permissions beyond
sendMessage/getUpdates. No inline mode, no group membership needed. - Webhook mode is not supported; the bot uses long-polling internally.
Session verbs (v0.2+, registry-wired in v0.10)¶
These five commands have been available since v0.2. In v0.10 they were migrated into the command registry alongside the new substrate verbs — behavior is unchanged.
| Command | Action |
|---|---|
/new [agent] |
Spawn a new session (defaults to default_agent) |
/close [handle] |
Close a session (default: the active one) |
/interrupt |
Interrupt the active turn |
/agents |
List configured agent profiles |
/sessions |
List open sessions with their state |
/<handle> text… |
One-shot to a specific session — doesn't move the active pointer |
| bare text | Sent to the active session, with telegram.auto_prompt appended |
Substrate command surface (v0.10)¶
Nine new commands reach the substrate resources directly. They follow
a consistent two-part shape: /resource subcommand [args] [@peer].
Output style¶
- Status and mutation replies — plain text, one or two lines.
- Tables and multi-line details — wrapped in a fenced code block so Telegram renders monospace without any MarkdownV2-escape gymnastics.
- Errors — short plain text explaining the problem and, where relevant, what to try instead.
Queue commands¶
/queue list¶
Shows all configured queues with depth, in-flight count, and the most recent task's status.
QUEUE AGENT DEPTH IN-FLIGHT LAST
impl opus 0 0 ✓ 17:42 task#abc123
fast haiku 2 1 ⏳ 18:01 task#def456
research opus 0 0 — none
v0.10 limitation: local only. The substrate does not yet expose a
GET /remote/v1/queue endpoint. If you add @peer, the bot replies:
/queue show <name>¶
Full detail on one queue: in-flight tasks, pending tasks, and the last 10 records from the queue's JSONL audit log.
queue: impl (agent: opus, max_parallel: 2)
IN-FLIGHT
⏳ task#abc123 worker:lucid-knuth started 17:42 payload="implement…"
PENDING
○ task#def456 enqueued 17:45 by agent:caller payload="fix…"
RECENT
✓ task#ghi789 completed 17:38 duration 4m12s
✗ task#jkl012 failed 17:30 duration 1m05s
Local only in v0.10 for the same reason as /queue list.
Schedule commands¶
/schedule list [@peer]¶
Lists all schedules with next fire time, enabled state, and fire count.
NAME SOURCE NEXT FIRE ENABLED FIRES
nightly-build pushed 2026-05-27T02:00:00Z ✓ 47
weekly-report inline 2026-05-31T08:00:00Z ✓ 12
ad-hoc-test pushed — ✗ 0
Add @<peer> to inspect a remote serve's schedule table:
/schedule show <name> [@peer]¶
Full detail on one schedule: the full spec plus runtime fields (next fire, last fire, fire count, in-flight flag, enabled state, source classification, push provenance).
/schedule run <name>¶
Force-fire a schedule immediately. Does not affect its next regular fire. Local only in v0.10 — cross-host fire is not yet supported.
If you add @peer:
Budget commands¶
/budget list [@peer]¶
Summary of budget state for every queue that has budgets configured.
QUEUE BUDGETS STATUS UNBLOCKS
impl 4 ⛔ $1.23/$1.00 1h 18:42Z
review 2 ✓ $4.10/$10.00 24h —
fast 0 — no budget —
Add @<peer> to inspect a remote serve's budget state:
/budget show <queue> [@peer]¶
Full decision for one queue: every configured budget entry with limit, amount spent in the window, headroom, and pass/block status.
budget for queue 'impl'
CONSTRAINT LIMIT SPENT WINDOW HEADROOM STATUS
usd 1.00 1.23 1h -0.23 ⛔
usd 10.00 4.50 24h 5.50 ✓
output_tokens 500000 612340 1h -112340 ⛔
usd 50.00 18.20 7d 31.80 ✓
blocked by 2 budget(s); unblocks at 19:10Z
Peers¶
/peers¶
Lists every configured remote with URL, auth status, and a live reachability probe (3s timeout; any HTTP response = reachable).
NAME URL AUTH REACHABLE
vps http://100.64.0.5:8556 token ✓
desktop http://100.64.0.3:8556 — ✗ unreachable
No @peer argument — the command is about peers themselves.
Help¶
/help¶
Lists every registered command grouped by resource, with a one-line summary per command.
/help <resource>¶
Lists all commands for a resource (e.g. /help queue, /help schedule).
/help <command>¶
Full detail for a specific command (e.g. /help queue show,
/help schedule run).
@<peer> cross-host syntax¶
Commands that support cross-host inspection accept an @<peer> token
anywhere in the argument list:
The peer name must match a key in the remotes: section of your
.aegis.yaml. If the name is unknown, the bot replies:
Commands that are local-only in v0.10 (/queue list, /queue show,
/schedule run) return a clear message instead of silently ignoring the
@peer token.
Error reference¶
| Situation | Reply |
|---|---|
| Unknown verb | Falls through to /<handle> alias routing; if no session matches: no session 'X' — /sessions |
Bad subcommand (/queue ghost) |
unknown subcommand 'ghost' for /queue; /help queue |
Missing required arg (/queue show) |
usage: /queue show <name> |
Unknown @peer |
unknown peer 'vps'; known: [desktop, …] |
@peer on local-only command |
▸ <command> not yet supported cross-host (local only). Drop @<peer>. |
| Substrate error | ▸ error: <message> (one line; full traceback goes to the serve log) |
| Remote HTTP error | The remote's error field, verbatim |
FAQ¶
What's not supported in v0.10?
/queue list @<peer>and/queue show @<peer>— the substrate has noGET /remote/v1/queueendpoint yet. Planned for v0.10.x./schedule run @<peer>— remote fire-now is not yet wired. Land when the use case arrives./schedule enable//schedule disable— these edit YAML on disk and deserve deliberate operator action, not a mobile tap./queue cancel <task_id>— needsQueueManager.cancel(task_id)on the substrate side. Side-quest for a later round.- Canvas, terminal, workflow, group commands — sit-at-keyboard ops. Telegram exposure is low-value for v0.10.
- Substrate push notifications (budget trips, schedule fires, etc.) —
a dedicated v0.11/v0.12 round with a
notify()API on the substrate. - Voice note / file input/output — a separate brainstorm round.
Can I use aegis serve without Telegram?
Yes. Telegram is entirely optional. Omit the telegram: block from
.aegis.yaml (or set token/chat_id to null) and the serve runs as a pure
headless substrate (MCP plane + HTTP remote plane).
Is there a webhook mode?
No. The bot uses long-polling. Webhook support can be added later if you're running the serve behind a public-IP reverse proxy.
The bot ignores my messages.
Check that telegram.chat_id matches your personal chat ID, not the
bot's own ID. Any message from an unrecognized chat is dropped without
a reply.
Can multiple users share one bot?
No. telegram.chat_id is a single integer. If you need multi-user
access, run separate aegis serve instances with separate bots.