Background agents (run_in_background: true) cause session to hang after completion
Summary
When using the Task tool with run_in_background: true, the session gets stuck in a "Channelling..." state after agents complete. The completion notification system is decoupled from TaskOutput, causing notifications to pile up without being acknowledged.
Steps to Reproduce
- Spawn multiple background agents:
Task(prompt="simple task", run_in_background=true)
Task(prompt="simple task", run_in_background=true)
Task(prompt="simple task", run_in_background=true)
- Wait for agents to complete (they do finish successfully)
- Observe the session remains stuck showing "Channelling... (esc to interrupt)"
- Run
/tasks- shows nothing running
- Press Esc - sometimes dismisses one notification, sometimes does nothing
- Call
TaskOutput(task_id, block=true)for each task - returns results successfully but does NOT clear the stuck state
Expected Behavior
- Session should return to interactive state when all background tasks complete
TaskOutputshould acknowledge/consume the completion notification- Or: completion notifications should auto-dismiss when tasks finish
Actual Behavior
- Session stays stuck in "Channelling..." state indefinitely
/tasksshows nothing running (tasks completed)- Esc key behavior is inconsistent - sometimes works, sometimes does nothing
TaskOutputretrieves results but notifications remain queued- Only way out is Ctrl+C or killing the process
Root Cause Analysis
The Task tool's run_in_background: true flag creates two decoupled systems:
- TaskOutput - retrieves agent results
- Notification system - queues completion notifications for display
These systems don't communicate. Calling TaskOutput doesn't acknowledge the notification, so it remains pending. The session waits for notification acknowledgment that never comes.
Workaround
Don't use run_in_background: true. Instead, spawn multiple agents in a single message without the flag:
# Works correctly - agents run in parallel, session terminates cleanly
Task(prompt="task 1")
Task(prompt="task 2")
Task(prompt="task 3")
# All called in same message = parallel execution
This achieves the same parallel execution but uses the synchronous completion path which works correctly.
Environment
- Claude Code version: 2.1.17
- OS: macOS Darwin 25.0.0
- Platform: darwin
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗