Ben Brandt 8f67b6a92b fix: Only resolve a denied tool call the client was told about (#923)
`permission_denied` forwarded an SDK frame as a `tool_call_update`
without checking that the referenced `tool_call` was ever announced,
leaving it the last emitter without that check after #916.

The id is the executing call's own, and the frame is enqueued from
inside canUseTool, so it lands between the call's `tool_use` and the
`tool_result` carrying the rejection — verified against the bundled CLI,
where the deny short-circuit only emits for pre-ask decisions (rules,
mode, classifier, asyncAgent) and fires exactly once per denial. In that
flow the call is announced and in flight, so the guard changes nothing.

It changes the denials that arrive outside that window. The
cancelled-turn guard drops the assistant message carrying the tool_use,
so no `tool_call` is emitted, and a denial for it can still land
afterwards — the same premise the `tool_result` fallback in
`toAcpNotifications` gates on `wasEmitted` for. Ids leave
`emittedToolCalls` at `tool_result`, so the check also stops a denial
trailing its own result from flipping a call the client has seen finish
back to failed.

While here: a denial raised inside a subagent identifies it by
`agent_id`, never by the Agent/Task call that spawned it, so the update
went out unattributed while the `tool_call` it resolves sits in the
subagent's transcript. Resolve the parent through `liveBackgroundTasks`,
as the canUseTool path already does, and leave the update unattributed
rather than dropped when `task_started` was never seen for that agent
id.

`permission_denied` had no test coverage. Add cases for the in-flight
resolve, the reason fallback, the never-announced and already-resolved
drops, and subagent attribution with and without a recorded parent.

Fixes #918

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-27 10:49:30 +00:00
2026-07-21 18:53:56 +02:00
2026-07-21 18:53:56 +02:00
2025-09-02 19:06:32 -03:00
2026-03-26 12:19:06 +01:00

ACP adapter for the Claude Agent SDK

npm

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)
  • Following
  • Edit review
  • TODO lists
  • Nested subagent transcripts
  • Interactive (and background) terminals
  • Custom Slash commands
  • Client MCP servers

Learn more about the Agent Client Protocol.

Nested subagent transcripts

ACP 1.2 has no standard subagent tool kind or nested-message relationship. Clients that can render nested transcripts can opt in with clientCapabilities._meta["subagent-transcript"] = true. The agent then forwards subagent text, thinking, and tool calls, relating nested updates to the launching Agent/Task call through _meta.claudeCode.parentToolUseId. Agent/Task calls are marked with _meta.claudeCode.subagent = true.

Clients that do not advertise the capability retain the legacy flattened behavior. In both modes, the normal Agent/Task tool result is preserved as the protocol-compatible fallback.

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).

Description
Pull mirror of agentclientprotocol/claude-agent-acp (Apache-2.0): the ACP bridge that lets Buzz drive Claude Code
Readme 107 MiB
Languages
TypeScript 99.2%
JavaScript 0.6%
Shell 0.2%