Build a Slack bot on an open model

Verified August 26, 2026

An open model can run a Slack bot. This sets one up through OpenRouter: one config file, four commands, and a bot that answers in a thread.

Every model below drives tools well enough to run an agent, which is the one requirement. A model that cannot call tools cannot run a bot at all. Qwen3.8 2.4T A95B leads the set on agentic tool use and is what the config uses. Ling-3.0-flash is the cheapest to run, and MiMo-V2.5-Pro holds the most context.

This takes about five minutes.

What you need

  • A Slack workspace where you can install apps
  • An OpenRouter account

Install the CLI

npm i -g @substructure.ai/cli

Write the config

Save this as subs.toml.

subs.toml
name = "slack-bot"

[llm.openrouter]
type = "openrouter"

[agent.assistant]
llm = "openrouter"
model = "qwen/qwen3.8-2.4t-a95b"
system = "You are a helpful assistant. Reply using Slack mrkdwn."

[agent.assistant.slack]
name = "Assistant"

[remote]
url = "https://api.substructure.ai"

[agent.assistant] declares the agent: its model, its prompt, and what it can reach. The Slack bot is how you talk to it.

That file is the whole project. It names the model, the prompt, and where the bot answers. It holds no keys.

[remote] is the deployment the CLI talks to. subs apply writes the org and the project back under it.

Create the project

subs apply

This creates the project from the file and writes the project id back into it. If you are not signed in yet, the command opens your browser first. Run subs apply again after any edit to the file.

Add your LLM key

subs auth llm.openrouter

The bot calls the model through OpenRouter, so it needs an OpenRouter API key. Create one at openrouter.ai/keys if you do not have one. The command stores the key with your deployment. It never goes in the config file.

Set up the Slack app

subs auth agent.assistant.slack

The command prints an app manifest. Go to api.slack.com/apps, choose Create New App, then From a manifest, and paste it in. Create the app and install it to your workspace.

Slack then shows you two values. Paste them back when the command asks.

  • The Bot User OAuth Token, under OAuth & Permissions.
  • The Signing Secret, under Basic Information.

The bot is live once both are in.

Use it

Invite the bot to a channel and mention it. It replies in the thread. Later mentions in that thread continue the same conversation. DM it and it replies to every message.

Which model to run

Open models with open weights, ranked by how well they drive tools. Prices are per million tokens.

ModelModel IDContext (tokens)InputOutput8-turn thread
Qwen3.8 2.4T A95Bqwen/qwen3.8-2.4t-a95b1,048,576$2.00$6.00about $0.08
Kimi K3moonshotai/kimi-k31,048,576$3.00$15.00about $0.14
DeepSeek V4 Prodeepseek/deepseek-v4-pro-08131,048,576$1.12$3.37about $0.05
GLM 5.2z-ai/glm-5.21,048,576$1.19$3.74about $0.05
MiniMax M3minimax/minimax-m31,048,576$0.30$1.20about $0.01
Inklingthinkingmachines/inkling1,048,576$0.95$4.05about $0.04
Hy3 previewtencent/hy3-preview262,144$0.18$0.60about $0.0077
Nex-N2-Pronex-agi/nex-n2-pro262,144$0.25$1.00about $0.01
MiMo-V2.5-Proxiaomi/mimo-v2.5-pro1,050,000$0.43$0.87about $0.02
Ling-3.0-flashinclusionai/ling-3.0-flash262,144$0.02$0.06about $0.0009

The thread column assumes 8 turns at 4,000 input and 400 output tokens each. Every turn resends the thread, so cost grows with thread length, so start a new thread for a new topic.

ModelParallel tool callsReads imagesReasoning
Qwen3.8 2.4T A95BNoNoAlways on
Kimi K3NoYesOptional
DeepSeek V4 ProNoNoOptional
GLM 5.2YesNoOptional
MiniMax M3NoYesOptional
InklingNoYesOptional
Hy3 previewNoNoOptional
Nex-N2-ProNoYesOptional
MiMo-V2.5-ProNoNoOptional
Ling-3.0-flashNoNoOptional

A model that reads images can answer about a screenshot someone pastes into the thread. Parallel tool calls matter once an agent has several connections and wants to hit them at once.

Swap the model

Change the model line to any id from the table and run subs apply. The rest of the file stays the same.

subs.toml
[agent.assistant]
model = "inclusionai/ling-3.0-flash"

Any model on OpenRouter that supports tool calling works, open weights or not. The table is the set worth starting from.

Give it tools

An agent can call MCP servers. Add one and name it on the agent.

subs.toml
[mcp.sentry]
url = "https://mcp.sentry.dev/mcp"

[agent.assistant]
mcp = ["sentry"]
subs auth mcp.sentry
subs apply

The engine authorizes the connection, fetches its tools, and runs every call. Your code never holds a token.

If it does not answer

  • The Slack app has no values yet. Run subs list. An app with nothing set never replies.
  • Bot not invited. Invite it to the channel before you mention it.
  • No API key. Run subs auth llm.openrouter.
  • Model does not call tools. A model with no tool support cannot run an agent. Pick one from the table.
  • Changes not applied. Run subs apply after every edit to the file.
  • Anything else. Run subs doctor to see what the project still needs.

Next steps