A router between IM and your agent team.
Agent Router connects instant messaging channels such as Slack and QQ to your agent team: Codex, Claude Code, Kimi, and other agent runtimes that can be exposed through executor adapters. Users can talk to those agents from the chat tools they already use, while Agent Router owns channel integration, session routing, executor switching, and reply delivery.
Agent Router is still in active development. Configuration, commands, backend protocols, channel behavior, and supported agent adapters may change before the project is considered stable. It is currently best suited for experiments, internal workflows, and early integrations.
- Receives messages from supported IM channels.
- Normalizes channel messages into a shared session model.
- Starts each session with a configured default agent.
- Routes a session to at most one active agent at a time.
- Lets users switch agents inside the same chat session.
- Projects conversation context when a session switches agents.
- Sends normalized replies back to the originating channel.
Channels:
- Slack Socket Mode
- Tencent QQ Official Bot Gateway
- Local browser web chat
Planned/supporting implementation targets:
- Telegram Bot API long polling with topic-aware sessions (design)
Agent integrations:
- Kimi through ACP, for example
kimi acp - Codex through app-server
- Claude Code through stream-json stdio
Other agents can be added through executor adapters as their protocol integrations land.
User commands:
/agent status
/agent <agent-name>
/agent auto
/new
/stop
For example:
/agent kimi
/agent codex
Requirements:
- Rust toolchain
- Node.js and npm when rebuilding the bundled web UI
- Credentials or local config for at least one supported channel
- At least one configured agent command available on
PATH
Run with the example configuration:
cargo run -- --config config/agent-router.example.yamlFor local changes, copy the example configuration and edit the agent names, commands, and channel options:
cp config/agent-router.example.yaml config/agent-router.yaml
cargo run -- --config config/agent-router.yamlPrefer environment variables for secrets. The runner also tries these dotenv locations, in order, so a local Hermes install can be reused without copying tokens into this repository:
.env../.env$HERMES_HOME/.env~/.hermes/.env
Slack:
SLACK_BOT_TOKEN=xoxb-...
SLACK_APP_TOKEN=xapp-...
# Optional: gate non-owner Slack requests behind owner approval.
SLACK_OWNER_USER_IDS=U123,U456Slack app setup:
In the Slack app settings, enable Socket Mode and create an app-level token for
SLACK_APP_TOKEN with:
connections:write
Enable Interactivity & Shortcuts so approval prompts can use Approve/Deny buttons. With Socket Mode enabled, Slack delivers interaction payloads over the WebSocket connection, so no public Request URL is required.
In OAuth & Permissions, add these Bot Token Scopes:
chat:write
im:write
app_mentions:read
channels:history
groups:history
im:history
mpim:history
users:read
files:read
files:write
Then enable Event Subscriptions and subscribe to these bot events:
app_mention
message.channels
message.groups
message.im
message.mpim
Reinstall the Slack app after changing scopes or event subscriptions.
Approval prompts include /approve and /deny text commands as fallback and
audit text. Use those commands if Block Kit buttons are unavailable.
QQ:
QQ_APP_ID=...
QQ_CLIENT_SECRET=...
QQ_SANDBOX=falseSlack, Telegram, and QQ are enabled automatically when all required credentials
for that channel are present, unless the config explicitly sets enabled: false.
When an executor reports safe tool-call or progress updates, Agent
Router streams those updates back to the originating channel while the turn is
still running, before the final assistant reply.
QQ access can be restricted with comma-separated openid lists:
QQ_ALLOWED_USERS=...
QQ_ALLOWED_GROUPS=...Telegram:
TELEGRAM_BOT_TOKEN=123456:...
TELEGRAM_REQUIRE_MENTION=trueTelegram support is designed around Bot API long polling and forum topic isolation. See the Telegram Topic Mode workflow.
Web chat:
npm --prefix web install
npm --prefix web run build
WEB_ENABLED=true cargo run -- --config config/agent-router.example.yamlThe Rust build embeds web/dist into the binary. Rebuild the frontend before
packaging a release binary; if web/dist is missing, the binary embeds a small
placeholder page. Set web.static_dir or WEB_STATIC_DIR for local debugging;
that switches the web channel to runtime static files instead of embedded
assets. WEB_AUTH_TOKEN is required when WEB_BIND uses a non-loopback
address.
The example config defines a default agent, available agent backends, and channel options:
router:
default_executor: kimi
executors:
kimi:
protocol: acp
command: kimi
args: ["acp"]
codex:
protocol: app_server
command: codex
pi:
protocol: pi_rpc
command: pi
provider: openai
model: gpt-5.1-codex
thinking_effort: high
slack:
require_mention: true
owner_user_ids: []
allowed_channels: []
free_response_channels: []
qq:
sandbox: false
allowed_users: []
allowed_groups: []
telegram:
require_mention: true
allowed_users: []
allowed_chats: []
poll_timeout_secs: 30
web:
enabled: false
bind: 127.0.0.1:8787
# Omit static_dir to serve embedded assets; set it to use runtime files.
# static_dir: web/dist
channel_events: compactEach chat session has at most one active agent. New sessions use
router.default_executor, or start auto-pending when an orchestrator is enabled.
Users can switch the active agent with /agent <agent-name>.
Optional routing can be enabled with router.orchestrator. The default
mode: initial starts new sessions as auto-pending, asks the routing executor
for one strict JSON decision, and then keeps the selected real executor until
the user switches it or runs /agent auto. mode: per_turn asks the routing
executor before every normal user message while routing mode is auto. The
routing prompt includes low-sensitivity session source metadata (source and
source_kind), such as Slack DM or QQ group, without exposing the full channel
session key.
- Replacing Hermes, OpenClaw, Codex, Claude Code, Kimi, or other agent runtimes.
- Importing a channel adapter wholesale as a runtime dependency.
- Building a full customer-support inbox product.
- Coupling channel adapters to LLM provider, memory, tool, or orchestration implementations.
- Architecture
- Session Executor Routing Workflow
- Remote Machines, Workspaces, and Skill Collection
- Slack User Token Proxy Workflow
- Telegram Topic Mode Workflow
- ADR 0001: Split Channel Router From Agent Runtime
- ADR 0002: Use ACP as the First Backend Protocol
- ADR 0003: Default Executor, Active Executor, and Shared Context
- ADR 0004: Make Machine a First-Class Execution Resource