# How to Configure the Multi-Channel IM Bot Gateway (QQ, Feishu, WeChat) with Routes and Allowlist

> Configure the multi-channel IM bot gateway for QQ, Feishu, and WeChat in DeepSeek-Reasonix. Use routes and allowlist for precise message routing and access control.

- Repository: [YHH/DeepSeek-Reasonix](https://github.com/esengine/DeepSeek-Reasonix)
- Tags: how-to-guide
- Published: 2026-08-06

---

**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`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/config/config.go)). The `BotConfig` struct defines the relationship between connections, allowlists, and routes:

```go
// 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:

1. **Allowlist validation** (`internal/gateway/gateway.go#L1046`) – Validates if the sender is authorized to interact with the bot.
2. **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:

```go
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`):

```go
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:

```toml
[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"`:

```toml
[[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:

1. **Configuration Loading** – [`internal/config/render.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/config/render.go) writes TOML sections to the user config file, parsing the `[[bot.routes]]` array.
2. **Runtime Initialization** – [`internal/botruntime/runtime.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/botruntime/runtime.go) converts `BotRouteConfig` slices into `bot.RouteConfig` objects, normalizing `tool_approval_mode` values.
3. **Admission and Routing** – [`internal/gateway/gateway.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/gateway/gateway.go) first 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]]` and `connection_id` fields in routes.
- Configuration resides in the global TOML file (e.g., [`reasonix.toml`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/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`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/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.