Quick Start
Send one VIP user to a dedicated agent
Add a
bindings: entry with peer: set to the user’s Telegram numeric id. The VIP agent handles that user; everyone else still goes to general.Mix peer, role, channel, and chat-type
Stack multiple bindings — the most specific rule wins automatically.A user with id
12345678 always gets vip. A support-role member who DMs the bot gets support (role beats chat type). The ops channel routes to the ops agent. All other DMs go to assistant. Everything else falls back to general.How It Works
The gateway resolves the target agent in four deterministic steps:| Step | What the gateway does |
|---|---|
| 1 | Extracts peer, roles, channel_id, account, chat_type from the inbound message |
| 2 | Tries every bindings: rule, keeps only the ones that match |
| 3 | Sorts surviving matches: higher priority wins, then higher specificity, then declaration order |
| 4 | If no binding matches, falls back to routes[chat_type], then routes["default"], then the literal agent id "default" |
Routes vs Bindings
Configuration Options
Each entry in thebindings: list is a RouteBinding:
| Field | Type | Default | Description |
|---|---|---|---|
agent | str | required | Agent id to route to when this binding matches |
chat_type | Optional[str] | None | "dm" | "group" | "channel" |
peer | Optional[str] | None | Sender/user id (most specific) |
role | Optional[str] | None | Role / guild-role membership of the sender |
channel_id | Optional[str] | None | Specific chat/channel id |
account | Optional[str] | None | Receiving bot account (multi-account channels) |
priority | int | 0 | Higher wins; ties broken by specificity then declaration order |
None conditions in a binding must match the inbound message for that binding to apply. A binding with no conditions always matches.
Specificity weights — when two bindings both match, the one with the higher total specificity wins:
| Field | Specificity weight |
|---|---|
peer | 16 (most specific) |
role | 8 |
channel_id | 8 |
account | 4 |
chat_type | 2 |
(priority, specificity) are broken by declaration order — the first matching binding in your list wins.
Common Patterns
priority
incident_responder binding has priority: 100 so it wins over the peer match for user 12345678, even though peer has higher specificity. Use this for incident-mode overrides.
Best Practices
Always declare a default in routes:
Always declare a default in routes:
Bindings are evaluated first, but
routes.default is the safety net when nothing matches. Without it, unmatched messages silently go to an agent named "default" — which may not exist.Prefer specificity over priority
Prefer specificity over priority
Let the resolver pick by specificity —
peer beats role beats channel_id beats account beats chat_type. Reach for priority only when you genuinely need to override, such as an incident-mode binding that must win regardless of user identity.Use stable peer and channel ids
Use stable peer and channel ids
Telegram numeric ids and Discord channel ids are stable. Display names and usernames change. Use the numeric id from the platform — never a username or handle.
Keep bindings short and reviewable
Keep bindings short and reviewable
If your list grows past ~10 entries, consider grouping users by role at the platform level and binding on
role instead of individual peer ids. A long list of peer bindings is hard to audit and easy to break.Related
Bot Message Routing
The simpler chat-type routing surface — route by dm, group, or channel.
Multi-Channel Bots
Run one bot per role on the same platform using multiple channel entries.

