can_use_tool permission stream permanently closed after a Task subagent runs ("Stream closed")

Open 💬 0 comments Opened Jul 9, 2026 by soupat

Summary

When driving Claude Code headlessly via the Agent SDK with a can_use_tool permission callback, the callback stream breaks permanently after the agent uses the Task tool (spawns a subagent). Every subsequent tool call that needs a permission decision fails with:

Tool permission request failed: Error: Stream closed

The session continues, but all permission-gated tool calls are denied from that point on — the agent cannot recover.

Environment

  • claude CLI: 2.1.201 (also observed on an earlier 2.1.x)
  • claude-agent-sdk (Python) 0.1.50, query() with ClaudeAgentOptions(can_use_tool=..., permission_mode default)
  • macOS (darwin), Python 3.11

Repro

  1. Drive a session via the Agent SDK query() with a can_use_tool callback that approves Bash calls.
  2. Give the agent a task that leads it to spawn a Task subagent (e.g. "delegate a file search to a subagent, then run a shell command").
  3. After the subagent completes, the next Bash tool_use triggers the permission callback → Tool permission request failed: Error: Stream closed.
  4. All later permission-needing calls in the session fail the same way.

Observed deterministically across two independent sessions in an eval harness: the agent staged its work correctly, spawned one Explore-type subagent, and after it returned could never dispatch another gated Bash call (two multi-minute runs lost to it).

Expected

The permission request/response stream survives subagent lifecycles; can_use_tool continues to be consulted after Task completes.

Workaround

Settings-level permissions.allow rules for the tools the session needs (so the decision resolves CLI-side and never rides the callback stream). Works, but it bypasses dynamic per-call decisions, which is what can_use_tool exists for.

View original on GitHub ↗