Channels
Channels overview
One row per catalog adapter. Always pass via="hosted" or via="self-host". Self-host needs a local adapter and that channel’s secrets — not a Caspian API key. Hosted-only names the gateway speaks (Bluesky, …) are not rows — inbound arrives as a gateway event.
The catalog
| Channel | Inbound | Bot token | Self-host loop |
|---|---|---|---|
| Telegram | webhook, poll | always (BotFather) | handle or poll |
| Slack | webhook, socket | self-host | listen("slack") |
| Discord | socket only | self-host | listen("discord") |
| webhook | self-host | handle("email", …) |
|
| webhook | self-host | handle + Meta verify GET |
|
| Messenger | webhook | self-host | handle + Meta verify GET |
| SMS | webhook | self-host | handle (Twilio form) |
| Voice | webhook | self-host | handle + TwiML response |
| iMessage | webhook | self-host | handle (relay HMAC) |
| X | webhook | self-host | handle + CRC GET |
| Linear | webhook | self-host | handle |
Capabilities (what thread.* can do)
Derived from caspian.catalog. Adapters degrade where they must (SMS has no buttons; Telegram send_blocks is text + keyboard).
| buttons | edit | react | typing | media | voice | |
|---|---|---|---|---|---|---|
| Telegram | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Slack | ✓ | ✓ | ✓ | ✓ | ||
| Discord | ✓ | ✓ | ✓ | ✓ | ✓ | |
| ✓ | ||||||
| ✓ | ✓ | ✓ | ||||
| Messenger | ✓ | ✓ | ✓ | |||
| SMS | ✓ | |||||
| Voice | ✓ | |||||
| iMessage | ✓ | |||||
| X | ||||||
| Linear |
◆
Self-host add() currently requires bot_token for every catalog row. Channels that do not have a BotFather-style token pass bot_token="local" so paperwork succeeds; the real secrets are the ones in each example (access_token, account_sid, …).