Channels
One normalized API — connections, bindings, threads, events — with the platform machinery (webhook ingress, socket fleets, rendering, reactions, retries) managed for you. Every conversation runs under your bot identity: your Slack app, your BotFather bot, your Discord bot, your WhatsApp business number, your Azure Bot, your Lark app — and soon your iMessage number.
In this section: Quickstart · Routing · Webhooks · guides for Telegram, Slack, Discord, WhatsApp, Microsoft Teams, Lark, LINE, iMessage (coming soon), and Email (SES). The endpoint-level reference lives in the API reference.
The object model
- Channel app — your own bot credentials for one platform (
POST /v1/channels/apps), encrypted at rest and write-only through the API. Registration proves the credentials against the platform where an API exists and returns thesetupsteps the platform cannot automate. - Connection — one installed conversation surface: a Telegram chat, a Slack channel, a Discord channel, a WhatsApp conversation, a Lark chat or group, an iMessage number pairing.
- Binding — routes a connection (or one thread of it) to a destination: an AgentSky session, or your own webhook endpoint.
- Thread ids — plain
{platform}:…strings used verbatim for posting and events (e.g.telegram:12345,slack:C0123:1712.0034). Treat them as opaque. - Webhook endpoint — where your service receives signed channel events (
message.receivedand friends).
Routing modes
Session destination (zero code) — bind a connection to an AgentSky session: inbound messages become agent turns, replies flow back automatically, and working markers (⏳ → ✅) ride the platform's reactions where supported.
Webhook destination (your code) — bind to a webhook endpoint instead: inbound arrives as signed message.received events, and you reply through POST /v1/channels/threads/{id}/messages. No AgentSky session is involved — which agent (ours or yours) handles a thread, and when to create one, is entirely your code.
Messaging
# post into a thread (markdown renders natively per platform; degrades safely elsewhere)
curl -s -X POST "https://api.agentsky.dev/v1/channels/threads/telegram:12345/messages" \
-H "Authorization: Bearer $AST_TOKEN" -H 'content-type: application/json' \
-d '{"parts": [{"type": "markdown", "text": "done — see **the report**"}], "done": true}'Parts are text, markdown, file ({type: "file", file_id}), or a labeled raw part ({type: "raw", platform, payload}) as the native escape hatch. Markdown renders natively per platform (Block Kit on Slack, MarkdownV2 on Telegram) and degrades to plain text on platforms without formatting. done: true resolves the working marker on the message being answered. Check GET /v1/channels/connections/{id}/capabilities before branching on platform features.
For files, upload through the Files API and pass the returned ID. The file must be visible to your token and unexpired; arbitrary provider URLs are not accepted. Native file replies require capabilities.files (Slack, Discord, Telegram and Lark). Message files total at most 32 MiB; each Discord file is at most 20 MiB. Unsupported channels return an explicit error. Long Markdown replies are sent in complete platform-sized parts.
Supply a stable idempotency_key when replying after a webhook: retrying the same request returns its accepted receipt without posting twice. Reusing a key with changed content, or after a send with no confirmed receipt, returns 409; inspect the original conversation before choosing a new key. Set failed: true to resolve a failed working marker. Do not combine it with done: true.
Where to next
- The quickstart gets a BotFather bot answering as your agent in about five minutes.
- Routing covers bindings, precedence, re-binding, proactive deliveries, and the hosted connect flow.
- Webhooks is the event reference: signatures, retries, idempotency, and the SSE dev mirror.
AgentSky