Subagents do not inherit Responses API client metadata from parent turns
What issue are you seeing?
When an app-server client supplies responsesapiClientMetadata on turn/start, the custom metadata is included in the parent turn's Responses API request, but it is dropped when Codex starts or continues a subagent.
This affects both multi-agent paths:
- V1 spawn/follow-up submissions do not carry the parent turn's client metadata.
- V2 mailbox submissions carry parent-turn identity, but have no channel for client metadata.
- Delegate/review/Guardian child-entry paths have the same gap.
As a result, downstream proxies and telemetry can attribute the root request to the originating client, but nested Responses API requests lose that attribution. Active child follow-ups can also retain stale attribution instead of following the triggering parent turn.
The reserved thread_id and turn_id fields should remain child-owned; the bug concerns inheriting the caller's custom metadata fields.
What steps can reproduce the bug?
- Start a Codex thread through app-server.
- Call
turn/startwith non-emptyresponsesapiClientMetadata, for example:
{
"client_trace_id": "parent-turn-a",
"thread_id": "spoofed-thread-id",
"turn_id": "spoofed-turn-id"
}
- Have the parent invoke
spawn_agent. - Inspect the parent and child outbound
/responsesrequests, particularly thex-codex-turn-metadataheader. - Repeat with Multi-Agent V1 and V2.
- For V2, send a follow-up while the child is active using a new value such as
parent-turn-b, then inspect the child's next Responses request.
Actual behavior:
- The parent request contains
client_trace_id. - The child spawn/follow-up request does not inherit it, or an active child continues with stale metadata.
- The missing propagation is independent of the child-owned reserved IDs.
What is the expected behavior?
- A child spawn should inherit the triggering parent turn's custom Responses API client metadata.
- Active child follow-ups should use the metadata associated with the input batch that triggers the sample.
thread_idandturn_idmust always be generated from the child thread/turn and must not be inherited or spoofable.- V2 mailbox aggregation should treat parent-turn ID and client metadata independently:
- inherit each unambiguous value;
- clear stale custom metadata when the contributing inputs disagree or do not provide a single value;
- let explicit steer metadata win for the batch it accompanies.
Root cause
The metadata currently stops at the parent turn's TurnMetadataState:
- the V1 spawn path submits child input without the parent metadata;
- the V2 mailbox models parent-turn ID only;
- child submission/delegate/review entry points have no shared parent-turn context carrying both values.
This is why merely preserving parent_turn_id does not fix client attribution.
Proposed fix
I prepared a focused implementation that introduces a parent-turn context containing both the optional parent turn ID and filtered custom client metadata, then propagates it through:
- V1 and V2 spawn/follow-up paths;
- the V2 mailbox and active-turn update path;
- delegate, review, and Guardian child entry points;
- internal
Submissionplumbing.
It also:
- filters reserved
thread_id/turn_idfields; - clears both provenance fields at the public
submit_with_idboundary to prevent spoofing; - stores explicit steer metadata with its pending input batch so it is applied only when that batch is drained;
- handles conflicting V2 mailbox contributors without retaining stale attribution.
Prepared implementation:
- Commit: https://github.com/hancao97/codex/commit/cdff1987266ba44c00e36e991d3fdb9997fb456a
- Compare: https://github.com/openai/codex/compare/main...hancao97:codex:codex/inherit-subagent-client-metadata?expand=1
Validation completed
- Responses API integration coverage for V1 and V2 subagent spawn.
- Active V2 follow-up coverage with changed client metadata.
- Queue aggregation, conflict-clearing, and explicit-steer precedence tests.
- Public-submit anti-spoof and delegate propagation coverage.
cargo check -p codex-core --tests --offline.- Focused
codex-coretests. just test -p codex-protocol -p codex-mcp-server.just fix -p codex-core -p codex-protocol -p codex-mcp-server.just fmtandcargo fmt --all -- --check.
I did not find an existing issue covering this exact metadata-propagation gap. If this approach aligns with the intended semantics, I would be happy to open the prepared PR with an invitation, per the repository's external contribution policy.
1 Comment
A brief follow-up after checking the changes merged since this report:
PR #37895 added
responses_api_metadata, and its configured product metadata is correctly present on both parent and subagent Responses requests. That is useful, but it does not cover this issue:responses_api_metadatais static configuration, whereasturn/start.responsesapiClientMetadatais dynamic app-server metadata that can differ per session/turn.The remaining affected use case is therefore:
I rechecked current
main; I do not see a parent-turn channel for carryingresponsesapiClientMetadatathrough subagent submissions/mailboxes, nor an associated PR for #37760.Could a maintainer confirm whether this dynamic metadata is expected to propagate to subagents? If the proposed semantics in the issue align with the intended design, I can rebase the prepared implementation onto current
mainand open the PR immediately once invited under the external contribution policy:If a smaller first step is preferred, I can also split initial spawn inheritance from active-follow-up/mailbox semantics.