Implementation:Openclaw Openclaw ResolveAgentRoute
| Knowledge Sources | |
|---|---|
| Domains | Agent_Runtime, Routing |
| Last Updated | 2026-02-06 12:00 GMT |
Overview
Concrete function for deterministic agent routing provided by the OpenClaw agent runtime.
Description
resolveAgentRoute accepts a routing input (channel, account, peer, guild, team, and the current configuration) and returns a ResolvedAgentRoute containing the matched agent ID, the derived session key, and a diagnostic matchedBy tag indicating which binding tier produced the match.
The function first normalizes all input tokens (channel, account ID, peer ID, guild ID, team ID) and filters the configured bindings list to those matching the channel and account. It then walks the binding tiers in specificity order: peer, parent peer (thread inheritance), guild, team, account-specific, wildcard-account (channel-level), and finally falls back to the default agent. For each match, it builds the session key via buildAgentSessionKey and the main session key via buildAgentMainSessionKey.
The matchedBy field in the result supports debugging and logging, reporting exactly which tier produced the match (e.g., "binding.peer", "binding.guild", "default").
Usage
Call resolveAgentRoute in any channel adapter or inbound message handler to determine which agent and session should process an incoming message. The returned sessionKey is used to load or create the conversation session, and the agentId determines which agent configuration (model, system prompt, tools) to apply.
Code Reference
Source Location
- Repository: openclaw
- File:
src/routing/resolve-route.ts - Lines: 167-260
Signature
export function resolveAgentRoute(input: ResolveAgentRouteInput): ResolvedAgentRoute
Import
import { resolveAgentRoute } from "../routing/resolve-route.js";
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
cfg |
OpenClawConfig |
Yes | The current OpenClaw configuration containing agent definitions and binding rules. |
channel |
string |
Yes | The messaging channel identifier (e.g., "telegram", "discord", "whatsapp").
|
accountId |
null | No | Provider account ID for multi-account setups. Defaults to DEFAULT_ACCOUNT_ID when absent.
|
peer |
null | No | The peer (chat/group/channel) sending the message. Contains kind ("dm", "group", "channel") and id.
|
parentPeer |
null | No | Parent peer for threads/topics, used for binding inheritance when the direct peer does not match. |
guildId |
null | No | Discord guild ID or equivalent organizational unit. |
teamId |
null | No | Slack team ID or equivalent workspace unit. |
The RoutePeer type:
export type RoutePeer = {
kind: RoutePeerKind; // "dm" | "group" | "channel"
id: string;
};
Outputs
| Name | Type | Description |
|---|---|---|
agentId |
string |
The resolved agent ID that should handle this message. |
channel |
string |
The normalized channel identifier. |
accountId |
string |
The resolved account ID (may be DEFAULT_ACCOUNT_ID).
|
sessionKey |
string |
The derived session key for persistence and concurrency control. |
mainSessionKey |
string |
Convenience alias for DM session collapse. |
matchedBy |
"binding.peer.parent" | "binding.guild" | "binding.team" | "binding.account" | "binding.channel" | "default" | Diagnostic tag indicating which binding tier matched. |
Usage Examples
Basic Usage
import { resolveAgentRoute } from "../routing/resolve-route.js";
import { loadConfig } from "../config/config.js";
const cfg = loadConfig();
const route = resolveAgentRoute({
cfg,
channel: "telegram",
accountId: null,
peer: { kind: "group", id: "-1001234567890" },
parentPeer: null,
guildId: null,
teamId: null,
});
console.log(route.agentId); // e.g., "support-bot"
console.log(route.sessionKey); // e.g., "agent:support-bot:telegram:group:-1001234567890"
console.log(route.matchedBy); // e.g., "binding.peer"