Skip to main content
Mirador enrichment hints connect an OpenTelemetry trace to actions that happen outside your process. Emit a reserved mirador.* event on the active user-flow span, and Mirador follows the action and stitches its outcome into that same trace. Supported actions include EVM, Solana, Canton, Safe, and Relay transactions, Stripe payments, and market rate resolution.
The canonical machine-readable contract is published at otel.mirador.org/llms.txt. Use it when generating integrations or prompting a coding agent.

Event catalog

An EVM chain is identified by chain.id, chain.name, or both when they agree. Only the EVM and Safe hints take a chain; every other hint is chain-agnostic or implies its chain from the event name.

Naming convention

Every hint follows mirador.<domain>.<subject>.<kind>hint:

Attribute reference

Extra attributes are preserved as context but do not control tracking. Notes on individual attributes:
  • safe.tx_hash is the SafeTxHash of the multisig proposal, not the hash of the transaction that executes it.
  • relay.request_id is the Relay request ID from the quote. Relay is chain-agnostic at hint time, so no chain attribute is needed; chain IDs and transaction hashes are resolved server-side from Relay’s status feed.
  • stripe.account_id routes calls to a Stripe Connect connected account. Omit it when observing your own account.
  • asset.symbol accepts a crypto symbol or an ISO 4217 fiat code and is upper-cased server-side, so casing does not matter.
  • asset.quantity must be positive. Mirador stamps usd_notional = quantity × usd_per_unit.
  • asset.kind is optional because the market service infers it from the symbol. It is passed through as-is; any value other than crypto or fiat is treated as unspecified and the market service still infers from the symbol. An unrecognized value does not reject the hint.
Attribute keys are literal flat strings. Emit 'tx.hash'; do not send a nested object such as { tx: { hash: value } }.

Emit a hint

Add the event only after the external system returns its identity.

Rules that must hold

  1. Emit an event, not a child span. Add the reserved event to the active user-flow span.
  2. Use the exact event name. Names are case-sensitive.
  3. Emit one event per action. Two transactions require two events; do not use an array of hashes.
  4. Use flat attribute keys. Dots are part of the key name.
  5. Wait for the identity. Do not emit before the transaction, intent, or payment ID is known.
  6. Keep the span sampled. A sampled-out span cannot carry a hint to Mirador.
  7. Flush before exit. Allow the batch exporter to drain or explicitly shut down the provider.
  8. mirador.trace.* is the exception to rule 1. Those keys are attributes, not events. See Reserved keys that are not events.

Chain resolution

The EVM and Safe hints accept these forms: Known IDs include Ethereum 1, Optimism 10, BNB Smart Chain 56, Polygon 137, HyperEVM 999, Base 8453, and Arbitrum 42161.

Invalid hints are preserved

A reserved event that is missing a required attribute or fails validation becomes a normal span event. Mirador preserves it instead of dropping it, but enrichment tracking does not start. This happens when:
  • A required attribute is missing or empty.
  • chain.id is 0, chain.name is unknown without an ID, or the two contradict each other.
  • asset.quantity is zero, negative, or not a number.
This fallback makes typos visible in the trace while preventing Mirador from following the wrong external action.

Reserved keys that are not events

The mirador.trace.* namespace works the other way round. These are attributes, not events, and they shape the whole trace rather than tracking an external action.
This namespace was previously mirador.tags. The old key is no longer recognized and now lands as an ordinary span attribute, so a trace set up the old way silently loses its tags. Rename it to mirador.trace.tags.
An event named mirador.trace.* is not a thing and lands as a plain event. It is the attribute key that matters, not the event name.

Trace tags

The array form is canonical. A plain string is comma-split so string-only configuration surfaces can reach this too, most importantly OTEL_RESOURCE_ATTRIBUTES=mirador.trace.tags=checkout,eu-west, which cannot express an array at all.
  • Set it on the Resource to tag every trace from a service. On the root span the span value wins outright rather than merging with the Resource value.
  • Only the root span is read. The same key on a child span stays an ordinary span attribute.
  • Non-string array elements render as their scalar text, so [1, true] tags as "1" and "true".
  • Values are trimmed; empties and duplicates drop, and first-seen order is preserved.
  • Capped at 32 tags of 128 characters. An over-cap tag is dropped whole, never truncated.

Trace attribute promotion

By default a span attribute stays on its span. mirador.trace.attribute.<key> is the opt-in way to make one a fact about the whole trace:
The prefix is stripped, so tier=gold joins the trace attribute bag. From there it is searchable through GET /v1/traces?filter=…, readable in automation-rule and derived-metric CEL as trace.attributes["tier"], and declarable as a derived-metric dimension.
  • Set it anywhere. The marker is honored on any span’s attributes and on any span event’s attributes, so trace facts do not have to be hoisted to the root span. When the same stripped key is set more than once, the last one applied wins.
  • It copies, not moves. The original mirador.trace.attribute.tier stays where you set it.
  • Scalars only. Arrays and maps are ignored, because CEL never binds them.
  • Explicit wins. A promoted value outranks a same-named resource attribute or vendor default.
  • Reserved targets are ignored: service.name (set that on the Resource), any key beginning __, and the mirador.trace.* namespace itself.
A bad marker is skipped rather than fatal, so one malformed key never rejects the span.

Event severity

OTLP span events have no native severity, so Mirador stores them neutral by default: they never affect a trace’s info, warn, or error counts. Span failure comes from the OTLP span status, not from its events, so recording an exception event does not by itself mark a trace failed. To give one event a severity, set the reserved attribute on that event:
An absent, empty, or unrecognized value means neutral. The value is case-sensitive, so use lowercase. The attribute is read before attribute capping and is left on the event’s attribute bag. This is what the severity filter on GET /v1/traces matches against, so an event you want to find later needs an explicit severity.

Next steps

Traces over OTLP

Configure trace export and understand span mapping

Transaction hints

Learn how Mirador follows and enriches transactions

Stripe payments

Track a PaymentIntent through charge and payout

Market rates

Resolve spot rates and stamp USD notionals