Summary
When Claude Code spawns a subagent via the Task tool, it creates a new session with a separate JSONL transcript file. The subagent's transcript marks messages with isSidechain: true and an agentId, but contains no reference to the parent session that spawned it.
This makes cross-session distributed tracing impossible for observability tools — the parent and child transcripts are two isolated islands with no shared key.
Current Behavior
Parent session transcript (~/.claude/projects/<project>/<parent-session>.jsonl):
{"type":"assistant","message":{"content":[{"type":"tool_use","id":"call-xyz","name":"Task","input":{"description":"..."}}]}}
{"type":"user","message":{"content":[{"type":"tool_result","tool_use_id":"call-xyz","content":"..."}]}}
Child session transcript (~/.claude/projects/<project>/<child-session>.jsonl):
{"type":"assistant","isSidechain":true,"agentId":"subagent-1","message":{...}}
The child session has no parent_session_id, no parent_turn_id, no parent_tool_call_id. An external tool reading both files cannot deterministically link them.
Requested Change
When Claude Code creates a subagent session (i.e. spawns via Task), write the parent context into the child session's first session_meta entry:
{
"type": "session_meta",
"sessionId": "<child-session-id>",
"parentSessionId": "<parent-session-id>",
"parentTurnId": "<turn-id-of-the-spawning-turn>",
"parentToolCallId": "<tool_use_id-of-the-Task-call>",
"isSidechain": true,
...existing fields...
}
Alternatively, if session_meta is not the right place, any structured first-line entry in the JSONL that external readers can reliably locate is acceptable.
Why This Matters
Without this link, observability tools face two bad options:
- Timestamp guessing — scan sibling sessions for
isSidechain: true entries whose start time falls within the parent's Task call window. Breaks when multiple subagents are spawned concurrently.
- No linking at all — parent and child traces are forever disconnected.
With parentSessionId + parentToolCallId in the child's metadata, tools can:
- Reconstruct the full agent execution tree
- Aggregate token costs across the entire hierarchy
- Attribute failures to the correct spawning turn
- Build flame-graph style views of multi-agent workflows
Context
This request comes from Spanory, an open-source observability tool for Claude Code and other agentic runtimes. It emits OTel spans and Langfuse traces from Claude Code session transcripts. Parent-child linking is the last gap preventing full distributed tracing support.
The companion issue tracking Spanory's side of this work: https://github.com/Bububuger/spanory/issues/1
Proposed Fields (non-normative)
| Field |
Type |
Description |
parentSessionId |
string |
Session ID of the spawning parent session |
parentTurnId |
string |
Turn identifier within the parent session |
parentToolCallId |
string |
tool_use_id of the Task call that created this session |
isSidechain |
boolean |
Already exists on message entries; ideally also on session_meta |
agentId |
string |
Already exists; the subagent's own identifier |
Backward Compatibility
Adding new fields to session_meta is additive. Existing readers that don't know these fields will ignore them. No breaking change.
Summary
When Claude Code spawns a subagent via the
Tasktool, it creates a new session with a separate JSONL transcript file. The subagent's transcript marks messages withisSidechain: trueand anagentId, but contains no reference to the parent session that spawned it.This makes cross-session distributed tracing impossible for observability tools — the parent and child transcripts are two isolated islands with no shared key.
Current Behavior
Parent session transcript (
~/.claude/projects/<project>/<parent-session>.jsonl):{"type":"assistant","message":{"content":[{"type":"tool_use","id":"call-xyz","name":"Task","input":{"description":"..."}}]}} {"type":"user","message":{"content":[{"type":"tool_result","tool_use_id":"call-xyz","content":"..."}]}}Child session transcript (
~/.claude/projects/<project>/<child-session>.jsonl):{"type":"assistant","isSidechain":true,"agentId":"subagent-1","message":{...}}The child session has no
parent_session_id, noparent_turn_id, noparent_tool_call_id. An external tool reading both files cannot deterministically link them.Requested Change
When Claude Code creates a subagent session (i.e. spawns via
Task), write the parent context into the child session's firstsession_metaentry:{ "type": "session_meta", "sessionId": "<child-session-id>", "parentSessionId": "<parent-session-id>", "parentTurnId": "<turn-id-of-the-spawning-turn>", "parentToolCallId": "<tool_use_id-of-the-Task-call>", "isSidechain": true, ...existing fields... }Alternatively, if
session_metais not the right place, any structured first-line entry in the JSONL that external readers can reliably locate is acceptable.Why This Matters
Without this link, observability tools face two bad options:
isSidechain: trueentries whose start time falls within the parent's Task call window. Breaks when multiple subagents are spawned concurrently.With
parentSessionId+parentToolCallIdin the child's metadata, tools can:Context
This request comes from Spanory, an open-source observability tool for Claude Code and other agentic runtimes. It emits OTel spans and Langfuse traces from Claude Code session transcripts. Parent-child linking is the last gap preventing full distributed tracing support.
The companion issue tracking Spanory's side of this work: https://github.com/Bububuger/spanory/issues/1
Proposed Fields (non-normative)
parentSessionIdparentTurnIdparentToolCallIdtool_use_idof theTaskcall that created this sessionisSidechainagentIdBackward Compatibility
Adding new fields to
session_metais additive. Existing readers that don't know these fields will ignore them. No breaking change.