fix(agents): prevent reverse sessions_send on A2A target turns#112326
fix(agents): prevent reverse sessions_send on A2A target turns#112326dankarization wants to merge 2 commits into
Conversation
|
Current-main replacement for PR #91161, preserving and crediting the original implementation while adapting the guard to the newer conversation-tool layout. Exact-head validation: 270 focused tests, core typecheck, targeted lint/format, and diff check are green. @codex review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Codex Review: Didn't find any major issues. Chef's kiss. Reviewed commit: ℹ️ 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". |
1edf3da to
db09420
Compare
|
Rebased onto current Validation after rebase: 270 focused tests, core typecheck, Plugin SDK API check, and diff check all pass. @codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: db09420334
ℹ️ 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".
| options?.recordToolPrepStage?.("openclaw-tools:plugin-tools"); | ||
| } | ||
|
|
||
| allTools = allTools.filter((t) => !options?.interAgentSendTurn || t.name !== "sessions_send"); |
There was a problem hiding this comment.
Carry the A2A send guard into CLI tool scopes
When the target session resolves to a CLI-backed runtime, the same sessions_send provenance goes through runCliAgent; its bundled MCP surface is built by prepareCliRunContext -> resolveMcpLoopbackScopedTools -> resolveGatewayScopedTools, which calls createOpenClawTools without any interAgentSendTurn/input-provenance field. In that environment this new filter is never activated, so the target still sees sessions_send and can reverse-call the requester, leaving the duplicate-delivery bug unfixed for CLI-backed agents.
Useful? React with 👍 / 👎.
| ...(isAgentToAgentSendInputProvenance(params.inputProvenance) | ||
| ? { interAgentSendTurn: true } | ||
| : {}), |
There was a problem hiding this comment.
Apply the guard to compaction tool builds
When a long sessions_send target turn compacts before answering, compactEmbeddedAgentSessionDirect builds a separate createOpenClawCodingTools surface from the same inputProvenance instead of going through this attempt-context helper, so interAgentSendTurn is never set for the compaction model. That leaves sessions_send available during overflow/pre-run compaction and preserves the reverse-call duplicate path for A2A turns that hit compaction.
Useful? React with 👍 / 👎.
| if (provenance?.kind !== "inter_session") { | ||
| return false; | ||
| } | ||
| return provenance.sourceTool === "sessions_send"; |
There was a problem hiding this comment.
Preserve sessions_send on delivery-failure retry turns
When async A2A delivery fails after being accepted, runSessionsSendA2AFlow notifies the requester with runAgentStep and explicitly asks it to retry or report the failure (src/agents/tools/sessions-send-tool.a2a.ts:126-137), but that recovery step also uses sourceTool: "sessions_send". Classifying every inter-session sessions_send provenance as a target A2A turn removes sessions_send from the requester’s recovery tool surface, so an embedded requester cannot perform the retry path the prompt asks it to consider.
Useful? React with 👍 / 👎.
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: fix(agents): prevent reverse sessions_send on A2A target turns This is item 1/1 in the current shard. Shard 0/1. This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
Summary
sessions_sendonly while an agent processes a target turn that came fromsessions_sendsessions_list,sessions_history,sessions_search, and conversation tools availablesessions_sendautomatically on ordinary turns and other inter-session handoffsFixes issue #39476.
Supersedes PR #91161, whose implementation and tests this replacement preserves and adapts to current
main. The original external branch had drifted too far to update from this account.What Problem This Solves
When Agent A calls
sessions_sendto Agent B, B's response already returns through the original tool result. The routed target turn still exposedsessions_send, so B could reverse-call A and create a second requester-visible delivery of the same logical result.Why This Change Was Made
The target turn carries trusted input provenance:
kind: "inter_session"withsourceTool: "sessions_send". This change derives a per-turn guard from that provenance and removes only the reverse-call vector from the constructed tool surface.Current
maingroups conversation tools next tosessions_send. The implementation filters onlysessions_send; it preserves the newer conversation tools and all read-only session tools. Other inter-session sources such assubagent_announceare unaffected.User Impact
A delegated agent can no longer send the same result back through a second reverse
sessions_sendpath. The requester still receives the target result through the original A2A return, while the target retains its inspection tools.Evidence
db09420334, rebased onto currentmain.pnpm tsgo:core— passed.pnpm plugin-sdk:api:check— passed with the refreshed baseline.git diff --check— passed.Original implementation: PR #91161 by
sumitaich1998. Current-main adaptation and validation: Codex-assisted.