Skip to content

Latest commit

 

History

268 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Agent Router

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.

Development Status

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.

What It Does

  • 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.

Supported Today

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

Quick Start

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.yaml

For 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.yaml

Secrets

Prefer 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:

  1. .env
  2. ../.env
  3. $HERMES_HOME/.env
  4. ~/.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,U456

Slack 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=false

Slack, 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=true

Telegram 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.yaml

The 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.

Configuration Overview

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: compact

Each 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.

Non-Goals

  • 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.

Documentation

About

An router between IM and your agent team.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages