Trace metadata applies to the entire trace. Use it for information that’s constant across spans:Documentation Index
Fetch the complete documentation index at: https://laminar.sh/docs/llms.txt
Use this file to discover all available pages before exploring further.
- Environment: production, staging, development
- Region: us-west, eu-central
- Deployment: version numbers, feature flags, A/B test variants
- Request context: correlation IDs, upstream service info
- Post-hoc signals: quality scores, reviewer notes, edit counts you compute after the trace ends
Adding metadata while the trace is running
Set metadata inside an active span context (for example, insideobserve() or an @observed function). If you call it outside any span context, it won’t attach to anything.
- TypeScript
- Python
Laminar.setTraceMetadata and observe(..., { metadata })Adding metadata after the trace ends
Some metadata only exists once the trace is over: the user accepted or edited the model’s suggestion, an offline scorer ran, a human reviewer triaged the run. UseLaminarClient.traces.pushMetadata to attach those signals to a finished trace by trace id.
Capture the trace id while the trace is running, store it alongside whatever produces the signal (a database row, a queue message, a session id), then push the metadata once you have it. No need to copy a trace id out of the Laminar UI.
- TypeScript
- Python
pushMetadata shallow-merges the patch into the trace’s existing metadata: top-level keys you pass overwrite existing ones, keys you don’t pass are left alone. Call it again later to add or replace more fields.
Call
Laminar.getTraceId() / Laminar.get_trace_id() inside a span context. Outside, it returns null / None. Reading the trace id at the very top of an observe(...) block is the canonical place: the trace exists by then and you can return it from the block.The trace must already exist in your project before the patch is applied. For short-lived scripts, call
await Laminar.flush() (TypeScript) or Laminar.flush() (Python) before pushing metadata. If the trace can’t be found at the time the patch is processed (typically because it hasn’t been flushed yet), the call logs a warning and returns without raising.Wire format
Without the SDK, set one OTel attribute per metadata key on the root span:JSON.stringifyd. See the full Span attribute reference for the rest of the keys Laminar reads.
To attach metadata to a finished trace without the SDK, POST /v1/traces/metadata with { "traceId": "<uuid>", "metadata": { ... } } and your project API key as a Bearer token. The server shallow-merges the patch into the trace’s existing metadata.
Notes
- Metadata set during the trace is merged as spans arrive. If multiple spans set the same key, the last span processed wins (order is not guaranteed), so values can change while a trace is still ingesting.
- Set each metadata key in one place per trace (ideally the root span) and avoid duplicate keys in nested
observe(...)calls or AI SDK telemetry. pushMetadataonly runs after the trace has ended and merges deterministically with whatever metadata the trace already has.- Keep metadata JSON-serializable and avoid sensitive data.
Filtering by metadata
In the Laminar UI, metadata filters currently match exact key-value pairs (for example,region=us-west).
If a trace seems to appear in results while it’s running and then disappears after it finishes, check whether
the same metadata key is being set by multiple spans. Because metadata is merged on ingestion, the final value
can change as more spans arrive, which can flip whether a trace matches a filter.
Metadata vs Tags
| Metadata | Tags | |
|---|---|---|
| Scope | Entire trace | Individual spans |
| Format | Key-value pairs | String labels |
| Best for | Environment, cohort, request context, post-hoc scores | Categorization, review labels |
| Add after the fact | client.traces.pushMetadata | client.tags.tag |
Best Practices
- Use consistent keys (
environment,region,feature_flag). - Use
environmentfor prod/staging/dev; add a low-cardinality key likedeveloperorsourceto separate dev traces in a shared project. - Store the trace id alongside the work that will produce post-hoc signals, so the data and the trace stay linked without manual lookups.
- Keep it lightweight and JSON-serializable.
- Avoid sensitive data (no PII).
