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 @mention it 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.
Many channels, one agent
Slack
Microsoft Teams
Discord interactions
Email
Telegram
WhatsApp
One agent loopsame memory · same tools
One SQL thread history
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.

  1. 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 current agent_view experience 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 public icon-512.svg as the source and convert it to a Slack-supported upload format if needed.

  2. 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.email
  3. Add this OAuth Redirect URL:

    https://your-app.example.com/_agent-native/integrations/slack/oauth/callback
  4. Turn on Event Subscriptions, set the Request URL, and subscribe to app_home_opened, app_context_changed, app_mention, and message.im:

    https://your-app.example.com/_agent-native/integrations/slack/webhook
  5. Turn on Interactivity & Shortcuts and set its Request URL:

    https://your-app.example.com/_agent-native/integrations/slack/interactions
  6. Configure SLACK_CLIENT_ID, SLACK_CLIENT_SECRET, and SLACK_SIGNING_SECRET on your app. Then open Admin → Messaging and click Add to Slack. Only an organization owner or admin can create a shared workspace install.

  7. 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:write enables Agent View context events; chat:write powers 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 posted
  • links:write — lets the app replace Slack's default preview
  • links.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/unfurl

A 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_IDS and, for shared Slack apps, SLACK_ALLOWED_API_APP_IDS so 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_shared to 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.

  1. Create a Microsoft Entra app registration and Azure Bot resource.

  2. Configure:

    • MICROSOFT_TEAMS_APP_ID
    • MICROSOFT_TEAMS_APP_PASSWORD
    • MICROSOFT_TEAMS_APP_TENANT_ID for a single-tenant registration
    • MICROSOFT_TEAMS_ALLOWED_TENANT_IDS as a comma-separated production allowlist
  3. Set the Azure Bot messaging endpoint to:

    https://your-app.example.com/_agent-native/integrations/microsoft-teams/webhook
  4. Add 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.

  1. Create a Discord application and configure:

    • DISCORD_APPLICATION_ID
    • DISCORD_PUBLIC_KEY
  2. Set Interactions Endpoint URL to:

    https://your-app.example.com/_agent-native/integrations/discord/webhook
  3. Register 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

  1. Open Telegram and message @BotFather.

  2. Send /newbot and follow the prompts to name your bot. BotFather will reply with an HTTP API token. Copy it.

  3. In your app's environment variables, set:

    • TELEGRAM_BOT_TOKEN — the token from BotFather
    • TELEGRAM_WEBHOOK_SECRET — a random secret used to authenticate webhook deliveries
  4. After deploying, register the webhook by POSTing to your app at:

    POST https://your-app.example.com/_agent-native/integrations/telegram/setup

    This tells Telegram to send messages to your app's webhook. You only need to do this once per deployment.

  5. 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)

  1. Sign up at resend.com. The free tier is enough to get started.

  2. Pick how the agent's email address will look:

    • Easiest: use a free <your-slug>.resend.app address — no DNS needed.
    • Branded: add a custom domain (like yourcompany.com) in Resend's Domains page and follow the DNS steps.
  3. In Resend, open Webhooks → Add Endpoint and point it at:

    https://your-app.example.com/_agent-native/integrations/email/webhook

    Subscribe to the email.received event. Resend will give you a signing secret — copy it.

  4. 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 key
    • EMAIL_INBOUND_WEBHOOK_SECRET — the signing secret from Resend (recommended; used for signature verification)
  5. Send an email to the agent's address. It'll reply in the same thread.

Steps (with SendGrid)

  1. Sign up at sendgrid.com.

  2. Add the MX record for your domain so inbound mail flows to SendGrid:

    MX  yourcompany.com  →  mx.sendgrid.net  (priority 10)
  3. Open Settings → Inbound Parse, click Add Host & URL, and set the destination to:

    https://your-app.example.com/_agent-native/integrations/email/webhook
  4. Set environment variables:

    • EMAIL_AGENT_ADDRESS — the address the agent receives at
    • SENDGRID_API_KEY — your SendGrid API key
    • EMAIL_INBOUND_WEBHOOK_SECRET — optional Svix signing secret if you've configured signed webhooks
  5. 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 / References headers, so replies stay in the right thread in any email client.
  • Identity is the sender's email. If alice@acme.com emails 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 allowedDomains in 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

  1. Go to the Meta Developer Portal, click Create App, and pick the Business type.

  2. Add the WhatsApp product to your app and configure a phone number to use as the sender.

  3. 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
  4. Pick any random string to use as a verify token — you'll enter the same value in two places below.

  5. In your app's environment variables, set:

    • WHATSAPP_ACCESS_TOKEN — your access token
    • WHATSAPP_PHONE_NUMBER_ID — the phone number ID
    • WHATSAPP_VERIFY_TOKEN — the random string you picked
    • WHATSAPP_APP_SECRET — the Meta app secret used to verify webhook HMAC signatures
  6. 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_TOKEN

    Subscribe to the messages field.

  7. 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/webhook

Telegram also exposes a one-time setup endpoint:

POST /_agent-native/integrations/telegram/setup

Environment 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 EMAIL_AGENT_ADDRESS, plus one of RESEND_API_KEY or SENDGRID_API_KEY EMAIL_INBOUND_WEBHOOK_SECRET
WhatsApp 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