openclaw - ✅(Solved) Fix [Bug]: Multi-agent routing resolves correct agent but session is created under default agent [1 pull requests, 4 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#58546Fetched 2026-04-08 02:01:12
View on GitHub
Comments
4
Participants
2
Timeline
11
Reactions
0
Author
Timeline (top)
commented ×3referenced ×3labeled ×2closed ×1

When using multiple Telegram accounts with per-agent bindings, resolveAgentRoute correctly identifies the target agent, but the session key is built using the default agent (main) instead of the resolved agent. This causes the non-default agent to load the wrong workspace, wrong identity files, and wrong session store.

Root Cause

The routing subsystem (resolveAgentRoute) works correctly — it matches the binding and identifies second-ana. But somewhere between route resolution and session key construction, the resolved agent ID is lost and the default agent (main) is used instead. The accountId (second-ana) appears in the session key as a path component rather than being used to select the agent prefix.

The session key format agent:main:telegram:second-ana:direct:* suggests the key builder treats second-ana as the Telegram account identifier within the main agent's namespace, rather than routing to a separate agent.

Fix Action

Fixed

PR fix notes

PR #58609: routing: support wildcard peer bindings (peer.id="*") for multi-agent routing

Description (problem / solution / changelog)

Summary

Fixes #58546.

Bindings with peer: { kind: "direct", id: "*" } were silently ignored because "*" was treated as a literal peer ID. The binding was indexed exclusively in the byPeer map under key "direct:*", which never matched actual incoming peer IDs (e.g. "direct:12345678"). This caused multi-agent routing to fall through to the default agent ("main"), breaking setups where a named Telegram account should route all DMs to a specific agent.

Root cause

normalizePeerConstraint normalized { kind: "direct", id: "*" } to { state: "valid", kind: "direct", id: "*" } — the same state as any concrete peer. buildEvaluatedBindingsIndex then placed it in the byPeer index under key "direct:*" and skipped all other categories. collectPeerIndexedBindings only looked up exact peer IDs, so the wildcard binding was never found.

Fix

  • Add a "wildcard-kind" state to NormalizedPeerConstraint for bindings where peer.id === "*"
  • Wildcard-kind bindings skip the byPeer index and fall through to byAccount/byChannel tiers
  • matchesBindingScope checks only peer kind (not ID) for wildcard-kind constraints
  • Exact peer bindings still take priority (higher tier) over wildcard peer bindings

Test plan

  • peer.id=* matches any direct peer and routes to the bound agent
  • peer.id=* does NOT match group peers when kind is direct
  • Exact peer binding wins over wildcard peer binding (tier priority)
  • Wildcard peer binding wins over default fallback for unmatched peers
  • Group wildcard peer matches any group peer
  • All 50 existing + new routing tests pass
  • All 76 tests across 5 routing test files pass

Joel Nishanth · offlyn.AI

Changed files

  • src/routing/resolve-route.test.ts (modified, +139/-0)
  • src/routing/resolve-route.ts (modified, +27/-0)

Code Example

{
  agents: {
    list: [
      { id: "main", default: true, workspace: "~/.openclaw/workspace" },
      { id: "second-ana", workspace: "~/.openclaw/workspace-second-ana" }
    ]
  },
  bindings: [
    { agentId: "main", match: { accountId: "default", channel: "telegram", peer: { id: "*", kind: "direct" } } },
    { agentId: "second-ana", match: { accountId: "second-ana", channel: "telegram", peer: { id: "*", kind: "direct" } } }
  ],
  channels: {
    telegram: {
      accounts: {
        default: { botToken: "..." },
        "second-ana": { tokenFile: "..." }
      }
    }
  }
}

---

[routing] resolveAgentRoute: channel=telegram accountId=second-ana peer=direct:xxx8131xxx guildId=none teamId=none bindings=2
[routing] binding: agentId=second-ana accountPattern=second-ana peer=direct:* guildId=none teamId=none roles=0

---

sessionKey=agent:main:telegram:second-ana:direct:xxx8131xxx
sessionFile=//.openclaw/agents/main/sessions/d04966ce-9060-492f-a315-96002e950fe2.jsonl

---

[ws] → event agent run=... agent=main session=telegram:second-ana:direct:xxx8131xxx stream=lifecycle phase=start

---

## Verbose Log Excerpt


21:20:57 [routing] resolveAgentRoute: channel=telegram accountId=second-ana peer=direct:xxx8131xxx guildId=none teamId=none bindings=2
21:20:57 [routing] binding: agentId=second-ana accountPattern=second-ana peer=direct:* guildId=none teamId=none roles=0
21:20:57 telegram inbound: chatId=xxx8131xxx from=telegram:xxx8131xxx len=92
21:20:57 preflightCompaction check: sessionKey=agent:main:telegram:second-ana:direct:xxx8131xxx
21:20:57 [agent/embedded] embedded run start: provider=ollama model=qwen3.5:35b-a3b-32k
21:20:57 [diagnostic] session state: sessionKey=agent:main:telegram:second-ana:direct:xxx8131xxx
21:20:57 [agent/embedded] [context-diag] pre-prompt: sessionKey=agent:main:telegram:second-ana:direct:xxx8131xxx systemPromptChars=37639 sessionFile=//.openclaw/agents/main/sessions/...
21:20:57 [ws] → event agent agent=main session=telegram:second-ana:direct:xxx8131xxx stream=lifecycle phase=start
RAW_BUFFERClick to expand / collapse

Bug type

Regression (worked before, now fails)

Beta release blocker

No

Summary

When using multiple Telegram accounts with per-agent bindings, resolveAgentRoute correctly identifies the target agent, but the session key is built using the default agent (main) instead of the resolved agent. This causes the non-default agent to load the wrong workspace, wrong identity files, and wrong session store.

Environment

  • OpenClaw version: 2026.3.28 (f9b1079)
  • OS: macOS (Apple Silicon, Mac Studio M4 Max)
  • Node: 25.8.1
  • Install method: npm global (npm install -g openclaw@latest)
  • Channel: Telegram (two separate bot accounts)

Configuration

Two Telegram accounts (default and second-ana) with explicit bindings:

{
  agents: {
    list: [
      { id: "main", default: true, workspace: "~/.openclaw/workspace" },
      { id: "second-ana", workspace: "~/.openclaw/workspace-second-ana" }
    ]
  },
  bindings: [
    { agentId: "main", match: { accountId: "default", channel: "telegram", peer: { id: "*", kind: "direct" } } },
    { agentId: "second-ana", match: { accountId: "second-ana", channel: "telegram", peer: { id: "*", kind: "direct" } } }
  ],
  channels: {
    telegram: {
      accounts: {
        default: { botToken: "..." },
        "second-ana": { tokenFile: "..." }
      }
    }
  }
}

Steps to reproduce

  1. Configure two Telegram bot accounts with separate agent bindings as shown above
  2. Send a direct message to the second-ana bot
  3. Observe routing logs and session key

Expected behavior

Routing resolves second-ana → session key should be agent:second-ana:main (or agent:second-ana:telegram:...)

Session file should be stored under ~/.openclaw/agents/second-ana/sessions/

Agent should load workspace ~/.openclaw/workspace-second-ana/ and its IDENTITY.md, SOUL.md, AGENTS.md

Actual behavior

Routing correctly resolves second-ana:

[routing] resolveAgentRoute: channel=telegram accountId=second-ana peer=direct:xxx8131xxx guildId=none teamId=none bindings=2
[routing] binding: agentId=second-ana accountPattern=second-ana peer=direct:* guildId=none teamId=none roles=0

But the session key is built with main:

sessionKey=agent:main:telegram:second-ana:direct:xxx8131xxx
sessionFile=//.openclaw/agents/main/sessions/d04966ce-9060-492f-a315-96002e950fe2.jsonl

The agent stream also shows agent=main:

[ws] → event agent run=... agent=main session=telegram:second-ana:direct:xxx8131xxx stream=lifecycle phase=start

As a result, the second-ana agent loads main's workspace, identity, and system prompt instead of its own.

OpenClaw version

2026.3.28 (f9b1079)

Operating system

macOS (Apple Silicon, Mac Studio M4 Max)

Install method

npm global (npm install -g openclaw@latest)

Model

ollama local

Provider / routing chain

Telegram (two separate bot accounts)

Additional provider/model setup details

What I've Tried

  • Deleting the stale session from main's session store → session is immediately recreated under main on next message
  • Changing session.dmScope from per-account-channel-peer to per-channel-peer to default → no effect
  • Removing session.dmScope entirely → no effect
  • Verified openclaw agents list --bindings shows correct routing rules for all agents
  • Verified openclaw sandbox explain --agent second-ana resolves correctly
  • Verified ~/.openclaw/agents/second-ana/sessions/ exists and is writable (remains empty — sessions never land there)
  • Ran openclaw gateway run --verbose to confirm routing vs session key mismatch in real time
  • Force-reinstalled openclaw@latest via npm → same version, same behavior

Analysis

The routing subsystem (resolveAgentRoute) works correctly — it matches the binding and identifies second-ana. But somewhere between route resolution and session key construction, the resolved agent ID is lost and the default agent (main) is used instead. The accountId (second-ana) appears in the session key as a path component rather than being used to select the agent prefix.

The session key format agent:main:telegram:second-ana:direct:* suggests the key builder treats second-ana as the Telegram account identifier within the main agent's namespace, rather than routing to a separate agent.

Logs, screenshots, and evidence

## Verbose Log Excerpt


21:20:57 [routing] resolveAgentRoute: channel=telegram accountId=second-ana peer=direct:xxx8131xxx guildId=none teamId=none bindings=2
21:20:57 [routing] binding: agentId=second-ana accountPattern=second-ana peer=direct:* guildId=none teamId=none roles=0
21:20:57 telegram inbound: chatId=xxx8131xxx from=telegram:xxx8131xxx len=92
21:20:57 preflightCompaction check: sessionKey=agent:main:telegram:second-ana:direct:xxx8131xxx
21:20:57 [agent/embedded] embedded run start: provider=ollama model=qwen3.5:35b-a3b-32k
21:20:57 [diagnostic] session state: sessionKey=agent:main:telegram:second-ana:direct:xxx8131xxx
21:20:57 [agent/embedded] [context-diag] pre-prompt: sessionKey=agent:main:telegram:second-ana:direct:xxx8131xxx systemPromptChars=37639 sessionFile=//.openclaw/agents/main/sessions/...
21:20:57 [ws] → event agent agent=main session=telegram:second-ana:direct:xxx8131xxx stream=lifecycle phase=start

Impact and severity

No response

Additional information

No response

extent analysis

TL;DR

The session key is being built with the default agent (main) instead of the resolved agent (second-ana), causing the non-default agent to load the wrong workspace, identity files, and session store.

Guidance

  • Verify that the resolveAgentRoute function is correctly resolving the agent ID (second-ana) and that the binding is correctly configured.
  • Check the session key construction logic to ensure that it is using the resolved agent ID instead of the default agent ID.
  • Review the logs to confirm that the routing subsystem is working correctly and that the issue lies in the session key construction.
  • Consider adding logging or debugging statements to the session key construction logic to determine where the resolved agent ID is being lost.

Example

No code snippet is provided as the issue does not contain enough information to suggest a specific code change.

Notes

The issue seems to be related to the session key construction logic, but without more information about the code, it is difficult to provide a specific solution. The logs suggest that the routing subsystem is working correctly, but the session key is being built with the wrong agent ID.

Recommendation

Apply a workaround to modify the session key construction logic to use the resolved agent ID instead of the default agent ID. This could involve adding a custom function to construct the session key or modifying the existing logic to use the resolved agent ID.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Routing resolves second-ana → session key should be agent:second-ana:main (or agent:second-ana:telegram:...)

Session file should be stored under ~/.openclaw/agents/second-ana/sessions/

Agent should load workspace ~/.openclaw/workspace-second-ana/ and its IDENTITY.md, SOUL.md, AGENTS.md

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: Multi-agent routing resolves correct agent but session is created under default agent [1 pull requests, 4 comments, 2 participants]