anomalyco / anomalyco/opencode
[FEATURE]: propagate W3C traceparent on outbound LLM HTTP requests
@kitlangton is already working on this.
Since Sep 14, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Feature hasn't been suggested before.
- I have verified this feature I'm about to request hasn't been suggested before. Related but different: #46856 asks for W3C trace context in MCP
tools/call_meta(per SEP-414); this request is about the outbound HTTP requests to LLM providers (OpenAI, Anthropic, Azure, Copilot, etc.), which is a different surface. #18801 and #28295 were closed for inactivity and covered MCP HTTP/SSE, not LLM inference calls.
Describe the enhancement
OpenCode's outbound LLM HTTP requests do not carry a W3C traceparent header. When OpenCode is used behind a tracing-capable gateway or proxy, the gateway creates server-side spans for each LLM request, but these spans start a new trace because the inbound HTTP request has no trace context. Client-side and server-side spans end up as disjoint traces that can only be correlated by content and timing.
Suggested implementation
OpenCode already has full OTel infrastructure in packages/core/src/observability/otlp.ts: @opentelemetry/api, AsyncLocalStorageContextManager, and the OTLP HTTP trace exporter. The missing piece is injecting the active span context into outbound LLM requests.
Injection point: packages/llm/src/route/executor.ts, in the layer definition (~line 370). Before http.execute(request), inject the traceparent header from the active OTel context:
import { context, propagation } from "@opentelemetry/api"
// In executeOnce, before http.execute:
const carrier: Record<string, string> = {}
propagation.inject(context.active(), carrier)
const traced = Object.entries(carrier).reduce(
(req, [k, v]) => HttpClientRequest.setHeader(req, k, v),
request,
)
return yield* http.execute(traced)...
This requires adding @opentelemetry/api as a dependency to the llm package (it's already in the monorepo via packages/core).
Behavior when tracing is not configured: propagation.inject() is a no-op when no propagator is registered (no TracerProvider set up), so no headers are added. Zero behavioral change for users without tracing.
Verified end-to-end
Tested the equivalent fix (W3C traceparent injection via SDK middleware) against a live OTLP-capable gateway. With propagation, the gateway's server span becomes a child of the client's span in a single connected trace:
rag-pipeline (root)
|- retrieve (parent: rag-pipeline)
|- generate (parent: rag-pipeline)
| \-- chat openai-gpt-5.4 [SERVER] (parent: generate) <-- gateway span
Without it, the gateway span is in a separate trace.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.