#1465

ACP: a sub-agent that needs approval waits forever; the request never reaches the client

Openjuliusmarmingeopened 17d ago

With fx acp in ask mode, a sub-agent that needs tool approval never finishes. fx moves the child to awaiting_approval, but never sends the ACP client a session/request_permission, or anything else. The parent's subagent tool call stays in_progress, and session/prompt never returns. The only way out is cancelling the turn.

Repro

fx 0.0.14. The code path is unchanged on main at e71a663b.

  1. Set "permission_mode": "ask" in ~/.fx/settings.json.
  2. Create a workspace containing a package.json and a tsconfig.json.
  3. Run the attached probe: node acp-subagent-probe.mjs <path-to-fx> <workspace> out.ndjson. It:
    • sends initialize and session/new;
    • prompts "Spawn 2 subagents, one to read package.json and one to read tsconfig.json";
    • approves any session/request_permission with allow_once;
    • logs every frame.
  4. One child finishes in about 6 s: its tool_call_update is completed. The other's tool call stays in_progress. No permission request or other frame follows, and the prompt never returns; the probe gives up after 240 s.
  5. The session's subagent/children.json shows that child with "phase":"awaiting_approval" and "permission_mode":"ask".

It happened every time: three of three runs, from this probe, from T3 Code, and from T3 Code's replay recorder. In auto mode, the same prompt completes.

Where it seems to come from

  • runSubagentChild runs the child with the parent's tool context.
  • When the child needs approval, TurnContext.registerApproval moves it to awaiting_approval and registers the request in the sub-agent approval registry.
  • Only the terminal app drains that registry, via pendingApprovalRequest / resolveApproval in input_approval_runtime.zig and app_worker_runtime.zig. Nothing under src/acp calls either function, so over ACP the request is never shown to the user and never resolved.

Expected

The child's approval reaches the client as a session/request_permission on the parent session, ideally saying which sub-agent asks, and the client's answer resolves it. If fx can't route it, the child should fail rather than wait forever.

Attachments

Found while adding fx to T3 Code (pingdotgg/t3code#18277). T3 Code shows fx sub-agents in their own threads, and for now tells users to switch to Auto when delegating.

Activity

1
suirindo17d ago

For the approval-routing fix, a deterministic regression could put two children in awaiting_approval at once, reject one request, and approve the other. Assert that each answer resolves only its originating child and that the rejected child's tool produces no side effect.

A second case can cancel the parent while a permission request is outstanding, then deliver a late allow_once response. The late response should not restart the cancelled child, and session/prompt should settle with the defined cancellation result. This would cover request correlation and lifecycle cleanup alongside the reported missing request_permission frame. I haven't rerun the attached probe.