Messaging
Connect your agent to Slack, Microsoft Teams, Discord interactions, email, Telegram, or WhatsApp. It's the same agent — same memory, same tools, same threads — just reachable from more places.
Using the Dispatch template? All of this is wired up for you in Admin → Messaging. Click to connect each platform — you don't need to read the rest of this page unless you're customizing or building your own template. See Dispatch or the Dispatch template reference.
What you can do
- Email your agent at an address like
agent@yourcompany.com— it replies in-thread, just like a coworker would. - CC your agent on a thread — it'll read along and jump in when you ask.
- DM the agent on Slack, or
@mentionit in any channel. - Message the bot in Microsoft Teams in an allowed tenant.
- Run a Discord slash command. The built-in Discord adapter handles HTTP interactions; ordinary Discord messages require a separate Gateway runtime.
- Message the agent on Telegram or WhatsApp from your phone.
- Same agent, same memory. Whatever you tell it on Slack is remembered when you email it later. The web chat and external messages share one thread history.
- Act on other tools from a message. An @mention can end in a row in Notion, an issue in Jira, or a record in HubSpot — see @mention in Slack → row in Notion for the full worked example.
- For one-way in-app alerts (bell icon, webhooks) see Notifications.
web chat + external messages share it
Every platform fans into the same agent loop and the same SQL thread history — so a Slack DM and an email continue the same conversation.
Set up Slack
What you'll need
- A Slack workspace where you can install apps (admin access)
- About 5 minutes
Managed Add to Slack
Managed OAuth is the recommended setup for Dispatch and multi-workspace apps. Each install gets its own encrypted bot-token bundle and health record, and Slack workspace, app, channel, and thread IDs are part of the conversation key.
In Admin → Messaging, select Agent manifest to download the host-specific
agent-native-slack-manifest.json, then create or update your Slack app at api.slack.com/apps by importing it from App Manifest. The manifest enables Slack's currentagent_viewexperience plus a writable App Home Messages tab for direct messages. Slack app icons are not part of the manifest. Under Basic Information → Display Information, upload the Agent-Native icon so the Agents picker matches the product; you can use the app's publicicon-512.svgas the source and convert it to a Slack-supported upload format if needed.Verify that the manifest requests these exact Bot Token Scopes under OAuth & Permissions:
assistant:write app_mentions:read channels:history channels:read chat:write files:read groups:history groups:read im:history im:read mpim:history mpim:read pins:read reactions:read users:read users:read.emailAdd this OAuth Redirect URL:
https://your-app.example.com/_agent-native/integrations/slack/oauth/callbackTurn on Event Subscriptions, set the Request URL, and subscribe to
app_home_opened,app_context_changed,app_mention, andmessage.im:https://your-app.example.com/_agent-native/integrations/slack/webhookTurn on Interactivity & Shortcuts and set its Request URL:
https://your-app.example.com/_agent-native/integrations/slack/interactionsConfigure
SLACK_CLIENT_ID,SLACK_CLIENT_SECRET, andSLACK_SIGNING_SECRETon your app. Then open Admin → Messaging and click Add to Slack. Only an organization owner or admin can create a shared workspace install.Reinstall the Slack app after applying or changing the manifest, scopes, events, Agent view, or Messages tab so the installation receives the updated permissions and surfaces.
In the current Agent view, app_home_opened detects when someone opens the
Messages tab, app_context_changed provides the Slack surface they are viewing,
and message.im delivers their direct messages. Slack owners and admins can hide
installed agents for the workspace or organization, and each member can hide an
agent from their own top bar. If the install succeeds but the agent is not
visible there, check those Slack display controls or open it from Tools →
Apps.
The OAuth entry and callback endpoints are
/_agent-native/integrations/slack/oauth/install and
/_agent-native/integrations/slack/oauth/callback. Slack access and refresh
tokens remain server-side. The canonical manifest leaves Slack token rotation
disabled.
Use the install health control in Messaging settings to test or disconnect a
workspace.
Legacy single-workspace setup
For a private, single-workspace deployment, you can still install the app
manually and configure SLACK_BOT_TOKEN plus SLACK_SIGNING_SECRET.
SLACK_ALLOWED_TEAM_IDS and SLACK_ALLOWED_API_APP_IDS are recommended in
production. The environment token is a compatibility fallback; managed installs
take precedence.
Slack-native collaboration
- Explicit thread turns. Start in a channel with an
@mention. Each later channel turn must explicitly mention the agent too. Ordinary thread replies, inactive threads, and general channel chatter do not invoke it. DMs remain direct invocations. - Bounded native context. Before execution, the adapter loads a bounded slice of the Slack thread plus channel, sender, reaction, and file metadata. It keeps file references and permalinks, never raw file bodies, in durable integration state.
- Live work card. Slack's streaming task surface shows the plan, tool and
delegated-agent progress, and final answer. The requester can cancel a running
task or approve/deny a gated action from signed, single-use controls.
assistant:writeenables Agent View context events;chat:writepowers replies and live status updates. - Personal and channel identity. A personal Slack DM is accepted only for a verified Agent-Native organization member or a Slack identity already linked to that member. Configured channels instead run as the channel's explicit service principal, with separate channel policies and budgets, so shared tools and connections do not silently inherit the latest speaker's personal access.
- Explicit channel memory. Channel memory is isolated by authorized conversation scope. The agent saves or removes it only when someone explicitly asks; ordinary conversation is not auto-memorized.
- Channel routines. A recurring job created from Slack keeps its origin scope, destination, thread, workspace, and optional model, then delivers its scheduled result back to that Slack conversation.
- Governance. Messaging settings expose configured-channel controls for guest access, Slack Connect, service principals, default models, and budgets. Daily or monthly organization, requester, and channel budgets are reserved before a run and settled from actual usage. Audit and usage records keep platform, workspace, channel, requester, task, run, source URL, and model lineage.
Optional: app unfurls
Slack app unfurls let an app replace Slack's normal link preview with a richer preview. Clips uses this for playable async screen-recording previews.
Add these extra bot scopes when your app needs unfurls:
links:read— lets Slack notify the app when registered domains are postedlinks:write— lets the app replace Slack's default previewlinks.embed:write— lets the app embed approved media/player URLs
Then subscribe to the link_shared event and register your public app domains
under App Unfurl Domains. For Clips-only playable previews, set the Slack
Event Subscriptions Request URL to:
https://your-clips.example.com/api/slack/unfurlA Slack app has one Events API Request URL. If the same Slack app should handle
both agent chat events and Clips unfurls, route Slack events through a small
dispatcher that sends message events to /_agent-native/integrations/slack/webhook
and link_shared events to the Clips unfurl handler.
Tips
- Channel mentions — use an @mention to start work. Each channel turn must explicitly mention the agent; ordinary thread replies and general channel chatter do not invoke it.
- DMs — accepted personal DMs are private conversations and require a verified organization member or linked Slack identity.
- Identity — personal DMs require a verified Agent-Native organization member or an already linked Slack identity. Configured channels use a separate service principal, policy, and budget.
- Production allowlists — set
SLACK_ALLOWED_TEAM_IDSand, for shared Slack apps,SLACK_ALLOWED_API_APP_IDSso a valid signing secret cannot be reused by an unexpected workspace. - Clips app unfurls — Clips can share the managed Slack app credentials, but a Slack app has only one Events API Request URL; route
link_sharedto Clips when chat and unfurls share an app.
Want to act on other tools from a Slack message?
See Messaging Recipes — @mention in Slack → row in Notion for the full worked example: wiring the Notion provider API, storing the credential in the vault, and asking your agent to write the action.
Set up Microsoft Teams
The built-in Teams adapter uses the Bot Framework activity endpoint. Incoming
JWTs are validated with Microsoft's botframework-connector, including issuer,
audience, signed service URL, and Teams channel endorsement checks.
Create a Microsoft Entra app registration and Azure Bot resource.
Configure:
MICROSOFT_TEAMS_APP_IDMICROSOFT_TEAMS_APP_PASSWORDMICROSOFT_TEAMS_APP_TENANT_IDfor a single-tenant registrationMICROSOFT_TEAMS_ALLOWED_TENANT_IDSas a comma-separated production allowlist
Set the Azure Bot messaging endpoint to:
https://your-app.example.com/_agent-native/integrations/microsoft-teams/webhookAdd the Microsoft Teams channel to the bot and install it in an allowlisted tenant.
Replies use the signed serviceUrl, conversation ID, and activity ID from the
inbound activity. Proactive sends without an inbound conversation reference are
not currently supported.
Set up Discord interactions
Discord supports HTTP interactions and persistent Gateway events. The built-in adapter implements HTTP interactions only: slash commands are verified with Discord's Ed25519 signature, acknowledged with a deferred type-5 response, and completed by editing the original interaction response. It does not claim to receive ordinary server messages or DMs.
Create a Discord application and configure:
DISCORD_APPLICATION_IDDISCORD_PUBLIC_KEY
Set Interactions Endpoint URL to:
https://your-app.example.com/_agent-native/integrations/discord/webhookRegister a chat-input command with a string prompt option and install the command for the intended server or users.
Discord requires the initial response within 3 seconds. Interaction tokens are valid for 15 minutes and are stored only in the active queue payload; terminal queue rows erase that payload.
Set up Telegram
What you'll need
- The Telegram app on your phone
- About 3 minutes
Steps
Open Telegram and message @BotFather.
Send
/newbotand follow the prompts to name your bot. BotFather will reply with an HTTP API token. Copy it.In your app's environment variables, set:
TELEGRAM_BOT_TOKEN— the token from BotFatherTELEGRAM_WEBHOOK_SECRET— a random secret used to authenticate webhook deliveries
After deploying, register the webhook by
POSTing to your app at:POST https://your-app.example.com/_agent-native/integrations/telegram/setupThis tells Telegram to send messages to your app's webhook. You only need to do this once per deployment.
Find your bot in Telegram (search for the username BotFather gave you) and send it a message.
Telegram forum topics and private-chat topics keep message_thread_id in the
canonical conversation identity. Replies preserve both the topic and the
inbound message through Bot API reply_parameters.
Set up Email
Email is the most powerful integration — your agent gets its own address, replies in-thread, can be CC'd on conversations, and uses the sender's email as their identity. No /link command needed.
What you'll need
- A domain you control (or you can use a free Resend subdomain — see below)
- An account with Resend or SendGrid to handle inbound + outbound mail
- About 10 minutes
Steps (with Resend — easiest)
Sign up at resend.com. The free tier is enough to get started.
Pick how the agent's email address will look:
- Easiest: use a free
<your-slug>.resend.appaddress — no DNS needed. - Branded: add a custom domain (like
yourcompany.com) in Resend's Domains page and follow the DNS steps.
- Easiest: use a free
In Resend, open Webhooks → Add Endpoint and point it at:
https://your-app.example.com/_agent-native/integrations/email/webhookSubscribe to the
email.receivedevent. Resend will give you a signing secret — copy it.In your app's environment variables, set:
EMAIL_AGENT_ADDRESS— the address the agent receives mail at (e.g.agent@yourcompany.com)RESEND_API_KEY— your Resend API keyEMAIL_INBOUND_WEBHOOK_SECRET— the signing secret from Resend (recommended; used for signature verification)
Send an email to the agent's address. It'll reply in the same thread.
Steps (with SendGrid)
Sign up at sendgrid.com.
Add the MX record for your domain so inbound mail flows to SendGrid:
MX yourcompany.com → mx.sendgrid.net (priority 10)Open Settings → Inbound Parse, click Add Host & URL, and set the destination to:
https://your-app.example.com/_agent-native/integrations/email/webhookSet environment variables:
EMAIL_AGENT_ADDRESS— the address the agent receives atSENDGRID_API_KEY— your SendGrid API keyEMAIL_INBOUND_WEBHOOK_SECRET— optional Svix signing secret if you've configured signed webhooks
Send an email to the agent's address.
Tips
- CC the agent to bring it into a thread. When the agent is CC'd it will reply-all so the whole thread sees the response.
- Threading just works — the agent uses standard
Message-ID/In-Reply-To/Referencesheaders, so replies stay in the right thread in any email client. - Identity is the sender's email. If
alice@acme.comemails the agent, that is her identity — no link or signup flow. - Rich responses — markdown in the agent's response is rendered as HTML in the email.
- Allowed domains — restrict who can email the agent by setting
allowedDomainsin the integration's config; messages from other domains are dropped. - Rate limit — 20 inbound messages per hour per sender.
Set up WhatsApp
What you'll need
- A Meta (Facebook) developer account
- A phone number you can dedicate to the bot
- About 15 minutes (Meta's setup has the most steps)
Steps
Go to the Meta Developer Portal, click Create App, and pick the Business type.
Add the WhatsApp product to your app and configure a phone number to use as the sender.
From the WhatsApp setup page, grab:
- Access token (the temporary one is fine for testing; generate a permanent token before going live)
- Phone number ID
Pick any random string to use as a verify token — you'll enter the same value in two places below.
In your app's environment variables, set:
WHATSAPP_ACCESS_TOKEN— your access tokenWHATSAPP_PHONE_NUMBER_ID— the phone number IDWHATSAPP_VERIFY_TOKEN— the random string you pickedWHATSAPP_APP_SECRET— the Meta app secret used to verify webhook HMAC signatures
Back in Meta's WhatsApp config, open the webhook section and set:
Callback URL: https://your-app.example.com/_agent-native/integrations/whatsapp/webhook Verify token: the same random string you set as WHATSAPP_VERIFY_TOKENSubscribe to the
messagesfield.Send a WhatsApp message to the bot's phone number.
Replies quote the inbound WhatsApp message using its wamid when available.
Use Dispatch as your agent's central inbox
If you're running multiple agent-native apps (mail, calendar, analytics, etc.), the recommended pattern is to set up messaging on Dispatch (see also the template reference) and let it route work to your domain apps over A2A.
Why this is nice:
- One agent, one inbox. All your channels (Slack, email, Telegram, WhatsApp) flow into Dispatch. You only set up integrations once.
- Dispatch delegates. Ask "summarize last week's signups" — Dispatch calls the analytics agent. Ask "draft a reply to Alice" — Dispatch calls the mail agent.
- Clicks, not config. Dispatch's Admin → Messaging page has connect buttons for every platform with the env-var fields built in.
If you don't need an orchestrator, any single template can wire up messaging directly using the env vars on this page.
Reference
The webhook routes and environment variables below apply across every platform. For the technical internals — the inbound webhook lifecycle, the integrations plugin, threading and identity, per-platform security, proactive sends, and writing a custom adapter — see Messaging Internals.
Webhook URLs
/_agent-native/integrations/slack/webhook
/_agent-native/integrations/microsoft-teams/webhook
/_agent-native/integrations/discord/webhook
/_agent-native/integrations/telegram/webhook
/_agent-native/integrations/whatsapp/webhook
/_agent-native/integrations/email/webhookTelegram also exposes a one-time setup endpoint:
POST /_agent-native/integrations/telegram/setupEnvironment variables
| Platform | Required | Optional |
|---|---|---|
| Slack | SLACK_SIGNING_SECRET, plus either SLACK_CLIENT_ID+SLACK_CLIENT_SECRET (managed OAuth, recommended) or SLACK_BOT_TOKEN (legacy single-workspace) |
SLACK_ALLOWED_TEAM_IDS, SLACK_ALLOWED_API_APP_IDS |
| Microsoft Teams | MICROSOFT_TEAMS_APP_ID, MICROSOFT_TEAMS_APP_PASSWORD, MICROSOFT_TEAMS_ALLOWED_TENANT_IDS |
MICROSOFT_TEAMS_APP_TENANT_ID |
| Discord | DISCORD_APPLICATION_ID, DISCORD_PUBLIC_KEY |
— |
| Telegram | TELEGRAM_BOT_TOKEN, TELEGRAM_WEBHOOK_SECRET |
— |
EMAIL_AGENT_ADDRESS, plus one of RESEND_API_KEY or SENDGRID_API_KEY |
EMAIL_INBOUND_WEBHOOK_SECRET |
|
WHATSAPP_ACCESS_TOKEN, WHATSAPP_VERIFY_TOKEN, WHATSAPP_PHONE_NUMBER_ID, WHATSAPP_APP_SECRET |
— |
For Slack, SLACK_BOT_TOKEN, SLACK_CLIENT_ID, and SLACK_CLIENT_SECRET are each individually optional at the adapter level — only SLACK_SIGNING_SECRET is unconditionally required — because either credential set satisfies setup. Use managed OAuth (SLACK_CLIENT_ID/SLACK_CLIENT_SECRET) for Dispatch and multi-workspace apps; SLACK_BOT_TOKEN is the compatibility path for a single-workspace deployment installed by hand. See Set up Slack above for both flows.
Integration credentials resolve from the integration owner's scoped secrets first (user, org, then workspace), with deployment env vars available as a local or deliberate single-tenant fallback. The setup UI saves scoped secrets; use deployment configuration only when you intentionally want one shared integration identity. Values are never returned to the browser or stored in source code.
The built-in runtime adapters are Slack, Microsoft Teams, Discord interactions, Telegram, WhatsApp Cloud API, and provider-webhook email (Resend or SendGrid). Discord support is interaction-only; ordinary Discord message ingestion is not included.
What's next
- Messaging Recipes — the full @mention-in-Slack-to-Notion-row worked example
- Messaging Internals — the webhook lifecycle, custom adapters, and security internals
- Dispatch — concept overview for using a central inbox across apps
- Dispatch template reference — recommended central inbox for multi-app workspaces
- A2A Protocol — how Dispatch delegates work to other agents, including continuation recovery
- Workflow Connectors — pre-configured n8n/Zapier-style workflow invocation, distinct from a chat platform integration
- Security — credential scoping and the webhook signature-verification model
- Agent Mentions —
@-mentioning agents inside the web chat