Skip to navigation

Tracing

Group related Gateway requests into one trace with HTTP headers, no SDK required

Tracing groups the requests in one run (an agent loop, chain, or pipeline step) into one trace that Logs shows as a tree. It’s header-based, so adding X-Merge-Trace-Id to requests you already send works on every endpoint and compatible SDK.

Trace a run

Send one trace ID on every request in a run. Optional span names make the tree easier to read.

TRACE_ID="run-$(uuidgen)"
curl https://api-gateway.merge.dev/v1/responses \
-H "Authorization: Bearer $MERGE_GATEWAY_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Merge-Trace-Id: $TRACE_ID" \
-H "X-Merge-Span-Name: draft" \
-d '{
"model": "openai/gpt-5.5",
"input": [
{"type": "message", "role": "user", "content": "Draft a reply to a customer asking for a refund."}
]
}'

A traced request with no parent is a root span. Mint a fresh trace ID per run, since reusing one merges unrelated runs. Untraced requests appear in Logs as usual.

Nest spans under a parent

Pass a response’s X-Request-ID header as X-Merge-Parent-Span-Id on a later request to nest it:

Python
draft = client.chat.completions.with_raw_response.create(
model="openai/gpt-5.5",
messages=[{"role": "user", "content": "Draft a reply to a customer asking for a refund."}],
extra_headers={"X-Merge-Span-Name": "draft"},
)
critique = client.chat.completions.create(
model="anthropic/claude-sonnet-5",
messages=[{"role": "user", "content": f"Critique this draft: {draft.parse().choices[0].message.content}"}],
extra_headers={
"X-Merge-Span-Name": "critique",
"X-Merge-Parent-Span-Id": draft.headers["x-request-id"],
},
)

Or send your own UUID as the parent’s X-Request-ID and reuse it on the children. Gateway doesn’t check that a parent exists, so a span whose parent never arrives sits at the root.

A traced Fusion request adds its panel calls as child spans fusion-candidate-1, fusion-candidate-2, and so on, with synthesis as your request’s own span.

Threads and turns

A thread is the conversation a run belongs to, such as a support ticket or chat session. Send one X-Merge-Thread-Id for its lifetime and a fresh trace ID per run, so filtering Logs by thread shows the whole conversation. X-Merge-Turn-Id groups an agent’s requests for one user message. Neither adds tree structure.

View traces in Logs

Filter Logs by Trace ID, Thread ID, Turn ID, Client trace ID, or Span name (only names you sent). A traced request’s detail shows its trace fields and, for multi-request traces, a tree of up to 100 requests with model, timeline bar, and status; click a row to open it. Detail also breaks down Gateway time (routing, security scanning, vendor time to first token) and shows payloads unless Disable payload logs is on under Settings → Organization. Viewing traces needs View logs.

Tracing from coding agents

When no X-Merge-Thread-Id is sent, Gateway turns a coding agent’s session header into a Thread ID:

ToolThread grouping
Claude CodeAutomatic, from x-claude-code-session-id
CodexAutomatic, from session-id, plus a Turn ID per turn from x-codex-turn-metadata
OpenCodeAutomatic, from X-Session-Id
PiSet "compat": { "sendSessionAffinityHeaders": true } on the provider in models.json
Continue.devSend X-Merge-Thread-Id in the model’s requestOptions.headers
Factory DroidSend X-Merge-Thread-Id in the custom model’s extraHeaders
CursorNot available, because requests come from Cursor’s servers

An explicit header always wins. This one groups a developer’s Claude Code sessions into one thread:

export ANTHROPIC_CUSTOM_HEADERS="X-Merge-Thread-Id: $(whoami)-claude-code"

Headers set this way are fixed per session, so an X-Merge-Trace-Id set at launch makes the session one flat trace. A W3C traceparent trace ID is recorded as Client trace ID, matching the agent’s own tool-call traces.

Reference

HeaderEffectLimit
X-Merge-Trace-IdAdds the request to a trace. Without it, the request isn’t traced.128 characters
X-Merge-Parent-Span-IdNests the request under an earlier request’s X-Request-ID. Ignored without a trace ID.128 characters
X-Merge-Span-NameLabels the span, such as draft. Ignored without a trace ID. In the trace panel, unnamed spans show the model name.64 characters
X-Merge-Thread-IdGroups requests into a conversation. Works without a trace ID.128 characters
X-Merge-Turn-IdGroups the requests for one agent turn. Works without a trace ID.128 characters
traceparentRecords the W3C trace ID as Client trace IDW3C format
X-Request-IDSets the request’s own ID, which children reference as their parent. A value that isn’t a UUID is replaced with a generated one.UUID

Merge header values may use A-Z a-z 0-9 . _ : -. An invalid or too-long value is dropped, never truncated, and the request still succeeds; only a dropped X-Merge-Trace-Id leaves it untraced.

Next steps