Repository navigation
Send a subagent's permission requests to the ACP client - #1524
Closed
jakeleventhal wants to merge 1 commit into
Closed
jakeleventhal wants to merge 1 commit into
jakeleventhal wants to merge 1 commit into
Conversation
Under `fx acp`, a subagent that needed approval waited until the turn was cancelled: its request went to the subagent approval registry, which only the terminal app reads. While a child's turn runs, the ACP host now sends each of its pending approvals as `session/request_permission` on the parent's session and gives the client's answer back to that child. The request names the child in `_meta.fx.subagent` with its session id, work id, and own tool call id. Its `toolCall.toolCallId` adds the child's session id, so it can't match one of the parent's calls. Several children can wait on the client at once. Cancelling the turn denies an open request, and a request is withdrawn with `$/cancel_request` when the child's turn ends first. Permission policy is unchanged: only requests that already reached the registry, the same ones the terminal app shows, are sent. Fixes vercel-labs#1465. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Author
|
@fazxes says we should wait until subagent v2 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1465.
Summary
Under
fx acp, a subagent that needs approval now sends its request to the client, and the client's answer goes back to that subagent. Before this change, the child moved toawaiting_approvaland waited until the turn was cancelled: its request went to the subagent approval registry, which only the terminal app reads.session/request_permissionon the parent's session. Child sessions are internal and the client never sees them, so the parent'ssessionIdis the one the client can answer on._meta.fx.subagent, with the child'ssessionId, itsworkId, and the child's owntoolCallId. A request without_meta.fx.subagentcomes from the parent.toolCall.toolCallIdis<child sessionId>/<child toolCallId>, so it can't match one of the parent's calls.rawInputdescribe the child's tool call. The registry now keeps that call with its pending approval.$/cancel_request, and a late answer has no effect.Behavior that doesn't change
permissions.zigand the child's admission first. Only requests that already reached the approval registry are sent, and they are the same ones the terminal app shows.automode. A security review's hold still returns guidance to the agent without a prompt, because a hold never reaches the registry.runningorawaiting_approvalas interrupted, so nothing is left to send. When the child runs again, it asks again and the client gets a new request.interactive = falsein every host, soask_user_questionnever reaches any client from a child. This change covers permission requests only.Relation to #1132
#1132 adds the experimental
--subagents-v2tool, which runs each child as a separate fx process, and notes that "infx askand ACP, a child's prompts don't reach the user yet." This change targets the default subagent tool onmain, whose children run inside the parent's process. It doesn't touch the v2 code path and doesn't conflict with it. #1088 deliberately leaves ACP and subagent approvals out of scope.Verification
zig fmt --check src/andzig buildpass, andzig build fx-core-wasm -Dwasm-surface=corebuilds.zig build teston macOS arm64, with a cleanHOME: 9857 pass, 4 skipped, 1 failed. The failure is the MCP HTTP test "a kept connection the server reset or closed while idle...", which is intermittent locally. It passed on a later run and doesn't touch this code.src/acp/permission_requests.zigand the per-child lookup in the approval registry.tests/e2e/acp.test.ts:_meta.fx.subagent, andallow_oncelets the child write its file.session/cancelwith a child's request open sends$/cancel_requestfor it, the prompt endscancelled, a lateallow_oncechanges nothing, and the server answers the next prompt.mainwithout this change, all three tests hang until the 30-second timeout.acp.test.tspass. The full file run locally had 14 MCP and session-load failures. Running those tests against a build ofmainwithout this change failed 6 of them, and running them again on this branch failed 5, with a different subset failing each time. CI's Linux run is the gate for those../zig-out/bin/fx acpwith a temporaryHOME,FX_DISABLE_KEYCHAIN=1,permission_mode: "ask", and a fake gateway, using a client like the one in ACP: a sub-agent that needs approval waits forever; the request never reaches the client #1465. The parent started two subagents: one rantouch made-by-child.txtand one readpackage.json. The shell child's request arrived assession/request_permissionon the parent session with_meta.fx.subagent. The client answeredallow_once, the file was created, the prompt ended withend_turn, fx exited 0, and stderr was empty.Docs
session/request_permissionon the parent's session._meta.fx.subagentnames the subagent with itssessionId,workId, andtoolCallId, and the answer goes to that subagent."🤖 Generated with Claude Code