fix(agents): prefer target agent's bound Matrix account for subagent spawns#1
fix(agents): prefer target agent's bound Matrix account for subagent spawns#1lukeboyett wants to merge 2 commits intomainfrom
Conversation
…spawns A Matrix-bound parent session spawning a subagent for another agent could seed the child's deliveryContext.accountId with the caller's account before target bindings were consulted, causing child posts to come from the wrong Matrix identity. - src/agents/subagent-spawn.ts: add resolveRequesterOriginForChild(...) that prefers the target agent's bound account via resolveFirstBoundAccountId before falling back to the caller's accountId. - src/routing/bound-account-read.ts: resolveFirstBoundAccountId now accepts an optional peerId and uses two-tier matching — peer-specific bindings win immediately, channel-only bindings are kept as fallback, non-matching peer bindings are skipped. The existing cron delivery-target caller is unaffected (it does not pass peerId, so it gets channel-only matching as before). Regression coverage in openclaw-tools.subagents.sessions-spawn.lifecycle.test.ts: - Matrix room-bound route uses the target agent's bound account over the caller's account. - Peer-specific binding wins over channel-only binding for the same agent. - Non-matching peer falls back to the channel-only binding. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5d11d7bb1e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…nt lookup `resolveFirstBoundAccountId` previously compared `resolved.peerId` as a literal string, so a binding with `match.peer.id: "*"` would never match real peer IDs and would get skipped. That could make child spawn identity selection fall through to a channel-only or requester account instead of the target agent's wildcard-bound account. Align the helper's three-tier precedence with `resolve-route.ts`: 1. Exact peer match wins immediately. 2. Wildcard peer match (`peer.id: "*"`) wins over channel-only. 3. Channel-only binding is the final fallback. Addresses Codex review comment on PR #1. Regression coverage: - Wildcard peer binding matches a caller with any peer and beats a channel-only binding for the same agent. - Exact peer binding still wins over a wildcard binding when both exist. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@codex review |
|
Codex Review: Didn't find any major issues. 🚀 ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
Review consensus reached. Codex approved after one P1 fix (wildcard peer binding handling). Squashed to a single commit and opened upstream as openclaw#67508. Closing this fork PR as the review record. |
Summary
Fixes Matrix subagent spawns inheriting the caller's
accountIdinstead of the target agent's room-bound account.src/agents/subagent-spawn.ts: addsresolveRequesterOriginForChild(...)that prefers the target agent's bound account viaresolveFirstBoundAccountId({ cfg, channelId, agentId: targetAgentId, peerId: requesterTo })before falling back to the caller'saccountId.src/routing/bound-account-read.ts:resolveFirstBoundAccountIdnow accepts an optionalpeerIdand uses two-tier matching — peer-specific bindings win immediately, channel-only bindings are kept as fallback, non-matching peer bindings are skipped.peerId(e.g.src/cron/isolated-agent/delivery-target.tsis unaffected).Why
Before this fix, a Matrix-bound parent session spawning a child for another agent could seed
deliveryContext.accountIdwith the caller's account before target bindings were consulted. A child intended to post as the target agent's bound Matrix identity could end up posting as the caller.The original
resolveFirstBoundAccountIdalso matched only on channel + agent, so multi-room-bound agents could get the "first binding wins" regardless of which room the spawn was happening in. The two-tier matching fixes that while staying backward-compatible for callers that don't pass a peer.Regression coverage
src/agents/openclaw-tools.subagents.sessions-spawn.lifecycle.test.ts:sessions_spawn uses the target agent's bound account for a Matrix room-bound route— a room-bound target binding beats the caller's account.sessions_spawn prefers peer-specific binding over channel-only binding— two bindings for the same agent (channel-only default, peer-specific for room A); spawning in room A returns the peer-specific account.sessions_spawn falls back to channel-only binding when peer does not match— same two bindings; spawning in a non-matching room returns the channel-only default.Existing caller-fallback coverage is provided by
sessions_spawn announces with requester accountId.Validation
pnpm build✓pnpm check✓ (typecheck, lint, import cycles, boundary checks; also re-run by the pre-commit hook)pnpm test:changed✓ 3777/3777 (360s)AI-assisted
Authored with Claude Code (Claude Opus 4.6, 1M-context). Fully tested locally (typecheck + lint + targeted vitest +
pnpm test:changed+ live Matrix validation). I've reviewed the change and understand what it does.Related / prior art
deliveryContextfrom spawn params at the gateway layer — complementary, different layer.accountIdforwarding insendMessage.@codex review