claude-agent-sdk-python icon indicating copy to clipboard operation
claude-agent-sdk-python copied to clipboard

Sidechain messages occasionally not yielded through receive_response() despite being saved to <Session>.jsonl

Open suryaiyer95 opened this issue 3 months ago • 0 comments

Summary

Subagent (Task tool) messages are saved to history.jsonl with isSidechain: true but occasionally are not yielded through the receive_response() async generator. This causes assistant responses from subagents to be lost during streaming, even though they're preserved in the session history file.

Expected Behavior

When a Task tool invokes a subagent that produces output:

  1. The subagent's output should be aggregated into the parent Task tool's tool_result
  2. OR the sidechain messages should be yielded through receive_response()
  3. All assistant responses should be available via the async generator

Actual Behavior

Occasionally, sidechain messages with large text content are:

  1. Saved to history.jsonl with "isSidechain": true
  2. NOT yielded through receive_response()
  3. Result in empty parent Task tool results (content: [])
  4. Effectively lost during the streaming process

Steps to Reproduce

  1. Configure ClaudeSDKClient with a subagent
  2. Invoke the Task tool to trigger the subagent (may need multiple attempts)
  3. Iterate through client.receive_response() to collect all messages
  4. Compare received messages with entries in <claude_config_dir>/history.jsonl

Observation:

  • history.jsonl occasionally contains assistant messages with "isSidechain": true and large text content
  • These messages are not yielded through the async generator
  • Tool result for the parent Task tool has empty content: ToolResultBlock(tool_use_id='toolu_xxx', content=[])

Evidence

Message in history.jsonl:

{
  "parentUuid": "ab3780f8-6529-4ae3-88ff-c003d2f7d722",
  "isSidechain": true,
  "timestamp": "2025-10-28T01:10:02.997Z",
  "message": {
    "type": "message",
    "role": "assistant",
    "content": [
      {
        "type": "text",
        "text": "...13,022 characters of subagent output..."
      }
    ],
    "parent_tool_use_id": null
  }
}

Expected sequence from receive_response(): 01:08:48 - AssistantMessage (Tool Use) 01:10:02 - AssistantMessage (Text - 13KB) ← MISSING 01:10:06 - AssistantMessage (Tool Use)

Actual sequence from receive_response(): 01:08:48 - AssistantMessage (Tool Use) 01:10:06 - AssistantMessage (Tool Use) ← Skipped directly here

Impact

  • Data Loss: Subagent responses are occasionally not accessible via the async generator
  • Inconsistency: history.jsonl contains messages that were never yielded
  • Debugging Difficulty: Intermittent nature makes it hard to track when output is lost

Environment

  • Claude Agent SDK Version: 2.0.26
  • Python Version: 3.11
  • Model: claude-sonnet-4-5-20250929
  • Configuration: Using persistent session with continue_conversation=True

Code which I used

async with ClaudeSDKClient(options=self.options) as client:
      await client.query(prompt=prompt)
      async for message in client.receive_response():
          message_count += 1
          message_type = type(message).__name__
          logger.info(
              f"Claude Agent SDK stream query - Message: {message_type}"
          )
          logger.debug(f"Claude Agent SDK stream query - Message: {message}")

Compared the logs against the session.jsonl

suryaiyer95 avatar Oct 29 '25 02:10 suryaiyer95