Skip to content

Telegram

q15 can answer in Telegram. It is the same agent you reach in the browser: the same transcript, the same memory, the same tools. Connecting it costs you two values and about ten minutes.

Be clear about the trade before you start: Telegram sees your messages. The browser channel seals content between your browser and the agent; the Telegram channel does not, because the messages pass through Telegram’s servers by definition. Use it for the things you would type into any chat app. Anything you want sealed stays in the browser client.

  • A bot token from Telegram’s @BotFather. Send it /newbot, answer two questions, and it prints a token.
  • Your numeric user ID. Telegram identifies people by number, not by username. Any of the well-known ID bots reports yours when you message it.
  1. Put the token in a file.

    The Compose stack mounts one file per secret and passes its path to the agent. Copy the tracked template and fill it in:

    in your deployment directory
    cp secrets/q15_telegram_token.example secrets/q15_telegram_token
    chmod 600 secrets/q15_telegram_token

    It reaches the agent as Q15_TELEGRAM_TOKEN_FILE, pointing at /run/q15-secrets/q15_telegram_token inside the container.

    You should now have a second file beside the template. ls -l secrets/ shows it mode 600, and secrets/q15_telegram_token.example untouched.

  2. Put your user ID in a second file.

    Terminal window
    cp secrets/q15_telegram_allowed_user_ids.example secrets/q15_telegram_allowed_user_ids

    One numeric ID per line. This list is the only thing standing between your agent and anyone who finds the bot, so it is not optional: q15 refuses to build a Telegram channel with an empty allow-list rather than reading an empty list as “everyone”.

    You should now have both files in secrets/, each containing one line and nothing else. A file with a trailing blank line is fine; a file with two IDs is not, unless both people should be able to talk to your agent.

  3. Point the config at both.

    agent-config.yaml
    agent:
    telegram:
    token_env: Q15_TELEGRAM_TOKEN
    allowed_user_ids_env: Q15_TELEGRAM_ALLOWED_USER_IDS

    The stack sets the matching *_FILE variables, so the values themselves never appear in the YAML.

    You should now see a third file under secrets/, and grep -n TELEGRAM deploy/compose/docker-compose.image-first.yml shows the two *_FILE variables the agent will read.

  4. Restart the agent and send the bot a message.

    Terminal window
    podman compose --env-file deploy/compose/release.env \
    -f deploy/compose/docker-compose.image-first.yml up -d --force-recreate q15-agent

    You should now see the agent’s reply in the chat, and the same exchange in your browser client’s history a moment later.

    If nothing arrives: the user ID is wrong, or the token file is still the empty template. Both are logged on stdout by the agent, and the second is listed in Troubleshooting.

In a private chat, a long answer grows in place while it is being written. Telegram’s native thinking indicator shows while the model works, reasoning appears as a short excerpt when the model streams it, and the finished answer replaces it. Updates reuse one message, are coalesced to at most one per second, and refresh every 20 seconds during long waits. Telegram’s Stop button cancels the run; the unfinished draft is discarded.

How much of the machinery you see is your choice, per chat:

Command What the chat shows
/progress quiet Thinking, partial replies and routine tool activity stay hidden. Only the long-wait notice appears.
/progress progress The current action, with a short command, file or search preview (up to 320 characters, five lines). This is the default.
/progress verbose The same action, with a longer preview (up to 640 characters, ten lines) and longer reasoning excerpts.

Tool output is never dumped into a progress message; only what the agent asked for. Commands keep their line breaks and shell syntax inside a code block.

Both directions work.

  • To the agent: send a photo, a document, a voice note, a video, a sticker or a GIF. It is stored in the agent’s media store under a content hash and attached to your message, so the agent sees the file, not a link.
  • From the agent: when the agent attaches something, it arrives as the matching Telegram kind: photo, audio, document, video, animation, sticker or video note.

A failed attachment does not lose your caption: the message still arrives, with a line saying what could not be ingested.

  • No sealing. Everything on this channel passes through Telegram.
  • The token is a bearer credential. Anyone holding it can act as your bot. It belongs in a secret file, not in the YAML, and it belongs in your backup only if that backup is encrypted.
  • Long polling, so no inbound port. q15 asks Telegram for updates; it never accepts a connection. There is nothing to expose, and it works behind NAT.
  • One bot per agent. Two agents need two bots, and they keep two separate conversations.
  • The two clients share one transcript. An exchange from Telegram shows up in the browser history, because the agent keeps one conversation and both clients read it. What differs is delivery: an answer written in Telegram is sent to Telegram, and is not repeated in the browser.
  • Chat for the browser client that seals its payloads.
  • Jobs for scheduled work; a job created here reports back here.
  • Credentials for how the bot token is held.