Channels
A channel is one way humans talk to Sona. The framework's tnsai-channels module defines the SPI; each adapter is one implementation that translates a platform-specific transport into the gateway's UnifiedMessage / UnifiedResponse records.
You can run more than one channel at the same time — Sona starts every channel listed under channels: in ~/.sona/sona.yml at boot.
Shipped today
These adapters are production-ready and live in the framework / Sona repos:
- Telegram — long-poll Bot API, threads, media, pairing flow. The default channel — Sona ships with it enabled out of the box.
- CLI — interactive REPL (
sona chat) or newline-delimited JSON for scripting (sona chat --json). No external dependencies; useful for local dogfooding, headless deployment smoke tests, and shell pipelines. - Email (IMAP/SMTP) — async inbox poll + SMTP send, thread tracking via
Message-ID. Framework adapter and Sona-side YAML config landed in framework 0.10.4 (TNS-354).
Framework adapter shipped, Sona-side wiring in progress
Each of these landed as a tnsai-channels adapter in framework 0.10.4. Sona discovers them at boot via SPI (ChannelDiscovery.discoverFactories), but the daemon still needs its own YAML config block for the channel to be useful — that wiring is the follow-up task tracked alongside each row.
| Channel | Framework PR | Sona-side wiring | Status |
|---|---|---|---|
| Slack | TNS-350 | TNS-502 | Socket Mode WebSocket + chat.postMessage |
| Discord | TNS-351 | TNS-503 | Gateway v10 WebSocket + heartbeat |
| WhatsApp Business | TNS-352 | TNS-504 | Cloud API webhook + HMAC verify |
Once a Sona-side wiring task lands, its setup guide follows here. Drop a thumbs-up on the Linear issue if you need one urgently or open a discussion on the Sona repo.
How channels compose
Every adapter sits behind the same ChannelAdapter SPI, so the gateway code is identical for all of them. The flow:
- Adapter receives a platform-specific message (Telegram update, Slack event, stdin line, …).
- Adapter translates it into a
UnifiedMessagewith achannelId("telegram","cli", …) and asenderId. - Gateway routes by
(channelId, senderId)to a session; the session runs the agent. - Gateway hands the reply back as a
UnifiedResponse; adapter renders it to the platform.
The How It Works page has a Mermaid sequence diagram that traces one Telegram message end-to-end. The same diagram applies to every adapter — only the first and last hops change.
Writing your own
The framework's Channels reference covers the SPI surface (ChannelAdapter, StreamingChannelAdapter, UnifiedMessage, UnifiedResponse). Sona will auto-discover any ChannelAdapter SPI on the classpath at boot — META-INF/services/com.tnsai.channels.api.ChannelAdapter.
To use a custom adapter with Sona, drop the JAR into ~/.sona/lib/, restart the daemon, and add its channels: config block to sona.yml. No Sona-side code change.