No way to cancel/stop spawned agent team without killing the session
Bug Report / Complaint
What happened: After Claude Code spawned multiple parallel agents without my approval (see related issue: agent proceeding without user confirmation), I was unable to stop or cancel the running agents. The only way to regain control was to kill the entire session.
Expected behavior: Users should be able to cancel or stop running agents mid-execution (e.g., via Ctrl+C, Escape, or a /stop command) without losing their session. Graceful cancellation of agent teams is essential for maintaining user control.
Impact: I was forced to kill the session entirely, losing conversation context. Combined with the unauthorized execution bug, this left me unable to prevent unwanted changes to my project. I am filing this as both a bug report and a formal complaint.
Environment:
- Platform: macOS (Darwin 25.3.0)
- Model: Claude Opus 4.6 (1M context)
- Claude Code CLI
Showing cached comments. Read the full discussion on GitHub ↗
11 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Until native
/stopor Ctrl+C support for agent teams lands, here are some workarounds:1. Kill specific agent processes without losing the parent session
Agent teammates run as separate node processes. You can kill them individually:
The parent session survives — it'll get a "teammate exited" notification and continue.
2. Prevent unauthorized agent spawning with a PreToolUse hook
This is the root fix for the "spawned without approval" problem from #34475:
~/.claude/hooks/agent-gate.sh:3. Time-bomb safety net: auto-kill long-running agents
If an agent hangs or runs away, this background watchdog kills agents that exceed a time limit:
The combination of gate (prevent unauthorized spawns) + watchdog (kill runaways) + manual kill (targeted shutdown) covers most cases while waiting for a proper
/stopcommand.same issue
this issue still exist in plugin version2.1.81
Adding a partial workaround for one specific failure mode in this area: stuck in-process teammates that ignore
shutdown_requestJSON but unblock with a plain-text message.Context
Claude Code v2.1.89,
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1, in-process backend, macOS.We had a 5-member team where one teammate got stuck partway through its boot prompt (the boot prompt called several MCP tools that weren't available in the teammate context — see #24316 for the root cause). The stuck teammate emitted only passive
idle_notificationevents and never produced a model turn.We sent two consecutive
SendMessagecalls with{"type": "shutdown_request", ...}JSON bodies. Both succeeded at the API layer (success: true,request_idreturned), but the teammate ignored both — noshutdown_response, just moreidle_notifications. The other three teammates in the same team received the same shutdown protocol and returned cleanshutdown_approvedwithin seconds.What worked
A normal
SendMessagewith a plain-text body broke the loop:About 90 seconds later the stuck teammate emitted a clean
shutdown_approvedfor the originalrequest_id, and the system terminated it normally.Hypothesis
It looks like
shutdown_requestJSON is delivered to the teammate's inbox but only processed in the "ready for next turn" state. A teammate stuck mid-boot or mid-turn never reaches that state, so the JSON sits unread. A plain-text message goes through the same inbox but apparently triggers the boot loop to advance, at which point the teammate sees both the new text message and the queuedshutdown_requestand can respond to both.Why this is worth a fix or a doc note
shutdown_requestis currently the documented protocol for terminating teammates from the lead. If it silently fails on exactly the case where you most need it (a stuck teammate), the only remaining option is killing the parent session and losing all state — which is what this issue is about.Either:
shutdown_requestas an interrupt that can preempt an in-progress / stuck turn rather than waiting for the teammate to finish a turn, orTeamMemberKillor similar) that doesn't depend on the teammate's cooperation, orWe've added the plain-text trick to our internal runbook. Posting it here in case it helps anyone else who hits this before there's a proper fix.
Runaway agent teams with no kill switch is scary, especially when they are burning tokens. Cozempic's guard daemon monitors agent teams and protects their state through compaction, and the doctor command can detect zombie teams that are no longer responsive.
pip install cozempichttps://github.com/Ruya-AI/cozempic — happy to hear how it goes.Same here, Summary
When TeamCreate agents stall mid-execution (commonly inside WebSearch), the lead has no working mechanism to terminate them. All three documented termination paths fail. The only recovery is for the user to close and restart Claude.
In our session, agents have now been stuck for over an hour. They continue consuming compute. The × button in the Tasks panel does nothing. This is a serious deficiency for a paid product — I am on Claude Max 20x, and the only way out is to kill the whole client.
Termination paths that fail
SendMessage with {"type": "shutdown_request"} returns success but the agent never processes its inbox while stuck in a synchronous tool call
TaskStop with the team agent ID name@team-name returns No task found with ID: ... — the team-agent ID space and TaskStop's ID space appear disjoint
TeamDelete refuses while members are active (consistent with docs, but combined with the above leaves no escape hatch)
The Tasks-panel × button signals stop but does not interrupt mid-tool-call. After an hour it still has not taken effect.
Result: stuck team members keep running until the user closes and restarts Claude. There is no programmatic or UI recovery from inside the session.
Separate issue, same session: TeamCreate registration race
One of five agents (akilah) was spawned via Agent but missing from ~/.claude/teams/{team-name}/config.json members[]. Inbox file existed (2135 bytes, accumulating routed messages), but no shutdown handshake was possible. The agent appeared idle/wake-looping from the lead's side and never delivered content.
The same race appears reproducible when 5 agents are spawned in a single tool-use block.
Reproduction
TeamCreate a team
Spawn 5 agents in one tool-use block, each prompt triggering WebSearch early
Wait until at least one agent is mid-WebSearch
Try any of the termination paths above
Compare Agent spawn count to config.json members[] length — they may differ
Impact
Live multi-agent demos break visibly with no graceful recovery
Users must close the entire Claude client to escape stuck teams
Background compute continues silently for the duration of the session
The pattern of "agent idle without delivering content" is indistinguishable to the user from "agent finished" — there is no surface signal that the team is stuck
Workaround for one related symptom
The Working with Agents documentation pattern instructs agents to append session learnings via Bash cat >> .... In sessions where Bash is not auto-approved, this stalls agents at the permission gate. We resolved this by writing prompts that explicitly forbid Bash, file writes, and self-logs (output goes only in the agent's chat message). This avoids the Bash-permission stall but does not fix the unkillable-stuck-agent or registration-race bugs above.
Environment
Claude Code, in-process backend, multi-agent team via TeamCreate
Claude Max 20x subscription
macOS, Claude Opus 4.7 (1M context)
May 7, 2026
Happy to provide session logs, team config files, and additional reproduction details.
Real-world corroboration that the keyboard-only escape hatch makes "kill the session" the only option in some terminals:
Running Claude Code (2.1.156) inside cmux (an Electron/Ghostty multi-session manager), the watchdog repeatedly fired:
…but
Ctrl+Fnever reaches the CC TUI — cmux/Electron captures it at the app layer (find-in-page / its own shortcut layer), so the documented force-stop is unreachable./cleardoesn't help either (background agents are preserved across/clearby design). So the hung agent could not be cleared without killing the whole session — exactly the loss-of-context this issue is about.This is a strong argument for a non-keyboard stop affordance (a
/stopor/agents stop <id>slash command, as suggested above): keyboard-only shortcuts are fragile across terminals/multiplexers that capture common chords likeCtrl+F. A secondary nice-to-have: the watchdog could surface the stoppable agent's id and a slash-command hint rather than only "press Ctrl+F".Filed the terminal-side half against cmux: manaflow-ai/cmux#4993.
The lack of graceful agent cancellation is a real gap — especially in overnight or unattended orchestration scenarios where you want to abort a branch of work without nuking the entire session and losing conversation context.
The
/stopcommand approach makes sense for single-session work. For multi-agent scenarios the need goes a level deeper: you want to cancel a specific spawned agent (and its subtree) while keeping the coordinator session alive and the remaining agents running. Right now the only option is kill the whole process group, which loses everything.The pattern I've found that helps while this is unresolved upstream: keep the coordinator session stateless (all work state lives in files, not the conversation history), so killing and restarting costs you a few tokens rather than a whole context window. The agents that were doing work just re-read the task file on restart.
If you're building serious multi-agent workflows and hitting this regularly, I'm working on Claudeverse — an out-of-process coordinator that can signal individual agent sessions without touching the others. Happy to loop you in on the beta if that would be useful.
This is a real gap — the inability to cancel a running agent team without destroying the session is the kind of thing that makes autonomous workflows feel fundamentally unsafe to deploy.
The core problem as I understand it from building orchestration layers: Claude Code currently has no "stop tree" primitive. When you kill the parent process, the subagents are running in separate contexts and may continue modifying files, committing, or even spawning further agents depending on what they were mid-task on. The only safe stop today requires you to know all the PIDs (or process group) and kill them as a group.
A few things that have helped in practice until this is fixed natively:
.claude/STOPbefore each tool call. Any of your own wrapper scripts or hooks can check this. Not elegant but it propagates stop intent into the agent loop without requiring a new CLI primitive.setsid) so a singlekill -9 -<pgid>stops the entire tree — parent + all subagents — atomically. This is what's missing from the current native flow.--max-turnsor wrapping in a timeout command at least gives you a ceiling on the damage.None of these are substitutes for a proper
/stopcommand that drains in-progress tool calls gracefully and preserves the conversation state. The Ctrl+C → "do you want to stop?" → "yes" flow that already exists for single sessions should extend to agent teams. Upvoting this — it's a prerequisite for trusting any unattended parallel workflow.Closing for now — inactive for too long. Please open a new issue if this is still relevant.