feat: propagate ACP trace context metadata - #910
Open
xiaoziv wants to merge 5 commits into
Open
Conversation
xiaoziv
force-pushed
the
feat/acp-trace-context-metadata
branch
from
July 28, 2026 02:32
bdbdaef to
7a3e057
Compare
Author
|
This PR is now rebased onto the latest |
Two fixes to the ACP trace-context propagation, both verified against the
real CLI with an OTLP sink.
Clearing never worked. `applyFlagSettings({ env: null })` drops `env` from
the flag settings layer, but the CLI only ever *assigns* settings `env` onto
its live `process.env` — it never unsets a key that disappeared. So an
untraced prompt following a traced one kept the previous prompt's
`TRACEPARENT` and its `claude_code.interaction` span stayed parented under
it, for the rest of the session. Writing the vars explicitly blank clears
them: an empty value reads as absent to the CLI's span-context extraction.
Through the adapter over ACP stdio, turn 3 (untraced, after a traced turn 2)
went from `traceId=1111…, parent=2222…` to a fresh root span.
The unit tests couldn't catch this: they asserted the mock was *called* with
`{env: null}`, which it was.
Prompt admission regressed for every client. Any `session/prompt` arriving
while `query.interrupt()` was in flight — or whose preparation began before a
`cancel()` — returned `{stopReason: "cancelled"}` without ever being pushed
to the SDK, including prompts carrying no `_meta` at all. That is the
ordinary "hit stop, then send a new message" flow, and an interrupt is a
control round-trip that can take a while (hence the 30s force-cancel grace).
The generation check exists to cover the awaited trace-env round-trip, so it
is now consulted only when that round-trip actually happened; the refcounted
cancel barrier is gone, which also restores the plain `await
session.query.interrupt()`.
Also document the telemetry env the feature needs: without
`CLAUDE_CODE_ENHANCED_TELEMETRY_BETA` no trace spans are exported at all and
the metadata has no observable effect.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Follow-up to the trace-context fixes, based on what the CLI actually does with `TRACEPARENT`. Verified end-to-end by driving the built adapter over ACP stdio against an OTLP sink. Session-level trace context. `session/new`'s `_meta.traceparent` / `_meta.tracestate` are baked into the query's spawn env, so the whole session joins the caller's trace with no control round-trip, no race against a queued prompt, and nothing to clear afterwards. This is what most callers want and it avoids every failure mode the per-prompt path has to handle. A prompt that carries its own context still overrides it for that one prompt — and now reverts to the session's context rather than to nothing. Queueing works again. The CLI reads `TRACEPARENT` when it *dequeues* a message, not when the message is enqueued, so a turn the CLI has already started cannot be pulled into a later prompt's trace. Requiring a fully idle session was therefore stronger than correctness needs: what matters is that no previously submitted prompt is still waiting to start. A traced prompt can now be queued behind the running turn, which is the ordinary "send a follow-up while the agent works" flow. The two conditions clients could not act on anyway — `pendingOrphanResults` and `orphanCommands`, internal cancellation bookkeeping — are gone: an undequeued orphan would consume the new env, but the prompt behind it still reads the same value, so this prompt lands where it should either way. Applying trace context is best effort. A timed-out or failed control round-trip no longer closes the session or fails the prompt — losing a parent span means a new root span, not a lost turn. The live env is unknowable after a failure, so the session is recorded as still carrying prompt context and the next prompt retries the reset; an extra reset is harmless where a missed one would leak the trace into later prompts. That also removes the rollback machinery it existed to serve: `restoreBaseFlagEnv`, the compensation closure, the preparation-generation counter, and the `cancel()` hook that bumped it. `baseFlagEnv` is gone too. It existed to reconstruct a baseline to restore, but writing only the two trace vars cannot unset env inherited from the session's inline `settings` or from a lower settings layer — the same CLI non-deletion behaviour that made the blank-value fix necessary. Verified with a project-layer + inline-settings + flag-layer probe. With no baseline to model, the "opaque settings path" rejection goes away: a session may now pass `settings` as a path and still use trace context. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
xiaoziv
force-pushed
the
feat/acp-trace-context-metadata
branch
from
August 1, 2026 10:42
de6521a to
32f6db1
Compare
Author
|
Hi @benbrandt — a gentle follow-up on this PR. It has been updated against the latest main, and the trace-context behavior has been verified end-to-end against the real Claude CLI with an OTLP sink. The latest CI |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Add support for propagating W3C trace context from ACP prompt metadata to the Claude Agent SDK environment.
Changes
traceparentandtracestatefields fromsession/prompt.params._meta.TRACEPARENTandTRACESTATEbefore submitting the prompt.baggageis intentionally ignored for now.Example
{ "sessionId": "existing-session-id", "prompt": [{ "type": "text", "text": "Run the task" }], "_meta": { "traceparent": "00-80e1afed08e019fc1110464cfa66635c-7a085853722dc6d2-01", "tracestate": "vendor=value" } }Validation