The third of three stacked PRs that replace #1257. It's based on #1321, so its diff shows only the `requires_action` part. Merge #1320 and #1321 first; this PR then retargets to `main`. 1. #1320: the RFD form for a v1 client that declares `subagents` and isn't AIR. 2. #1321: a child keeps its session across SendMessage resumes. 3. **This PR:** `requires_action` while a child's request is open. **AIR is unchanged.** ## What changes The [subagents RFD](https://github.com/agentclientprotocol/agent-client-protocol/blob/main/docs/rfds/subagents.mdx) reports a child that waits for the user as `requires_action`. - **While a request is open:** a child whose permission or question request is open reports `requires_action` on its parent, then `running` again when its last open request ends (`NativeSubagentRuntime.awaitingUser`). The agent wraps the permission and elicitation requests of a child session in it (`withChildAwaitingUser`). - **Overlapping requests** keep `requires_action` until the last one ends. A child that ended while it waited doesn't report `running` again. - **A resume while a request is open** reports `requires_action`, not `running`. ## Live run Against real Claude Code (Sonnet), a child's Bash permission request showed `running` → `requires_action` while the request was open → `running` once it was answered. No schema violations. ## Follow-ups (low severity, not in this PR) - **Brief `running` after a withdrawal:** after a cancel withdraws a child's request, the child briefly reports `running` before the SDK's stop event. The same happens at a stream end, whose cleanup aborts every pending request. - **Ignored cancel requests:** AskUserQuestion's `createElicitation` is not raced against the abort. If a client ignores `$/cancel_request`, the child's open-request count stays up, and a later resume reports `requires_action`. ## Tests - **End to end:** `requires_action` around a child's permission request. The cancel test now also expects the background child's `requires_action` before the cancel. - **Runtime:** overlapping requests, a child that ended while it waited, and a resume with an open request. - **Checks:** `npm run check`, build and all 2877 tests pass on this branch, whose tree is #1257's with `main` merged in. CI runs only on PRs to `main`, so I ran `ci.yml` on this branch by hand.
ACP adapter for the Claude Agent SDK
Use Claude Agent SDK from ACP-compatible clients!
This tool implements an ACP agent by using the official Claude Agent SDK, supporting:
- Context @-mentions
- Images
- Tool calls (with permission requests)
- Compact file changes through the negotiated AIR diff patch extension
- Following
- Edit review
- TODO lists
- Nested subagent transcripts
- Interactive (and background) terminals
- Custom Slash commands
- Client MCP servers
/mcpin the chat: the MCP server status as a list. The adapter runs/mcp reconnect,/mcp enable, and/mcp disablethrough the SDK control API, because Claude Code refuses them in SDK mode. A reconnect of an ACP server that needs authentication starts MCP OAuth through URL elicitation- Session-scoped long-running goals for AIR through the goal extension under
_meta.jetbrains.air.goal - Structured errors, recovery, and warnings through the opt-in session failure extension
- Concrete model and effort defaults through the opt-in recommended config value extension
- Tool permission presentation, editable choices, and durable effects through the permission extension
- One fact per field in every tool call report, as the ACP tool call contract defines
- All AIR extensions, capabilities, and
_metakeys: AIR extensions
Learn more about the Agent Client Protocol.
To try changes that have landed on main but are not released yet, install from the
preview channel — every push to main publishes one. See
docs/RELEASES.md.
npm install @agentclientprotocol/claude-agent-acp@preview
Subagent sessions
A client that declares clientCapabilities.subagents, other than JetBrains AIR, gets each Agent or
Task subagent as its own child session, following the subagents RFD:
subagent_updateon the parent announces the child before any of its traffic, with the parent'stitleanddescriptionfor it, and reports its work state:running,requires_actionwhile one of its requests is open, andidlewhen its work ends, withend_turnorcancelledwhen the SDK gives the reason. A failure isidlewith theerrorstop reason and the SDK's error text as itserror. The child keeps its session for every delegation to it.- The prompt of the Agent or Task call that launches the child, and the message of each
SendMessage call that resumes it, is a
session_messagein the child's transcript. The tool call stays a tool call of the session that made it. session/cancelon the parent interrupts Claude Code, which stops the foreground children that the turn waits on and, currently, background children too. Each stopped child reportsidlewithcancelledfrom Claude Code's own events, and the open requests of the foreground ones are withdrawn. The adapter ends no child at a cancel itself, so a child that keeps running keeps its open requests. A child that still runs when Claude Code exits isidlewith no stop reason.- A child whose parent is not yet known when it ends is not exposed, since the RFD forbids guessing its parent.
- A client cannot prompt, cancel, or otherwise change a child yet, and a replay does not restore children yet.
JetBrains AIR keeps the earlier draft of the RFD (subagent_spawned, subagent_state_update),
which it enables with nativeSubagentSessions in _meta.jetbrains.air.capabilities. See
AIR extensions.
Without either signal, Agent and Task stay ordinary tool calls and child interactions stay on the
root session. Clients that use the historical _meta["subagent-transcript"] capability or the
forwardSubagentText session option retain the flattened child transcript.
Contribution Policy
This project does not require a Contributor License Agreement (CLA). Instead, contributions are accepted under the following terms:
By contributing to this project, you agree that your contributions will be licensed under the Apache License, Version 2.0. You affirm that you have the legal right to submit your work, that you are not including code you do not have rights to, and that you understand contributions are made without requiring a Contributor License Agreement (CLA).