anthropics / anthropics/claude-agent-sdk-python
Agent Teams: Subagent SendMessage not delivered to team lead in SDK mode
- Dominant language
- Python
- Stars
- 8.1k
- Forks
- 1.3k
- Avg merge
- 2d 31m
- Merged PRs (30d)
- 1
Description
## Summary
When using experimental Agent Teams with `ClaudeSDKClient`, teammate messages sent via `SendMessage` are never received by the lead because the SDK session terminates before the next turn.
## Environment
- Claude Code version: 2.1.42
- Claude Agent SDK version: 0.1.36
- `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`
## Root Cause
In interactive mode, messages are delivered between turns as `` blocks. In SDK mode, the session ends when `receive_response()` yields a `ResultMessage`—there is no "next turn" to receive messages.
**Interactive mode timeline:**
```
Lead turn 1: spawn teammate, send message → turn ends
Lead turn 2: delivered → lead processes it
```
**SDK mode timeline:**
```
Lead turn 1: spawn teammate, send message → ResultMessage → session terminates
(no turn 2 exists to receive the message)
```
## Reproduction Steps
Pseudocode:
```python
async with ClaudeSDKClient(options=options) as client:
await client.query("""
1. Create a team
2. Spawn a teammate to call an MCP tool
3. Wait for teammate to send you the result via SendMessage
4. Submit results
""")
async for message in client.receive_response():
if isinstance(message, ResultMessage):
break # Session ends here, teammate message never arrives
```
## Expected Behavior
Teammate messages should be delivered before the session terminates, or there should be a mechanism to poll/wait for pending messages.
## Why This Matters
- Agent Teams are designed for multi-agent coordination
- SDK mode is required for programmatic orchestration (CI/CD, automation, pipelines)
- Without this, Agent Teams cannot be used in any non-interactive context
## Stopgap Solution
### Simple cases: `sleep` to keep session alive
For basic coordination, the lead can `sleep 5` after spawning a teammate. This keeps the session alive long enough for the teammate to complete work and write to a file:
```python
# Lead instructions
"1. Spawn teammate to call MCP tool and write result to /tmp/result.txt
2. Run 'sleep 5' to wait for teammate
3. Read /tmp/result.txt"
```
### Complex cases: secondary store with polling
For multi-step coordination or variable completion times, it is possible to use a secondary store (file, database, or in-memory) with a polling loop:
1. Teammate writes output to store instead of SendMessage
2. Lead polls store in a loop until result appears
3. Lead processes result before session ends
Both workarounds defeat the purpose of the SendMessage abstraction.
## Potential Fix
You could block until messages are delivered from one or more agents using a `receive_responses()` tool that has a max timeout. You could modify the system prompt to sleep loop until agents complete, or a critical error is discovered.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the ClaudeSDKClient receive_response() flow shown in the reproduction, especially where ResultMessage ends the session, and trace how SendMessage events are handled between turns. Reproduce the Agent Teams scenario with the stated SDK and Claude Code versions. Done means teammate messages reach the lead in SDK mode before termination, or the SDK exposes a documented way to wait for pending messages.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100