GitHubBook a demoStart routing
Browse docs

Observability & tracing

The x-tt-* header contract, traces and agents, the Live feed, business dimensions, and OTel export — attribution comes only from explicit identity on the wire, never a guess.

On this page

TokenTriage attributes cost by trace identity, and identity comes exclusively from explicit x-tt-* request headers. There is no heuristic stitching — traceparent is logged for correlation but is never used to infer identity, because a wrong ledger is worse than a narrow one.

The header contract

Header What it does
x-tt-trace-id Groups requests into one agent trace. The one header that turns rows into a trace.
x-tt-step-id Identifies the step within the trace — enables the per-step cost tree (top --trace ID).
x-tt-parent-id The parent step id — draws the sub-agent fan-out edges.
x-tt-agent Logical agent / sub-agent name — drives top --by agent.
x-tt-step-class Explicit step class: user_turn | tool_loop | provider_state. When absent, the proxy derives a guess and records step_class_source: derived — the guess feeds routing rules but never trace identity.
x-tt-tier Explicit tier override by name; always honored in route mode, logged in all modes.
traceparent W3C context, logged as trace.w3c — never used to stitch identity.

All x-tt-* headers are stripped before the request is forwarded upstream (the provider never sees them); response rows echo the resolved identity into the decision log. The complete recipe is one line:

x-tt-trace-id per run, x-tt-agent per role, x-tt-step-id per call, x-tt-parent-id on delegation.

From x-tt-* identity headers to a per-step cost treeYour agent or SDK sets explicit x-tt-* headers per call — trace-id, step-id, parent-id and agent. The proxy groups the costed rows into one trace whose planner step has a child coder step, drawn from x-tt-parent-id, each carrying its own dollar. The same costed rows feed the per-step cost tree, agent rollups, and OTel export. The headers are stripped before the request reaches the provider.Your agent / SDKsets x-tt-* per call:trace-id · step-idparent-id · agenttrace: run-a1b2c3step: planneruser_turn · $0.000180step: codertool_loop · $0.004500parent-idTOTAL $0.004680Per-step cost treetop --trace <id>Rollupstop --by agent · step-classOTel exportone span per ledger rowstripped beforeupstreamIdentity comes only from explicit headers — never guessed from timing or prompt text

Setting the headers

Any framework where you control the HTTP client sets these on its outbound requests (set base_url to the proxy and pass the headers). The Python and TypeScript SDKs mint and propagate them for you across async boundaries. For Claude Code, tokentriage wrap injects a static, per-session x-tt-trace-id (plus x-tt-agent):

Business dimensions

With ledger.dimensions.enabled, four business dims come from headers — x-tt-user, x-tt-tenant, x-tt-feature, and bounded x-tt-tag-<k> (key ≤ 32 bytes, value ≤ 128 bytes, up to max_tags, default 8). They land in dims on the row, are stripped before upstream, and spend with no value renders as a first-class “unattributed” slice, never silently dropped. Promotion to Prometheus labels is opt-in and cardinality-guarded via ledger.dimensions.promote_to_metrics.

The Live feed

The dashboard’s Live surface is an off-path SSE tail of costed decision-log rows as they arrive — with a byte-fidelity indicator and a running session cost ticker. Being off-path, it can never backpressure your traffic.

localhost:9090/ui/liveDemo data
The Live feed: costed decision rows streaming in over SSE, each with provenance.
The Live feed — costed rows arriving over an off-path SSE stream, each stamped with its provenance.
localhost:9090/ui/tracesDemo data
A trace cost waterfall: per-step dollars (not milliseconds), with cost-path shading and the agent fan-out.
Traces & agents — a cost waterfall in dollars, not milliseconds, with the sub-agent fan-out.

OTel export

TokenTriage ships an OTLP exporter today (export.otlp.enabled, one span per ledger row) that emits cost under two namespaces on every priced row. Its own extension — tokentriage.cost.usd (omitted when unpriced), tokentriage.cost.unpriced, tokentriage.cost.pricing_snapshot, tokentriage.cost.pricing_key, tokentriage.cost.estimated, and tokentriage.cost.would_usd.<tier> — and, alongside it, the proposed GenAI convention gen_ai.cost.amount, gen_ai.cost.currency, gen_ai.cost.pricing_source, and gen_ai.cost.estimated, carrying the identical dollar. The endpoint and headers are references (export.otlp.endpoint, headers_env).

Related: SDKs (which automate the header contract) · The trust dashboard.