Features
Slack agents
A Slack app that answers with a model.
A Slack agent connects your own Slack app to RouterPlus. People mention the app in a channel or send it a direct message. RouterPlus answers in the same thread, with the model you select.
Each agent has its own RouterPlus inference key. Every answer is an ordinary request on that key. Your guardrails, budgets, routing and billing apply.
Set up an agent
- 01Create a Slack app at api.slack.com/apps:
- Select "From scratch" and install the app in your workspace.
- Copy the bot token (
xoxb-...) from "OAuth & Permissions". - Copy the signing secret from "Basic Information".
- 02Create the agent with a management key (
Authorization: Bearer tm_mk_...):
POST /v1/slack/agents{
"slug": "helpdesk",
"bot_token": "xoxb-...",
"signing_secret": "8f74...",
"model": "gpt-6-luna",
"system_prompt": "You answer questions about our product.",
"allowed_channel_ids": ["C0123ABCD"],
"allowed_user_ids": [],
"tools": { "server": [{ "type": "web_fetch" }], "mcp_servers": ["docs"] },
"max_cost_usd_per_day": 10
}- 03Get the app manifest:
GET /v1/slack/agents/{id}/manifest- 04In your Slack app, open "App Manifest", paste the manifest and save. Slack checks the events URL. When Slack asks, install the app again to give it the new scopes.
- 05Invite the app to a channel (
/invite @helpdesk). Mention it, or send it a direct message.
POST returns 201 with the agent. Slack sends events to the agent's events_url: https://<gateway>/v1/slack/events/{id}.
Fields
| Field | Rule |
|---|---|
slug | Required. 1 to 40 of a-z, 0-9 and -, starting with a letter or digit. Unique in your org. |
bot_token | Required. The bot token, xoxb-.... Stored encrypted. Never returned. |
signing_secret | Required. The app's signing secret. Stored encrypted. Never returned. |
model | Required. A model id, a preset (@preset/<slug>) or routerplus/auto. |
system_prompt | Optional. Up to 8,000 characters. |
allowed_channel_ids | Optional. Channel ids where the agent answers. Empty (the default) means every channel that the app is in. This list does not limit direct messages. |
allowed_user_ids | Optional. User ids that the agent answers, in channels and in direct messages. Empty (the default) means anyone in the workspace. |
tools.server | Optional. Server tools: { "type": "web_fetch" } with optional allowed_domains, max_bytes and max_calls, and { "type": "advisor", "model": "..." }. Not with routerplus/auto. See Server tools. |
tools.mcp_servers | Optional. Slugs of your MCP servers. The agent calls them through the MCP gateway with its own key, so their tool policies apply. |
max_cost_usd_per_day | Optional. The most that the agent's key spends in one UTC day. null (the default) means no daily limit. |
workspace_id, principal_id | Optional, on create only. The workspace and principal of the agent's key. Default: your default workspace. |
slack_team_id, slack_app_id | Optional. When set, the agent ignores events from another Slack workspace or app. |
enabled | Optional. Default true. A disabled agent acknowledges events but does not answer. |
Manage agents
| Route | What it does |
|---|---|
GET /v1/slack/agents | Lists your agents. |
POST /v1/slack/agents | Creates an agent and its key. |
GET /v1/slack/agents/{id} | Reads one agent. |
PATCH /v1/slack/agents/{id} | Changes the fields you send. Send bot_token or signing_secret to rotate it. |
DELETE /v1/slack/agents/{id} | Deletes the agent and its thread memory, and disables its key. |
GET /v1/slack/agents/{id}/manifest | The Slack app manifest for the agent. |
- Every route also works under
/api/v1. - Each change writes a row to the audit log (
GET /v1/audit). - Responses show
has_bot_tokenandhas_signing_secret, never the values. - The agent's key is a normal inference key with the name
slack:<slug>. It shows inGET /v1/keysand in activity. To stop all spend immediately, disable the key or the agent.
Scopes and events
The manifest asks for these bot scopes:
| Scope | Use |
|---|---|
app_mentions:read | Receive mentions of the app. |
chat:write | Post answers. |
im:history, im:read, im:write | Receive and answer direct messages. |
channels:history | Read messages in threads of public channels. |
It subscribes to two bot events: app_mention and message.im.
How the agent answers
- A mention in a channel gets an answer in the thread of that message.
- A direct message gets an answer in the direct message. Direct messages outside a thread are one conversation.
- The agent does not answer bots (itself included), edits, deletions, or people who are not on the allow lists.
- RouterPlus removes the app mention from the text before the model sees it.
- The model sees the system prompt, the thread's earlier messages (up to 30), and the new message.
- When the agent's key has reached
max_cost_usd_per_daytoday, the agent posts a short notice and does not call the model. - When the model call fails, the agent posts a short message, for example "Sorry, I could not answer that. Try again later."
Security
- RouterPlus checks Slack's signature on every request. The signature is an HMAC-SHA256 of the timestamp and the body, with your signing secret. A request without a valid signature gets
401. - A request with a timestamp more than 5 minutes from now gets
401. Thus nobody can send a captured request again. - Slack sends an event again when it gets no acknowledgement in time. RouterPlus answers each event id one time.
- RouterPlus acknowledges each event immediately and answers in the background.
What is stored
| Data | How long |
|---|---|
| Bot token, signing secret, agent key | Encrypted, until you delete the agent. |
| Thread memory: the last 30 messages of each thread, from people and from the agent | 7 days after the thread's last message, then deleted. |
| Event ids, to answer each event once | 1 day. |
RouterPlus keeps the model requests like any other request on your key. See Data policy.
For agents: /docs/slack-agents.md and /llms.txt