Propagate nested rollout trace lineage - #640
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 713cc3d5d5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if job_id is None: # no standalone traces: a lone rollout is a job of one | ||
| job_id = uuid.uuid4().hex | ||
| await job_enter(job_id, name=task.id, group=1) | ||
| parent_trace_id = get_current_trace_id() |
There was a problem hiding this comment.
Propagate lineage through hosted rollouts
When a nested task selects HostedRuntime, Taskset._run calls HostedRuntime.run directly, bypassing this new parent capture, and the hosted submission payload includes only trace_id and job_id. Consequently, nested hosted rollouts still create an unparented trace and their remote gateway requests cannot carry the immediate parent; capture and submit parent_trace_id in the hosted path as well.
AGENTS.md reference: AGENTS.md:L153-L154
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 713cc3d. Configure here.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7dbad18ab2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if group_id is not None: | ||
| payload["group_id"] = group_id | ||
| if parent_trace_id is not None: | ||
| payload["parent_trace_id"] = str(uuid.UUID(parent_trace_id)) |
There was a problem hiding this comment.
Preserve hosted runs with non-UUID parent trace IDs
When a hosted rollout runs under an ambient trace ID that is not UUID-shaped, this new conversion raises ValueError before submission, and HostedRuntime.run turns the otherwise valid rollout into a failed run. This can occur through supported SDK paths because rollout(trace_id=...) and set_trace_context(...) accept arbitrary strings, and telemetry explicitly normalizes arbitrary run identifiers; previously, the hosted rollout succeeded regardless of the ambient context. Either preserve the parent identifier without UUID parsing or avoid letting an unrepresentable optional lineage value abort the child rollout.
AGENTS.md reference: AGENTS.md:L103-L107
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: afa1c03fc5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| trace_id = get_current_trace_id() | ||
| meta = {MCP_TRACE_ID_META_KEY: trace_id} if trace_id is not None else None | ||
| raw = await self._client.call_tool_mcp(name=name, arguments=arguments, meta=meta) |
There was a problem hiding this comment.
Propagate trace metadata through Claude SDK MCP calls
When ClaudeSDKAgent invokes an MCP capability, the Claude process uses the generated server configuration in hud/agents/claude/sdk/agent.py:98-107 and never calls this MCPClient.call_tool wrapper. Consequently, an MCP tool that launches a nested rollout receives no hud/trace-id, so _get_mcp_trace_id() returns None and the child is still recorded as a root trace for this shipped agent path. Extend the propagation mechanism to the Claude SDK MCP route as well.
AGENTS.md reference: AGENTS.md:L149-L150
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 29fdbfe. Claude SDK MCP server configs now include the active trace as a Trace-Id HTTP header, and FastMCP resolves that header when per-call MCP metadata is unavailable. Covered by the Claude SDK and server-context tests.
| parent_trace_id = get_current_trace_id() | ||
| trace_id = trace_id or uuid.uuid4().hex | ||
| if parent_trace_id == trace_id: | ||
| parent_trace_id = None |
There was a problem hiding this comment.
Compare canonical UUIDs before suppressing self-parenting
When the ambient context contains a hyphenated UUID and the explicit trace_id is the same UUID in compact .hex form, this string comparison does not recognize them as equal. _submit_and_await then canonicalizes both values, producing a submission whose parent_trace_id equals its trace_id, which can create or be rejected as a self-referential trace. Normalize valid UUIDs before applying the self-parent guard.
AGENTS.md reference: AGENTS.md:L103-L107
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 29fdbfe. Hosted parent IDs are canonicalized before comparison, so hyphenated and compact forms of the same UUID are treated as self-parenting and omitted. A regression test covers this exact case.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 29fdbfef41
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if parent_trace_id == trace_id: | ||
| parent_trace_id = None |
There was a problem hiding this comment.
Canonicalize IDs in the local self-parent guard
When the ambient parent is a hyphenated UUID and the explicit local trace_id is the same UUID in compact form, this raw string comparison misses the match, so trace_enter and gateway requests receive a parent that canonically equals the child and can create or be rejected as a self-referential trace. The hosted guard was corrected to compare canonical UUIDs, but the local rollout path still needs the same normalization before suppressing the parent.
AGENTS.md reference: AGENTS.md:L103-L107
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in fd84a80. Local and hosted rollouts now share UUID-aware trace ID equality, so compact and hyphenated forms cannot produce a self-parent edge. The local rollout lifecycle test covers the exact case.
fd84a80 to
4096d57
Compare
4096d57 to
599dd8a
Compare

Summary
Verification
Note
Medium Risk
Changes trace attribution across eval reporting, gateway inference, and MCP boundaries; incorrect parent handling could mis-link nested rollouts on the platform, but behavior is guarded by normalization and extensive tests.
Overview
Nested rollouts now keep a child trace as the active context while recording the immediate parent separately, so platform reporting and downstream calls can stitch lineage without collapsing nested work into one id.
Trace context replaces header-only storage with
currentandparentcontext variables.set_trace_contextyields the prior active trace as the parent and drops self-parenting when ids are equivalent UUID forms.get_current_trace_idcan also resolve inbound MCP tool metadata (hud/trace-id) or atrace-idHTTP header when no local context is bound.Rollout reporting: local
rolloutpassesparent_trace_idintotrace_enter; hosted submit includes a canonicalparent_trace_idwhen the ambient parent is usable (omitted for self-parent or non-platform ids).Propagation paths align on the same lineage: gateway HTTP adds
Trace-IdandX-HUD-Parent-Trace-Id;MCPClient.call_toolsendshud/trace-idin call meta; Claude SDK remote MCP configs add aTrace-Idheader alongside auth.Reviewed by Cursor Bugbot for commit 599dd8a. Bugbot is set up for automated code reviews on this repo. Configure here.