fix(routing): resolveAgentRoute uses binding.accountId, not agent_id #11

Merged
hzhang merged 1 commits from fix/routing-use-binding-accountid into main 2026-05-31 19:33:13 +00:00
Contributor

Summary

  • Dispatch path called resolveAgentRoute({accountId: agentId, ...}) — passing the openclaw agent id where the routing layer expects the binding's match.accountId slot label.
  • For most agents the two are the same string by convention ({agentId: developer, accountId: developer}) so the bug was invisible.
  • For the recruitment workflow's shared interviewee placeholder (multiple new agents temporarily bind to the same fabric account during interview), the slot label is interviewee, not the agent_id → routing returned bindings=0 → openclaw core fell back to the main agent → main ran the sub-discussion turn under its workspace IDENTITY.md.

Fix

  • Walk cfg.bindings to find the entry for this agent on the fabric channel, use that binding's accountId for the route lookup.
  • Fall back to agentId when there's no explicit fabric binding — preserves prior semantics for agents wired before bindings were uniform.

Test plan

  • Prod-t2 retest 2026-05-31 (analyst2 recruitment): routing log accountId=interviewee ... bindings=1, dispatch went to analyst2 session, 0 main sessions in the sub channel. Before the fix, the same flow showed accountId=analyst2 ... bindings=0 and main owned the turn.
  • All pre-existing agent flows (developer/manager/operator/ard DMs, work channels) still routed correctly since their binding accountId happens to equal agentId.
  • The shared apikey noise (multiple agents subscribe to the same Fabric user because their fabric-identity entries weren't promoted off the interviewee placeholder by onboard) is a separate root cause — fixed independently in ClawSkills onboard scripts (secret-mgr set typo).
## Summary - Dispatch path called `resolveAgentRoute({accountId: agentId, ...})` — passing the openclaw agent id where the routing layer expects the binding's `match.accountId` slot label. - For most agents the two are the same string by convention (`{agentId: developer, accountId: developer}`) so the bug was invisible. - For the recruitment workflow's shared `interviewee` placeholder (multiple new agents temporarily bind to the same fabric account during interview), the slot label is `interviewee`, not the agent_id → routing returned `bindings=0` → openclaw core fell back to the `main` agent → `main` ran the sub-discussion turn under its workspace IDENTITY.md. ## Fix - Walk `cfg.bindings` to find the entry for this agent on the fabric channel, use that binding's `accountId` for the route lookup. - Fall back to `agentId` when there's no explicit fabric binding — preserves prior semantics for agents wired before bindings were uniform. ## Test plan - [x] **Prod-t2 retest 2026-05-31 (analyst2 recruitment)**: routing log `accountId=interviewee ... bindings=1`, dispatch went to analyst2 session, **0 main sessions** in the sub channel. Before the fix, the same flow showed `accountId=analyst2 ... bindings=0` and main owned the turn. - [x] All pre-existing agent flows (developer/manager/operator/ard DMs, work channels) still routed correctly since their binding accountId happens to equal agentId. ## Related - The `shared apikey` noise (multiple agents subscribe to the same Fabric user because their fabric-identity entries weren't promoted off the `interviewee` placeholder by onboard) is a separate root cause — fixed independently in ClawSkills onboard scripts (`secret-mgr set` typo).
hzhang added 1 commit 2026-05-31 19:33:00 +00:00
`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).
hzhang merged commit 260d50196b into main 2026-05-31 19:33:13 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: nav/Fabric.OpenclawPlugin#11