agentafk
Surfaces

Telegram bot

Talk to Agent AFK, receive unattended results, and answer questions from your phone.

The Telegram bot gives each allowed chat an agent conversation and can deliver daemon notifications. Use it when you need to work from your phone, inspect a running session, or answer a task's question while away from the terminal.

Set up the bot

Create a bot with @BotFather using /newbot and copy its token.

Run the interactive wizard. It validates the token, discovers your chat ID after you message the bot, and stores the token and allowlist in your user configuration:

afk telegram setup

Start the bot and check its status:

afk telegram start
afk telegram status

The wizard sets TELEGRAM_BOT_TOKEN and AFK_TELEGRAM_ALLOWED_CHAT_IDS in ~/.afk/config/afk.env. The allowlist is a comma separated set of chat IDs; all other chats are ignored. If you configure it manually, use afk config env set TELEGRAM_BOT_TOKEN for masked secret entry. AFK_TELEGRAM_CWD selects the working directory for bot sessions when run as a service. Manage the process with afk telegram stop, restart, and logs; afk telegram logs -f follows the log. See Run as a service for persistent hosting.

Commands in the chat

The following handlers are registered by the bot. Telegram's command picker and /help show a subset; /help can also show available session slash commands.

CommandUse
/start, /helpWelcome text and command help.
/clear, /compactStart over by clearing history, or compact the current conversation.
/model, /model opusChoose a model, with buttons when no argument is given. The advertised short aliases are opus, sonnet, and haiku.
/cd, /cwd, /nameShow or change the session directory, or show or set its name.
/new, /sessionsStart another conversation or list saved conversations with buttons to switch back.
/afk on, /afk offEnable or disable autonomous mode for this chat session.
/usageShow Claude subscription usage.
/watch, /unwatch, /abortFollow another live session in this chat, stop following, or request an authenticated abort of the watched session.
/inbox, /inbox release all, /inbox drop allReview, accept, or discard peer messages held for this chat's session. A message ID prefix can replace all.
/good, /badRecord positive or negative feedback on the current session.

/inbox is especially useful when AFK_PEER_INBOUND=hold. It shows each held peer message's sender, age, and preview. Releasing one accepts it even while hold mode remains active. Peer messages are not user instructions; inspect them before releasing. See Peer messaging.

A chat has one active conversation at a time, not just one conversation forever. /new preserves the old session; /sessions lists resumable sessions and lets you tap one to stage a resume on your next message. Switching or creating a session is refused while a turn is running. A topic has its own conversation route, so a button tapped inside a topic switches that topic's session rather than the General topic's.

Send files, photos, and background work

Send a text or code document, or a PDF, as a Telegram attachment. Text formats such as .txt, .md, .json, .py, and .ts are decoded as UTF-8; PDF content is passed as a document block to the model. Add a caption to explain what you want done with it. The document limit is 5 MB, including files whose downloaded size exceeds that limit. Unsupported formats receive an error message. Photos are also supported; voice, audio, video, and stickers are not.

You can ask the agent to dispatch a long investigation with the agent tool in background mode. The dispatch returns a job ID without waiting for the result, letting you continue the conversation. When a noncancelled background subagent finishes, the bot pushes its result to the originating chat and topic. If that session is idle and has no user message waiting, it also wakes automatically to process the result. Otherwise the result is injected into the next turn. Long result bodies are capped in the notification and include a /bgsub:join marker identifying the job; use the CLI background job command to retrieve its full output when available. See Subagents.

In groups, inbound messages include a sanitized sender marker with the Telegram sender ID so the agent can distinguish participants. Replies and manually quoted text carry a short reference to the earlier message; a reply to the bot is marked as a reply to the assistant. Referenced content is truncated, and unaddressed group messages may never enter a tag only session.

Chats, groups, and topics

AFK_TELEGRAM_ALLOWED_CHAT_IDS controls inbound access. Outbound notifications default to the first private chat in that list (or the first allowed chat). Set AFK_TELEGRAM_PRIMARY_CHAT_ID to pick a different default, or configure telegram.notify.mode as primary, broadcast, or custom in afk.config.json; custom mode uses telegram.notify.targets. AFK_TELEGRAM_NOTIFY_MODE fills in the mode when file configuration does not specify one.

For a quieter allowed group, set telegram.tagOnlyChats to its chat ID, or use AFK_TELEGRAM_TAG_ONLY_CHAT_IDS as the fallback. In such a chat the bot answers ordinary text or photo only when you reply to the bot, mention its @username, or use a Telegram text mention of the bot. Slash commands remain available. Turn off Telegram bot privacy mode with BotFather /setprivacy Disable if you expect the bot to receive nonaddressed group messages at all.

{
  "telegram": {
    "notify": { "mode": "primary", "primaryChatId": 12345678 },
    "tagOnlyChats": [-100987654321],
    "chatAliases": { "ops": -100987654321 }
  }
}

To send to one chat instead of the default, the agent's send_telegram tool accepts chat: "ops" (or an allowed numeric chat ID). A scheduled task's notifyChat accepts the same kind of target. Explicit chat targets must resolve to an ID in the inbound allowlist: send_telegram refuses an invalid target, while a daemon task warns and falls back to its default notification route. telegram.chatAliases lets you keep raw IDs out of routine prompts. For a supergroup with topics enabled, send_telegram also accepts a numeric thread_id, but only together with an explicit chat. Ordinary bot replies and background results follow the topic they originated in. See Schedule unattended work.

Autonomous runs and approvals

From a CLI session, /afk on lets the agent continue reversible work while you are away. Each turn's parsed Done, Blocked, Asking, or Interrupted state is sent to Telegram as a compact report. The report prefers structured verdict fields rather than tool output, applies secret redaction, and limits notification volume. The chat bot's own /afk on similarly enables autonomous mode for that chat; /afk off restores normal mode. Its mode is runtime only, so a bot restart requires you to reenable it.

There are two different high risk approval paths. A CLI session in autonomous mode can ask you to approve or deny a single high risk operation. Use /watch from Telegram to follow that CLI session; its approval request appears as inline Approve and Deny buttons. A refusal, timeout, or unrecognized answer denies the call. The always on Telegram bot's own autonomous session deliberately does not offer one tap approval of high risk operations: it refuses the operation and asks you to handle it deliberately. Never assume /afk on in the bot makes irreversible actions phone approvable.

The bot also renders ordinary path approval and agent questions through Telegram prompts. A scheduled daemon task can save a question as a durable handoff; you can answer it in Telegram and the daemon resumes later. These are distinct from the CLI autonomous high risk gate. See Permissions and Daemon.

Troubleshooting

If the bot starts but stays silent, verify the chat ID in AFK_TELEGRAM_ALLOWED_CHAT_IDS and check afk telegram status and afk telegram logs. If a service cannot see a token exported only in your interactive shell, set it in the user afk.env instead. If a tag only group is silent, confirm you mentioned the bot or replied to it, and check BotFather privacy mode.

On this page