fix(routing): resolveAgentRoute uses binding.accountId, not agent_id #11
Reference in New Issue
Block a user
Delete Branch "fix/routing-use-binding-accountid"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
resolveAgentRoute({accountId: agentId, ...})— passing the openclaw agent id where the routing layer expects the binding'smatch.accountIdslot label.{agentId: developer, accountId: developer}) so the bug was invisible.intervieweeplaceholder (multiple new agents temporarily bind to the same fabric account during interview), the slot label isinterviewee, not the agent_id → routing returnedbindings=0→ openclaw core fell back to themainagent →mainran the sub-discussion turn under its workspace IDENTITY.md.Fix
cfg.bindingsto find the entry for this agent on the fabric channel, use that binding'saccountIdfor the route lookup.agentIdwhen there's no explicit fabric binding — preserves prior semantics for agents wired before bindings were uniform.Test plan
accountId=interviewee ... bindings=1, dispatch went to analyst2 session, 0 main sessions in the sub channel. Before the fix, the same flow showedaccountId=analyst2 ... bindings=0and main owned the turn.Related
shared apikeynoise (multiple agents subscribe to the same Fabric user because their fabric-identity entries weren't promoted off theintervieweeplaceholder by onboard) is a separate root cause — fixed independently in ClawSkills onboard scripts (secret-mgr settypo).`socket.on('message.created', ...)` dispatched with `accountId: agentId` (the openclaw agent id, e.g. 'analyst2') instead of the binding's `match.accountId` (the fabric account slot label, e.g. 'interviewee'). For most agents the binding is `{agentId: X, accountId: X}` so the two coincide and the call works by accident. For shared-placeholder slots (the recruitment `interviewee` apikey reused across pre-onboard agents) the slot label is `interviewee` not the agent_id, so the lookup returns bindings=0 and openclaw core silently falls back to the `main` agent — which then handles the sub-discussion turn under main's workspace identity. Symptom: every sub-discussion interview reply masquerades as the human user's IDENTITY.md text. Walk cfg.bindings for the entry that ties this agentId to a fabric account; use its accountId. Fall back to agentId when the agent has no explicit fabric binding declared (preserves prior behavior for agents wired before the binding format was uniform). Verified on prod-t2 recruitment retest 2026-05-31: Before: routing log `accountId=analyst2 ... bindings=0`, main session ran instead of analyst2. After: `accountId=interviewee ... bindings=1`, analyst2 session ran (0 main sessions in sub channel).