SKIP TO CONTENT
AI AGENTS6 minAgents in Production / Ep. 12 · Stage 12-3

Agent Cost and Audit Data: What OpenTelemetry Covers

Your trace backend keeps 30 days of spans, and an auditor asks about an agent decision from last year (illustrative case). Where do you look?

XIN
Pixel-art night scene of a ship’s chart table under a lamp. Glowing thread lines run between small robot figures on the map, and a brass pin holds the chart down while the sea outside the window shifts.

IN 30 SECONDS

The GenAI conventions are strong on the inference line of an agent’s cost model and weak on its audit record. Spans give the other lines a join key, and your audit record, not the trace, stays the evidence.

KEY TAKEAWAYS · 3

  • The conventions cover the inference line of a cost model well: tokens per model, cache reads and writes. They count tokens, never money.
  • Most of the 14 audit-record fields have no gen_ai.* home. Use spans as the index into your audit record, not as the record.
  • Decisions, human review, evidence hashes and retention belong in your own com.acme.* namespace or in the record itself.
On this page

What gen_ai.* covers in an agent’s bill

IN SHORT The conventions cover the inference line of a cost model well, and give the expensive lines a join key, nothing more.

WORDS TO KNOW

Span
One timed step of work, such as a model call or a tool call, with a name and labelled values called attributes.
Trace
All the spans of one run, linked parent to child, so you can see which step started which.
Join key
An id stored in two places, so a record in one system can find the matching record in another.
Audit record
The record you keep of what an agent decided, on what evidence, and who reviewed it, kept for an auditor.

In the cost post I split an agent’s monthly bill into five lines. Put the conventions next to them and the coverage is lopsided.

Inference
gen_ai.client.inference.usage.* counters by model and gen_ai.token.modality; gen_ai.usage.* on each span, cache reads and writes included
Your price table. The conventions count tokens, never money
Platform
Nothing GenAI-specific
Your infrastructure metrics, joined on service.name
Data upkeep
Retrieval spans (gen_ai.data_source.id) show which source was read
Re-indexing and connector work, from your pipeline
Human review
Nothing
An escalation flag on the agent span, review minutes from the queue
Engineering upkeep
inference_calls and tool_calls histograms show drift
Hours, from tickets

about 5%

of the monthly cost: the inference line the conventions cover

Episode 7’s illustrative model, not a measured figure.

Covering only that line is fine. The inference line becomes comparable across providers and SDKs.

IN PLAIN WORDS

The other lines get a Join key An id stored in two places, so a record in one system can find the matching record in another. See the glossary, an id the span shares with your other data. The span that sent a case to a person is the one you hang the review cost on.

One trap: #469 removed the cache fields from the in-process invoke_agent span, because they mix several models. Take them from the inference spans.

Spans index the audit record; they aren’t it

IN SHORT Most of the 14 audit fields have no gen_ai.* home, so the spans become the index and the audit record stays the record.

The Audit record The record you keep of what an agent decided, on what evidence, and who reviewed it, kept for an auditor. See the glossary from episode 8 has 14 fields. The diagram shows where each one would land.

WHERE EACH AUDIT FIELD LANDS
Layered stack diagram: 3 layers, top to bottomLayered stack diagram: 3 layers, top to bottom. Layer 1, ON THE SPAN ALREADY: occurredAt, agentId (name), modelId, promptVersion. Layer 2, YOUR OWN COM.ACME.* KEYS: recordId, taskRef, decision, agentId (version). Layer 3, MOSTLY IN THE RECORD: actor, inputDigest, evidence (a retrieval span covers part), checks (optional summary on the span), humanReview, retentionClass, chain.ON THE SPAN ALREADYoccurredAtagentId (name)modelIdpromptVersionYOUR OWN COM.ACME.* KEYSrecordIdtaskRefdecisionagentId (version)MOSTLY IN THE RECORDactorinputDigestevidence (a retrieval spancovers part)checks (optional summary onthe span)humanReviewretentionClasschain
The 14 episode 8 fields, grouped. com.acme is a stand-in for your own reverse-domain prefix.
audit record → span
recordIdcom.acme.audit.record_id

The join key. Put it on the agent span; the record keeps the trace id.

agentIdgen_ai.agent.name + com.acme.agent.version

Version is no longer on the in-process span.

promptVersiongen_ai.prompt.name + gen_ai.prompt.version

Any scheme is allowed; match your prompt tool if you use one, else a content hash works.

evidenceretrieval span + record

gen_ai.retrieval.documents is opt-in and defines only an optional id and score.

decisioncom.acme.decision

finish_reasons is why the model stopped, not what the agent decided.

A Trace All the spans of one run, linked parent to child, so you can see which step started which. See the glossary may be sampled, batched, dropped or rewritten on the way. Then the backend deletes it on its own schedule.

Trace storage is the right design for operations and the wrong one for evidence.

THE AUDITOR’S QUESTION

Flow diagram: 4 stepsFlow diagram: 4 steps. Agent span, then Audit record. Audit record, then Trace backend. Trace backend, then Auditor’s answer.1Agent spanCarries the record id2Audit recordKeeps the trace id3Trace backendDeletes on its own schedule4Auditor’s answerFrom the record

Step 1. The agent decides. Its span carries the audit record id, under com.acme.audit.record_id.

Pick a step to see it move
  1. The agent decides Its span carries the audit record id, under com.acme.audit.record_id.
  2. The record keeps the trace id Decision, review and evidence go in the record, which points back at the trace.
  3. Day 31: the trace is gone The backend deleted it on schedule. Asking the trace store finds nothing.
  4. The record answers A year later, the auditor’s question is answered from the record: the span was only the index.
Illustrative case: a backend that keeps traces for 30 days. Link the two both ways, and either side finds the other.

Mind the prefix. For custom names, OpenTelemetry’s naming guide recommends your company’s reverse domain: com.acme for acme.com. It advises against borrowing an existing convention namespace.

ADAM says: My rule: never invent a gen_ai.decision. The day the spec adds one with another meaning, your data and theirs collide.

ITEM GET

Spans are the index

Put the record id on the span and the trace id in the record. The record, not the trace, is the evidence.

Sources, read on 7 October 2026: metrics, agent spans, spans, naming.

FAQ

Not by default: the conventions say instrumentations SHOULD NOT capture instructions, inputs or outputs by default. Where volume or sensitive data call for it, they recommend storing content externally, with references on the span. That suits an audit trail, since the evidence stays in storage you control.

STAGE CLEAR

What you now know

  • Which cost line the conventions cover, and how the other lines join to a span.
  • Why the audit record, not the trace, holds the evidence.

Check yourself

Tap or click a question to see the answer.

You need to record that a person approved an agent’s decision. Do you add a gen_ai.human_review attribute?

No. Never invent a gen_ai.* key: the spec may add one with another meaning. Use your own com.acme.* namespace, or keep it in the audit record the span points to.

Next stage:How do you pin a version of a spec that has no release?6 min
Adam Boudjemaa
Adam Boudjemaa

Web3 x AI engineer, former CTO of Integra. Named author (1 of 5) of ERC-3643, first author of ERC-6960, co-author of ERC-7410, and co-author of ERC-8203, which is still a draft.

Have a project to ship or a role to fill?

Discuss your project or role

My work at the web3 x AI intersectionOpen-source tools I build

Follow the engineering notes

Get new articles on production AI and smart contracts by email.