Skip to content
Star3

Semantic conventions

Schema version: 0.1.0-dev · Stability: development for everything below. Rationale: ADR 0003. Privacy defaults: ADR 0004.

Span name Kind Parent Ends when
send {blockchain.chain.id} CLIENT active context (e.g. execute_tool) hash returned or send failed
confirm {blockchain.chain.id} CLIENT see below receipt retrieved, timeout or error; links to send or payment
payment {blockchain.chain.id} CLIENT active context (e.g. execute_tool) settlement reported or payment failed

Send span as the active span. While the call that sends the transaction runs, the send span is the active span, so spans that wallet, RPC or HTTP instrumentation creates for it nest under the send span. This holds for the viem adapter’s clients with a chain and for the CDP adapter, not for viem clients without a chain, whose send span is recorded after the call, and not for x402’s paid request (ADR 0015).

Confirm span parent, in order: an explicitly passed context; otherwise the active span (whatever is waiting for the receipt); otherwise the parent of the send span (confirmation in the background); otherwise none. The link to the send span is added whenever the transaction was sent through the same tracker within the link TTL (default 10 minutes).

Replaced transactions. A receipt is recorded on the confirm span of the transaction that was mined. When a wait for one hash ends with the receipt of another (a transaction with the same sender and nonce replaced it), the confirm span of the awaited hash ends as replaced, without block, gas or fee, and the receipt goes to the confirm span of the mined hash. If that span is created for this purpose, it has the same parent and start time as the replaced one and links to it and to both send spans when known. Dashboards counting confirmations should exclude blockchain.tx.status = replaced. See ADR 0008.

Payments. A payment span records a payment that the agent authorizes and another party settles on chain, such as an x402 facilitator: the agent signs, but does not send, the settling transaction, so there is no send span (ADR 0013). It carries what was paid, to whom, and the settlement. A settlement with a transaction hash makes the payment span the one a confirm span for that hash links to, and whose parent it takes for confirmation in the background, as a send span would.

blockchain.payment.status is recorded only from the settlement the settling party reported; when the client never learned it, the payment span has none and error.type says why.

One confirm span per transaction and tracker. Concurrent waits for the same transaction share one confirm span; its parent is determined by the first wait. A receipt from any wait ends it; a timeout or failure ends it only when it is the last wait still running, with that wait’s outcome. After a receipt, further waits within the link TTL add no span; after a timeout or failure, a retry gets a new span. See ADR 0007.

Situation Span Status error.type blockchain.tx.status
Transaction hash returned send unset none none
Signing, simulation or broadcast failed send error the library’s error code when the adapter reports one (see below), else error class name, else _OTHER none
Receipt with status success confirm unset none success
Receipt with status reverted confirm error reverted reverted
Gave up waiting for the receipt (its timeout, or flush() gave up) confirm error timeout timeout, deprecated; see below
Replaced by another transaction (same sender and nonce) confirm of the replaced hash unset none replaced
Receipt with an invalid transaction hash confirm error _OTHER none
Retrieving the receipt failed confirm error error class name, else _OTHER none
Payment settled payment unset none none; blockchain.payment.status is settled
Payment settlement pending: transaction known, receipt not seen payment unset none none; blockchain.payment.status is pending
Payment settlement failed payment error the settling party’s reason if it is a short identifier (see below), else _OTHER none; blockchain.payment.status is failed
Creating the payment failed (e.g. signing it) payment error as for a failed send none
Payment response without a settlement payment error no_settlement (x402 adapter) none
Payment outcome never learned (no response before its authorization expired, or flush gave up) payment error timeout none

Timeouts. blockchain.tx.status describes the transaction as the chain recorded it. A confirm span that gave up waiting has error status and error.type timeout; its blockchain.tx.status timeout is deprecated and will no longer be recorded from the first minor release after 0.4.0, so query error.type instead (ADR 0016).

An adapter whose library reports a stable, machine-readable error code records it as error.type of a failed send, if it is a short identifier ([A-Za-z0-9_.-], at most 64 characters); exception.type stays the class name. The CDP adapter records the CDP API’s error type, e.g. insufficient_balance.

Failures with an error object add an exception event following the OpenTelemetry exception conventions. By default it carries only exception.type; exception.message and exception.stacktrace depend on the tracker’s errorMessages mode (off | sanitized | raw), and the span status description is the recorded exception.message, if any. See ADR 0006.

Planned: RPC spans from a viem transport wrapper, following the OpenTelemetry JSON-RPC conventions (rpc.system.name = "jsonrpc", rpc.method from an allowlist of eth_* methods). No RPC spans are emitted today.

Attribute Type Spans Default Description
blockchain.system string all on evm
blockchain.chain.id int all on EIP-155 chain id, e.g. 8453
blockchain.operation.name string all on send | confirm | payment
blockchain.tx.hash string all on 0x-prefixed tx hash; on a payment span, the settling transaction’s, when reported
blockchain.tx.from string send raw sender address, subject to address mode
blockchain.tx.to string send raw recipient / contract address, subject to address mode
blockchain.tx.value string send on value in wei, decimal string
blockchain.tx.nonce int send on sender nonce
blockchain.contract.function.name string send on decoded function name when an ABI is known
blockchain.contract.function.selector string send on 4-byte selector, e.g. 0xa9059cbb
blockchain.contract.function.arguments string send off (opt-in) decoded call arguments as a JSON array, e.g. ["0x2222...2222","1000000"]: bigints as decimal strings, addresses per address mode, truncated after 4096 characters. Only own enumerable data properties are serialized; toJSON() and getters are never called
blockchain.tx.status string confirm on from chain data: success | reverted | replaced; timeout is deprecated (ADR 0016)
blockchain.block.number int confirm on inclusion block
blockchain.tx.gas.used int confirm on gas used
blockchain.tx.effective_gas_price string confirm on wei, decimal string
blockchain.tx.l1_fee string confirm on L1 data fee on OP-stack chains, wei
blockchain.tx.fee string confirm on gas.used × effective_gas_price + l1_fee, wei; omitted if the gas price is unknown
blockchain.tx.revert.reason string confirm on decoded revert reason when available: the Error(string) message, Panic(0x..), ErrorName(arg, ...) for custom errors with a known ABI, else the 4-byte error selector. See ADR 0005
blockchain.tx.replacement.hash string confirm on on a replaced confirm span: hash of the mined transaction that replaced it
blockchain.tx.replacement.reason string confirm on on a replaced confirm span: repriced | cancelled | replaced, as reported by the instrumented library; omitted when it reported none
blockchain.payment.protocol string payment on x402
blockchain.payment.payer string payment raw address that pays, subject to address mode
blockchain.payment.recipient string payment raw address that is paid, subject to address mode
blockchain.payment.asset string payment raw contract address of the token paid with, subject to address mode
blockchain.payment.amount string payment on amount in the asset’s smallest unit, decimal string; the settlement’s amount only when the payer knew none
blockchain.payment.status string payment on settled | pending | failed
x402.scheme string payment on x402 payment scheme, e.g. exact
x402.resource string payment origin the resource paid for, per the tracker’s paymentResource mode: origin (default) records scheme, host and port only, path the URL without query string, fragment or user info, off nothing; at most 512 characters, and nothing for text whose user info contains ? or #
error.type string all on see Span status; reused from OpenTelemetry general conventions

Agent identity is recorded with the GenAI conventions gen_ai.agent.id and gen_ai.agent.name. A field set in the tracker’s static agent option always wins; fields it leaves unset are taken from OpenTelemetry Baggage entries with the same keys, unless agentFromBaggage is false (ADR 0011). This lets backends search transactions by agent without joining spans. Baggage is propagated to downstream services; identifiers that must stay internal belong in the static agent option, which is never propagated.

blockchain.tx.from, blockchain.tx.to and the blockchain.payment.* addresses follow the address mode: raw (default), hashed (sha256: + first 32 hex characters of SHA-256 of the lower-cased address, or a custom function) or off. A redaction hook runs last on every attribute set; if it throws, only blockchain.system, blockchain.chain.id, blockchain.operation.name, blockchain.tx.hash, blockchain.tx.status, blockchain.tx.replacement.hash, blockchain.tx.replacement.reason, blockchain.payment.protocol, blockchain.payment.status and error.type are recorded. Hashing is pseudonymisation, not anonymisation. See ADR 0004. Neither hashed nor off hides the parties of a transaction: blockchain.tx.hash is always recorded and resolves to them on chain. The address mode also applies to addresses inside blockchain.tx.revert.reason, blockchain.contract.function.arguments, x402.resource, error.type and sanitized error messages (<address> in off mode). In hashed and off mode, hex values longer than an address are recorded as <hex> in those attributes, because a padded bytes32 or ABI-encoded bytes value can embed an address. The redaction hook also runs on error.type and on exception event attributes; if it throws, only exception.type is kept on the event.

Payment values usually come from a remote party (the paid server or the settling party): addresses that are not 0x-prefixed 20-byte hex, amounts that are not non-negative integers, hashes that are not 32-byte hex and identifiers (protocol, scheme, failure reason) that are not short identifiers are not recorded. Paths of paid APIs often carry user or account identifiers, so x402.resource records only the origin by default; with paymentResource: 'path' it records the path too, never the query string, fragment or user info, which can carry credentials (ADR 0004).

Additions are minor changes. Renames and removals keep the old attribute emitted for at least one minor release, are announced in the CHANGELOG, and bump the schema version.