MAILGENT
Concepts

Slack

Send and receive Slack messages as your agent — one workspace per project

Slack gives your agent a presence in your team's workspace. Connect a workspace once, /invite the bot to the channels you care about, and the agent can post messages, reply in threads, and poll for anything said in those channels.

Slack is in admin preview. It's merged and documented, but only enabled for admin accounts while we finish hardening it.

How It Works

Connect:  POST /v0/slack/connect → install URL → human authorizes in browser
Send:     Agent calls slack.messages.send → Mailgent posts via the bot token
Receive:  Slack events → stored server-side → agent polls with a since cursor

One Slack workspace per identity. The bot only sees channels it has been /invite'd to.

Connecting a Workspace

Two ways, same result:

  1. Console — open console.mailgent.dev → your project → Integrations and click Add to Slack.
  2. APIPOST /v0/slack/connect returns an installUrl (valid 15 minutes). Open it in a browser and authorize the workspace. The connection appears on GET /v0/slack/connection once authorized.

Either way, a human authorizes the install in a browser — the agent never handles the OAuth exchange. After connecting, /invite the bot to each channel it should read or post in.

Inbound Is Store-and-Poll

Messages from channels the bot is in are stored server-side, like a mail inbox. Agents don't need a webhook or a socket — they poll:

GET /v0/slack/messages?since=2026-06-12T09:00:00Z

Keep the timestamp of your last check and pass it as since to fetch only what's new. Reply in-thread by passing the message's ts as threadTs when sending.

Scopes

ScopeAllows
slack:readRead connection status, list channels, poll stored messages
slack:sendConnect/disconnect the workspace, send messages

MCP Tools

ToolScopeDescription
slack_list_channelsslack:readChannels the bot can see, with membership
slack_list_messagesslack:readPoll stored inbound messages (since cursor)
slack_send_messageslack:sendPost a message, optionally in a thread

API Endpoints

MethodPathScopeDescription
GET/v0/slack/connectionslack:readConnection status (never includes the token)
POST/v0/slack/connectslack:sendGet an "Add to Slack" install URL
DELETE/v0/slack/connectionslack:sendDisconnect the workspace
GET/v0/slack/channelsslack:readChannels the bot can see
POST/v0/slack/messagesslack:sendSend a message {channel, text, threadTs?}
GET/v0/slack/messagesslack:readList stored inbound messages (channel, since, limit)

Example: Send a Message

curl -X POST https://api.mailgent.dev/v0/slack/messages \
  -H "Authorization: Bearer mgnt-your-api-key" \
  -H "Content-Type: application/json" \
  -d '{ "channel": "C0123456789", "text": "Deploy finished ✅" }'

Returns { "channel": "C0123456789", "ts": "1718180400.000100" }. Pass that ts as threadTs in a follow-up call to reply in the same thread. If you get not_in_channel, /invite the bot to the channel first.

Example: Poll for New Messages

curl "https://api.mailgent.dev/v0/slack/messages?channel=C0123456789&since=2026-06-12T09:00:00Z&limit=50" \
  -H "Authorization: Bearer mgnt-your-api-key"

Returns stored messages newest first, each with channelId, userId, text, ts, and threadTs.

Security

  • Bot tokens are sealed server-side — encrypted with AES-256-GCM and never returned by any endpoint, including GET /v0/slack/connection.
  • Human-in-the-loop install — the OAuth authorization always happens in a browser; agents only receive an install URL.
  • Channel-scoped by invitation — the bot only sees channels it has been /invite'd to.
  • Audit trail — connects, disconnects, and sends show up in the activity log.

On this page