How to Configure the Multi-Channel IM Bot Gateway (QQ, Feishu, WeChat) with Routes and Allowlist
Configure the multi-channel IM bot gateway in DeepSeek-Reasonix by defining a global [bot.allowlist] for access control and granular [[bot.routes]] to route QQ, Feishu, and WeChat messages to specific workspaces, models, and tool-approval modes.
The esengine/DeepSeek-Reasonix repository provides a single shared Go gateway that handles multiple IM bots simultaneously. Two configuration layers in the TOML file control access and message routing: the allowlist acts as a global gatekeeper, while routes provide fine-grained overrides per connection, chat, or user.
Architecture Overview
The gateway reads the Bot section from the global Reasonix configuration (internal/config/config.go). The BotConfig struct defines the relationship between connections, allowlists, and routes:
// BotConfig – controls the multi‑channel IM bot gateway.
// (source: internal/config/config.go#L34-L53)
type BotConfig struct {
Enabled bool `toml:"enabled"`
Model string `toml:"model"`
ToolApprovalMode string `toml:"tool_approval_mode"`
Allowlist BotAllowlist `toml:"allowlist"` // global access control
Routes []BotRouteConfig `toml:"routes"` // per-message routing
Connections []BotConnectionConfig `toml:"connections"` // individual connections
}
When a message arrives, the gateway performs two sequential checks:
- Allowlist validation (
internal/gateway/gateway.go#L1046) – Validates if the sender is authorized to interact with the bot. - Route evaluation – Iterates through
[[bot.routes]]and applies the first-match-wins rule to determine the effective model, workspace, and approval mode.
Global Allowlist ([bot.allowlist])
The BotAllowlist struct (internal/config/config.go#L94-L104) provides a fallback access control layer for connections without explicit per-connection access rules:
type BotAllowlist struct {
Enabled bool `toml:"enabled"`
AllowAll bool `toml:"allow_all"`
QQUsers []string `toml:"qq_users"`
FeishuUsers []string `toml:"feishu_users"`
WeixinUsers []string `toml:"weixin_users"`
QQAdmins []string `toml:"qq_admins"`
FeishuAdmins []string `toml:"feishu_admins"`
// ...
}
When allow_all is set to false, the gateway checks the sender against the listed users, groups, and admins before consulting any routes.
Message Routes ([[bot.routes]])
Routes are defined by the BotRouteConfig struct (internal/config/config.go#L82-L92):
type BotRouteConfig struct {
ConnectionID string `toml:"connection_id"`
Platform string `toml:"platform"` // qq | feishu | weixin
ChatType string `toml:"chat_type"` // dm | group
ChatID string `toml:"chat_id"`
UserID string `toml:"user_id"`
ThreadID string `toml:"thread_id"`
Model string `toml:"model"`
ToolApprovalMode string `toml:"tool_approval_mode"`
WorkspaceRoot string `toml:"workspace_root"`
}
Empty fields act as wildcards. The runtime converts these configurations in internal/botruntime/runtime.go#L58-L86 into active routing rules used by the gateway.
Practical Configuration Examples
Deny-by-Default with Feishu and QQ
This configuration enables the gateway with a restrictive allowlist and specific routes for different platforms:
[bot]
enabled = true
model = "deepseek-coder-v2"
tool_approval_mode = "ask"
# Global allowlist – deny by default, allow specific users
[bot.allowlist]
enabled = true
allow_all = false
feishu_users = ["ou_12345"] # Feishu user IDs
qq_admins = ["12345678"] # QQ admin QQ numbers
# Route: QQ group messages to dedicated workspace
[[bot.routes]]
connection_id = "qq-main"
platform = "qq"
chat_type = "group"
chat_id = "1234567890"
workspace_root = "/projects/qq-group"
model = "deepseek-coder-v2"
tool_approval_mode = "auto"
# Route: Feishu DM from power-user to high-capacity model
[[bot.routes]]
connection_id = "feishu-main"
platform = "feishu"
chat_type = "dm"
user_id = "ou_99999"
model = "deepseek-coder-v2-max"
tool_approval_mode = "yolo"
# Connection definitions (must match connection_id in routes)
[[bot.connections]]
id = "qq-main"
provider = "qq"
domain = "qq"
label = "QQ Bot"
enabled = true
[[bot.connections]]
id = "feishu-main"
provider = "feishu"
domain = "feishu"
label = "Feishu Bot"
enabled = true
Adding WeChat (Weixin) Routes
Add WeChat-specific routing by specifying platform = "weixin":
[[bot.routes]]
connection_id = "weixin-main"
platform = "weixin"
chat_type = "dm"
user_id = "wx_user_abc"
workspace_root = "/projects/wechat-dev"
model = "deepseek-coder-v2"
tool_approval_mode = "ask"
Ensure the connection_id matches an entry in [[bot.connections]] with provider = "weixin".
How the Gateway Processes Messages
The message handling flow follows three distinct phases:
- Configuration Loading –
internal/config/render.gowrites TOML sections to the user config file, parsing the[[bot.routes]]array. - Runtime Initialization –
internal/botruntime/runtime.goconvertsBotRouteConfigslices intobot.RouteConfigobjects, normalizingtool_approval_modevalues. - Admission and Routing –
internal/gateway/gateway.gofirst validates the sender against the allowlist (line ~1046), then iterates routes in order (line ~745) to find the first match where non-empty fields equal the incoming message attributes.
If a route matches, the gateway overrides the default Model, WorkspaceRoot, and ToolApprovalMode for that specific turn, affecting model selection and tool-approval prompts.
Summary
- [bot.allowlist] provides global access control, rejecting unauthorized users before any routing occurs.
- [[bot.routes]] enables platform-specific overrides for QQ, Feishu, and WeChat, supporting distinct workspaces, models, and approval modes per chat or user.
- First-match-wins logic applies routes in order, with empty fields functioning as wildcards.
- Connection IDs must align between
[[bot.connections]]andconnection_idfields in routes. - Configuration resides in the global TOML file (e.g.,
reasonix.toml), accessible via the Desktop UI under Settings → Bots.
Frequently Asked Questions
What is the difference between allowlist and routes?
The allowlist ([bot.allowlist]) is a security gate that determines whether a user may interact with the bot at all, acting as a fallback when per-connection access controls are absent. routes ([[bot.routes]]) handle message processing after admission, determining which model, workspace, and tool-approval mode apply to a specific conversation. The allowlist runs first; routes execute only if the user passes the allowlist check.
Can I use wildcards in route matching?
Yes. In [[bot.routes]], any empty field acts as a wildcard that matches all values. For example, omitting user_id creates a route that applies to all users within the specified chat_id and platform. The gateway evaluates routes sequentially and applies the first match it encounters.
How do I find the correct connection_id for my IM platform?
The connection_id must match the id field defined in a [[bot.connections]] entry. For example, if you define id = "qq-main" in the connections table, your route must specify connection_id = "qq-main". These connections are typically configured through the Desktop UI or manually in the TOML file under internal/config/config.go structure (BotConnectionConfig at lines 66-86).
What happens if no route matches an incoming message?
If no route matches, the gateway uses the default values defined in the root [bot] section of your configuration, specifically the model, tool_approval_mode, and workspace settings. The message still processes through the allowlist check, but routing defaults to global bot settings rather than customized per-chat behavior.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →