Telegram
Telegram is optional. sona init + sona chat work without a bot. Use this page when you want the same assistant on your phone.
The adapter long-polls the Bot API, so you don't need a public IP, a tunnel, or a webhook server — Sona pulls updates over an outbound HTTPS connection.
Get a bot token
- Open Telegram, search for @BotFather, start a chat.
- Send
/newbot. - Pick a display name — what users will see in the chat header. Anything goes.
- Pick a username — must be globally unique and end in
_bot(e.g.myname_sona_bot). - BotFather replies with the token. It looks like
123456789:ABC-DEF1234ghIkl-zyx57W2v1u123ew11.
Keep the token secret — anyone with it can impersonate your bot.
Optional but useful, still in BotFather:
/setdescription— short blurb users see before the first message/setabouttext— long description on the bot's profile page/setuserpic— bot avatar/setcommands— populate the slash-command menu (see slash commands below)/setjoingroupsand/setprivacy— group behaviour (default: groups disabled, "privacy mode" on so the bot only sees commands and mentions)
Wire it into Sona
Prefer the channel command (does not re-run the full wizard):
sona channel add telegramPaste the token, or confirm the env var if TELEGRAM_BOT_TOKEN is already set. You can still edit the file directly:
# ~/.sona/sona.yml
channels:
telegram:
token: ${TELEGRAM_BOT_TOKEN} # or paste the literal stringThe ${VAR} form makes Sona read from the environment at boot — you keep the token out of the config file but still tie it to the channel config. If you'd rather paste the literal token, that works too.
Restart the daemon:
sona stop
sonaOn a healthy start you should see:
INFO c.t.c.t.TelegramAdapter [] - Telegram adapter started — listening for messagesIf you see Unauthorized in the logs, the token is wrong or revoked — re-issue via BotFather /token and try again.
First message + pairing
Open t.me/<your_bot_username> and send hi.
A fresh install has no owner. The bot asks you to reply YES in that same chat — no second terminal, no pairing code.
You: hi
Bot: Hi! This Sona has no owner yet. Reply YES to claim it.
You: YES
Bot: You're the owner of this Sona.After that, unknown senders get an 8-character pairing code. You approve them:
sona pair list # pending + approved
sona pair approve AB3K7NPM # 8 chars, A–Z 2–9 (no 0 O 1 I)Do not pass telegram:<userId> to approve. That is not a pairing code.
Pairing is per-(channelId, senderId). Approving someone on Telegram does not approve the same person on Slack.
Slash commands
Telegram's slash-command menu helps users discover what a bot can do. Set the menu from BotFather:
/setcommands
@your_bot_username
help - What can this bot do?
new - Start a new conversation
stop - Stop the current taskSona doesn't currently parse slash commands into special behaviours — they flow into the gateway like any other text. If you want a command to do something specific, register a skill whose match() looks for the /help prefix.
Threads, groups, and multi-user chats
By default Telegram bots only see DMs and messages that mention them. To use Sona in a group:
- In BotFather:
/mybots→ pick your bot → Bot Settings → Group Privacy → Turn off. (This lets the bot see every message in the group, not just@mentions.) - Add the bot to the group.
- Anyone in the group can now talk to it — but pairing applies per-user, so you'll need to approve each user that should be allowed to use the LLM budget.
For 1:1 DMs Sona's session boundary is the user's Telegram ID; conversations across days resume from where they left off (until the daemon is restarted with sona uninstall, or you explicitly purge ~/.sona/sessions/).
Media
The adapter accepts inbound photos, documents, and voice notes; they're attached to the UnifiedMessage as Attachment records. What happens next depends on whether your configured LLM is vision-capable:
| Attachment | Vision LLM (Claude Sonnet, GPT-4o, Gemini Vision) | Text-only LLM |
|---|---|---|
| Photo | Encoded inline; passed to the LLM as image input | Logged, not sent to the LLM |
| Document (PDF, txt) | If a tool's wired for it (tnsai-tools PDF / text), the agent can ask for content; otherwise logged | Same |
| Voice note | Not yet wired — tracked in tnsai-tools STT toolkit |
For outbound media, the adapter renders UnifiedResponse.attachments as Telegram media — Sona doesn't ship outbound-media skills today, but the SPI supports it.
Privacy + audit
Sona logs every inbound message + the LLM reply to ~/.sona/sona.log (and the per-session JSON in ~/.sona/sessions/). The Telegram chat metadata (user ID, message ID, timestamps) is in the audit log; the LLM's API call to the provider follows the provider's own retention policy.
If you need a redaction filter on the way in — e.g. strip emails or credit-card numbers before they reach the LLM — see the framework's redaction guide. Wiring it through Sona is one extra config block; no code change.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
Unauthorized in logs | Token wrong / revoked | Re-issue via BotFather /token, then sona channel add telegram |
Conflict: terminated by other getUpdates request | Another process is polling the same bot | Stop the other process; only one consumer per token |
| Bot is added to a group but doesn't respond | Group privacy is on | BotFather → bot settings → group privacy → turn off |
| Message reaches Sona logs but no reply | LLM key is invalid, or budget is exhausted | Check sona logs --grep ERROR -i for the provider's response |
First hi does not ask for YES | This install already has an owner | Expected — later senders get an 8-char pairing code |
sona pair approve says "no such code" | Daemon restarted between code-issue and approve | Issue a new one by sending a new message |
Removing the bot
To stop using a bot but keep its token alive for future use:
# ~/.sona/sona.yml
channels: {} # empty map = no adapters at bootthen sona stop && sona. The bot exists on Telegram's side until you /deletebot via BotFather.
Channels
A channel is one way you talk to Sona. None of them except the terminal is required. sona chat works after sona init with only an LLM key.
How Sona Works
Sona is mostly routing. The LLM, the tool calls, the streaming — all of that is tnsai-core doing its job. Sona's contribution is deciding which agent should hear an inbound message, keeping a session for each (channel, sender) pair, and enforcing a pairing policy so strangers can't burn your LLM budget.