Skip to content

Drive the agent from Telegram

Atomic Agent can be driven from your phone over Telegram. It’s the same agent and the same model you use on your desktop; Telegram is a remote control, not a second assistant. The channel is single-owner: once paired, only the owner’s messages are accepted and everyone else is dropped.

What you need

  • A Telegram account.
  • A bot token from Telegram’s @BotFather (create a bot, and it hands you a token that looks like 123456:ABC-...).
  • Atomic Agent installed (the prebuilt binary bundles its own runtime; Node.js 25.7+ is needed only when running from source), with a model configured.

Set it up

Since v0.5.6, Telegram is set up in the TUI’s Integrations tab. There is no separate Telegram panel any more. Open the TUI:

Terminal window
atomic-agent tui

Then go to Manage → Integrations → Telegram (or type /telegram, which opens the same place) and press Enter to open it.

  1. Create a bot. In Telegram, open @BotFather, send /newbot, then a display name, then a username ending in bot. BotFather replies with the token. Copy the whole line.

  2. Save the token. Move to the Bot token field, press e, paste the token and press Enter. The value is checked for the right shape, written to <stateDir>/.env as TELEGRAM_BOT_TOKEN, and the channel starts by itself. No restart is needed.

  3. Pair yourself as the owner. Press p, then send your bot any message within 60 seconds (/start works fine). The first eligible direct message inside that window claims ownership; the agent saves your account to telegram.ownerUserId. From then on, only your account is accepted.

    If the window expires before you send anything, nothing is paired. Press p again. Only a private chat can pair; a message in a group never claims the bot.

The Channel field is the on/off switch: press Enter (or e) on it to toggle. Off stops the bot without forgetting the token. s restarts the channel.

Every DM is dropped while no owner is set, so messaging the bot before you pair does nothing at all. Pairing is the easy way to set the owner. If you already know your numeric Telegram user id, you can instead type it into the Owner field, or set telegram.ownerUserId in config.json.

Configure by hand

If you’d rather not use the TUI:

  1. Enable the channel in config.json:

    {
    "telegram": { "enabled": true }
    }
  2. Add your bot token to the secrets file at <stateDir>/.env (by default ~/.atomic-agent/.env), never to config.json. The agent writes this file with mode 0600:

    Terminal window
    TELEGRAM_BOT_TOKEN=123456:ABC-your-bot-token
  3. Restart the agent. A token you add to .env by hand is picked up on the next start. (If you set the token from the TUI instead, no restart is needed.)

  4. Set the owner. Either run /telegram pair in the TUI and DM the bot within 60 seconds, or put your numeric user id in telegram.ownerUserId.

Using it

Once paired, just chat with the bot to send the agent a request, the same way you’d type in the TUI. When the agent wants to run a dangerous tool, execution pauses and an approval request arrives as inline approve / deny buttons; the tool only runs if you approve.

Built-in commands:

/start, /help show commands and setup
/status this chat's session id, status, turns, steps and last error
/sessions every chat this bot has a session for
/switch <session-id> point this chat at an existing Telegram session
/new rotate this chat to a fresh session (the current one is archived)
/model show the provider and model in use
/model <provider> [model-id] switch the provider, and optionally the model
/cancel abort this chat's running turn

Every chat has its own session

Each Telegram chat, and each forum topic in a group, has its own session, separate from the TUI. Chatting from your phone doesn’t continue the conversation open on your desktop, and /new rotates only the current chat: its session is archived and a fresh one starts, leaving the TUI and your other chats untouched. /switch accepts only sessions that belong to Telegram, never TUI ones.

Files and media

Send files in a direct message with the bot: photos, documents, video, audio, voice notes, animations, video notes and stickers up to 20 MB are saved to <stateDir>/inbox/telegram/ and handed to the agent with your caption and the saved path. Albums arrive as one batch. Larger files are refused with a notice.

The agent can send files back: photos up to 10 MB and documents up to 50 MB.

Media sent in a group is ignored; only DMs with the owner carry files.

Groups

You can add the bot to a group or a forum. It still acts only for the owner, and only when the owner addresses it:

  • reply to one of the bot’s messages,
  • mention it as @yourbot, or
  • use a command aimed at it, like /new@yourbot. A bare /new in a group is ignored, because Telegram delivers it to every bot there.

With Telegram’s privacy mode on (the BotFather default), plain @mentions are not delivered to the bot, so use replies or /cmd@yourbot. To make mentions work, disable privacy mode in BotFather (/setprivacy) and re-add the bot to the group.

Approvals expire

An approval request sent to Telegram auto-denies after 8 minutes if you don’t tap anything. That’s the away-from-keyboard policy: a pending tool call can’t wait indefinitely for a phone you left on a table. The window isn’t configurable.

Two config keys worth knowing

Both live under telegram in config.json and both have sensible defaults, so you only touch them if something misbehaves:

KeyDefaultEffect
parseMode"html"How agent replies are formatted. "html" converts the model’s markdown into Telegram’s HTML subset; "plain" disables formatting entirely, the escape hatch if the formatter mangles something
progressIndicatortrueThe live “Thinking…” bubble that mirrors the turn’s activity and deletes itself when the reply lands. Set false to switch it off
{
"telegram": {
"enabled": true,
"parseMode": "plain",
"progressIndicator": false
}
}

parseMode governs agent replies only. Command output (/help, /status, the cancellation acks) and approval prompts are always sent as plain text, so switching to "html" won’t add formatting there.

The /telegram commands

Bare /telegram opens Manage → Integrations, where the Telegram row lives. The verbs below drive the channel from the chat editor:

CommandWhat it does
/telegram enableTurn the channel on and save it to config
/telegram disableTurn it off and save it to config
/telegram startSame as enable
/telegram stopSame as disable
/telegram restartRestart the channel
/telegram pairOpen the 60-second owner-pairing window
/telegram clear-tokenDelete the stored bot token
/telegram clear-ownerForget the paired owner

To set or replace the token, use the Bot token field in Integrations (press e). There is no /telegram token command.

clear-token and clear-owner are the revoke path. Use clear-token when a token may have leaked (revoke it in BotFather too, then save the new one), and clear-owner to hand the bot to a different account, after which you pair again. Both take effect immediately, with no confirmation.

More than one bot

The Swarm tab (/swarm) lists every Telegram and Discord bot this agent runs, and lets you add extra bots, each with its own token, owner and role. The primary Telegram bot from this page shows there too, but it is managed only in Integrations. See TUI panels.

Privacy and safety

  • Single owner by design. Pairing binds the channel to one owner; messages from anyone else are dropped, and it fails closed when no owner is set.
  • The token stays in the secrets file. It lives in .env (0600) and is scrubbed from error messages before they reach logs.
  • Approvals still apply. Remote-driving doesn’t bypass the approval gate: risky tool calls wait for your explicit yes, from your phone.
  • Your messages go through Telegram. Requests and replies travel over Telegram’s servers. If a cloud provider is active, prompts also go to that provider.
  • TUI panels: every key in the Integrations and Swarm tabs.
  • Local models: the model Telegram drives.
  • Configuration: the .env secrets file and precedence rules.
  • Tools: the approval gate behind those inline buttons.