Agent Bindings: Route Channel Messages to the Right OpenClaw Agent

Learn how agent bindings route channel messages to specific OpenClaw agents based on account, peer, guild, or roles. Ideal for teams needing consistent traffic division across multiple agents.

Read this when

  • Routing channel accounts to different agents
  • Sending one conversation to a specialized agent
  • Deciding whether one agent is sufficient

When a message shows up on a channel, OpenClaw must pick which agent handles it. In the default case, that choice is simple: the agent designated as default: true receives everything. An agent binding overrides that selection for a portion of your traffic. Each binding specifies an agentId and matches channel attributes like the account, peer, guild, team, or Discord roles, and the agent that matches owns the resulting session.

Bindings only determine the agent. They do not set up channel accounts, nor do they grant permissions. A binding is only checked after the channel has already admitted the message through its usual pairing, allowlist, and account rules.

When to use a binding

If all conversations can share a single workspace, one model policy, and a common session boundary, bindings are unnecessary. The default agent handles everything. Use bindings when you need a consistent division, such as:

  • a separate channel account for each agent
  • a support inbox directed to a support workspace
  • a single direct message or group assigned to a specialist
  • a guild, team, or Discord role handled differently from the rest of an account

Set up the channel account first, then attach the binding. A binding that points to an account the channel never accepts will have no effect.

Route an account to an agent

This example keeps main as the fallback and sends the Discord account named support to its own dedicated agent and workspace:

{
  agents: {
    entries: {
      main: {
        default: true,
        workspace: "~/.openclaw/workspace",
      },
      support: {
        workspace: "~/.openclaw/workspace-support",
      },
    },
  },
  bindings: [
    {
      agentId: "support",
      comment: "Route the support bot account to the support agent",
      match: {
        channel: "discord",
        accountId: "support",
      },
    },
  ],
}

Messages arriving on the support account now go to agentId: "support". All other Discord accounts and every other channel continue using main unless another binding matches.

Routing configuration is loaded at startup, so restart the Gateway, then check the roster and channel accounts:

openclaw agents list --bindings
openclaw channels status --probe

Match a specific conversation

Add match.peer when only one direct message, group, or channel should reach the specialized agent:

{
  bindings: [
    {
      agentId: "support",
      match: {
        channel: "discord",
        accountId: "default",
        peer: {
          kind: "channel",
          id: "123456789012345678",
        },
      },
    },
  ],
}

peer.kind accepts direct, group, or channel. Use the channel's canonical peer ID, not a display name.

Match fields and precedence

Every binding requires agentId and match.channel. The optional route-match fields are:

  • accountId: one configured account. Leaving it out matches only the channel's default account; "*" is an explicit channel-wide fallback.
  • peer: a concrete or wildcard direct, group, or channel peer
  • guildId and teamId: channel-specific group-space constraints
  • roles: Discord role IDs, evaluated together with the guild constraint
  • session.dmScope: an optional session-scoping override for matched direct messages
  • session.groupScope: an optional main or per-group override for matched groups and channels

Precedence follows specificity: concrete conversation and group-space matches beat account and channel fallbacks. Within the same tier, the first binding in config order wins, so place narrow rules before broad ones when they share a tier.

Top-level bindings also accepts type: "acp" entries for persistent ACP conversations. Those need a concrete match.peer.id and follow the ACP conversation identity contract rather than normal route precedence. See ACP agents if that is what you need.

Common mistakes

Omitting accountId to mean every account

An omitted accountId matches only the channel's default account. For a channel-wide fallback, state it explicitly with accountId: "*".

Binding to an unknown agent

The agentId must exist under agents.entries, and exactly one entry should be marked default: true. A binding that references a missing agent silently misroutes.

Treating bindings as access control

Bindings pick an agent for messages that were already admitted. Pairing, dmPolicy, group policy, and allowlists are separate controls. Configure them independently.

663 words · updated Aug 22, 2026