Field notes · For the engineer · 27 August 2026 · 7 min

LangChain observability vs audit trail — why they're not the same thing

LangSmith tells you why the chain did what it did. It cannot prove to a third party that it did. The four properties a trace lacks, and how to get them from the spans you already emit.

Somebody on the compliance side has just asked whether the LangChain agent has an audit trail, and the engineer’s honest first thought is “yes — it’s all in LangSmith”. Every chain run, every tool call, inputs and outputs, latency, cost, a trace tree you can click through. What else would an audit trail be?

The answer is that a trace and an audit trail are different artefacts built for different readers, and confusing them is the most common way a team ends up with two years of beautiful traces and nothing an auditor will accept. This is the difference, precisely, and the good news at the end: if you already trace, you have done most of the work.

What a trace is for

A trace answers why did the chain do that? for an engineer, usually the same day. It is optimised for that: full payloads, because you need to read the prompt; a tree, because you need to see the retrieval that fed the generation; fast search; and cheap, short-lived storage, because traces are enormous and most are never opened. LangSmith, Langfuse and Phoenix are all good at this. We use two of them.

What an audit trail is for

An audit trail answers prove to me that this happened, in this order, and that nobody changed the record afterwards— for a reader who does not trust you, months later. That reader is an auditor, a regulator, a customer’s security reviewer, or opposing counsel. It needs four properties a trace does not have, and it is missing them not because the observability tools are bad but because nobody asked them to be evidence.

The questionA LangSmith / Langfuse traceAn audit trail
Who reads itAn engineer, debuggingAn auditor, a regulator, a security reviewer
How long it livesDays to weeks by default; self-hosters decideAs long as the obligation — EU AI Act Art. 19 says six months minimum; financial records run to years
Can it be editedYes. It is a row in a database, and nothing in the trace would show an editEach entry carries a hash of the previous one; any edit breaks every link after it
Who approved the actionThe service account that called the APIA named person, from the authenticated session, recorded before execution
Can it stop anythingNo — a trace is written after the call returnsYes — policy runs before the action, and the refusal is recorded beside it
Can an outsider verify itThey read what you export and take your wordThey run a verifier offline with public keys, no account with anyone

The six-month reference in the table comes from Article 19 of the EU AI Act; sector-specific obligations can require longer retention.

The four properties, one at a time

Retention. The easy half, and the one self-hosting Langfuse genuinely solves — if you set it. But a stored trace is still a mutable trace, so retention alone gets you more of a record that was never built to be evidence.

Tamper evidence.Not access control. “Only admins can edit” says who could have; a hash chain with an independently timestamped head says nobody did, and lets a stranger check.

A named human. A trace records the caller. For anything material — money, data about a person, a decision — the auditor wants the person who authorised it, and wants that identity to have come from the session, not from a field the agent populated.

Pre-execution. A trace is a record of the past. A policy check has to run before the tool call, or it is not a control; it is a report of a control you did not have.

The good news: same spans

If you emit OpenTelemetry — and LangSmith, Langfuse and Phoenix all can, via OpenInference or their own exporters — the instrumentation is done. An audit system of record reads those spans downstream: model calls become recorded actions, tool executions become tool calls with a policy verdict, payloads become fingerprints (so the prompt itself never has to leave your systems). You keep the trace viewer for debugging. You add the chain for evidence.

# You already have this
from langsmith import traceable

# Add this — it reads the same spans
import auditant
auditant.init(api_key="ak_…", agent_id="refund-agent")

@traceable                       # LangSmith: why did it do that?
@auditant.record(policy="refunds")  # Auditant: prove that it did, and who approved
def process_refund(order_id: str, amount: float): ...

Two decorators on the same function, two artefacts for two readers. The observability tool is not replaced, and we would rather say so than pretend a trace viewer with long retention is the same thing.

Do you need both?

  • No regulator, no auditor, no enterprise security questionnaire: you need observability, not this. Keep LangSmith and stop reading.
  • Agents that move money, decide about people, or touch regulated data: you need both, and the second one is the one that is currently missing.
  • Either way, write down what each plane retains today. The number is usually smaller than the team believes.

The longer version of this argument is at /llm-observability; the field-by-field spec of what the record has to hold is at /ai-agent-audit-trail.

See it on a real chain

The evidence path described above is running on our own account. Every ad-account change made by the agents behind Admiral, our paid-ads product, is recorded on the chain admiral/prod — actions on the chain, seals countersigned, and the sealed-through sequence are read live at /trust, not written into the page.

Start

Keep the traces. Add the record.

Two lines in one agent, free while you evaluate — and it reads the spans you already emit.

  • No card to start
  • Nothing is blocked until you say so
  • Your proof stays yours if you leave