How to Give a Long-Running AI Agent a Verifiable Trace
An agent that runs for hours leaves a long trail of model calls, tool invocations, and side effects. Application logs record that trail; they cannot prove it was not edited afterward. Here is how to give every agent run a signed, sealed, independently verifiable trace with Invoance: create, attest, anchor, seal.
Long-running agents create an evidence problem
An agent that runs for hours or days makes dozens of model calls, invokes tools, writes to databases, and sometimes waits for a human to approve something. When a customer, an auditor, or a regulator later asks what the agent actually did, the answer usually lives in application logs: plain rows that anyone with database access can edit or delete after the fact.
That is the gap. Ordinary logs record what happened, but they cannot prove the record itself was not cleaned up afterward. And for AI systems the bar is rising: Article 12 of the EU AI Act expects automatically generated logs across a high-risk system's lifetime, ISO/IEC 42001 auditors ask how AI decisions are recorded, and enterprise procurement questionnaires now include a blunt version of the same question: how do you log what your AI did, and how would we know if those logs were altered?
Invoance answers with three primitives that compose: AI attestations (a signed record of each model interaction), events (a signed record of everything around the model), and traces (a container that groups one run's records and seals them into a single verifiable proof). This guide wires all three into a long-running agent loop.
What a trace is (and is not)
A trace is a named, ordered grouping of anchored records under a single identifier. Every event, document, and AI attestation you attach keeps its own SHA-256 content hash and Ed25519 signature; the trace id is the thread that connects them. When the run ends, you seal the trace: Invoance computes a composite hash over every item's hash in chronological order, signs a seal record with your tenant's key, and closes the trace to new items.
A trace is not a workflow engine. It does not enforce steps, sequencing, or approvals, and it does not care how long the run takes. An open trace keeps accepting records for minutes or months, which is exactly the shape of a long-running agent.
Key insight. The sealed result is signed, append-only, and independently verifiable. Anyone can recompute the composite hash from the item hashes and check every signature against your published public key, with no Invoance account required.
Step 1: open a trace per agent run
Create one trace per run, at the moment the run starts. Put the run id in the label (open traces must have unique labels within your account, so a stable run id prevents collisions) and put searchable context in metadata. Then anchor a run-started event right away: it gives auditors the authoritative starting timestamp, and a trace needs at least one event before it can be sealed.
import { InvoanceClient } from "invoance";
const client = new InvoanceClient(); // reads INVOANCE_API_KEY
const trace = await client.traces.create({
label: "support-agent-run-" + runId,
metadata: { agent: "support-refunds", environment: "production" },
});
await client.events.ingest({
eventType: "agent.run.started",
payload: { run_id: runId, goal: "resolve ticket 4821" },
traceId: trace.trace_id,
});Step 2: attest every model call
Each time the agent calls a model, ingest an attestation of type output. Invoance hashes the input and the output with SHA-256, canonicalizes the full record, and signs it with your tenant's Ed25519 key. Use subject to tie the attestation to the run and step, and pass the trace id so it lands inside the run's trace.
const att = await client.attestations.ingest({
type: "output",
input: promptSentToModel,
output: modelResponse,
modelProvider: "anthropic",
modelName: "claude-sonnet-4-5",
modelVersion: "2025-09-29",
subject: {
sessionId: runId,
step: String(stepNumber),
},
traceId: trace.trace_id,
idempotencyKey: runId + "-model-" + stepNumber,
});
console.log(att.input_hash, att.output_hash, att.status);Attestation types map to agent moments
Attestations come in three types, and the other two cover the moments that make agents hard to audit. Use decision when the model chose a course of action: which tool to call, whether to escalate, whether a threshold was met. Use approval for human-in-the-loop sign-offs, with the approver's id in subject. The type is part of the signed payload, so "the model decided" and "a human approved" become distinct, provable claims rather than log lines that read the same.
The ingest call returns the input hash, output hash, and payload hash immediately; the signed record is durably queued and written asynchronously, so the call adds no meaningful latency to your loop. Duplicate submissions with the same content return the original attestation id instead of creating a second record.
Step 3: anchor tool calls and side effects as events
Model calls are half the story. An auditor's question is usually about effects: what did the agent actually change? Anchor an event for every tool invocation and consequential side effect, with the same trace id. Keep action names stable and lower-snake (agent.tool.called, refund.issued, ticket.closed) so filtering stays useful months later.
If the agent produced an artifact (a generated report, an exported file), anchor the file itself with Document Anchor and the same trace id. The document's hash becomes part of the sealed proof, so the artifact the customer received is provably the artifact the run produced.
await client.events.ingest({
eventType: "agent.tool.called",
payload: {
run_id: runId,
tool: "stripe.refund",
amount_cents: 4200,
result: "success",
},
traceId: trace.trace_id,
});Step 4: seal the run
When the run finishes, on success or failure, anchor a final run-finished event and seal the trace. Sealing is asynchronous: the API returns 202 and a worker computes the composite hash, a SHA-256 over every item's hash in chronological order across events, documents, and attestations, in the order they actually happened. The worker then writes a trace.sealed event signed with your tenant key and marks the trace sealed. Poll the trace until its status reads sealed; the proof endpoint returns 409 until then.
A sealed trace rejects new items. Anything ingested with that trace id afterward fails with a 409 instead of quietly rewriting history, which is precisely the property you want from a record of an autonomous system.
await client.events.ingest({
eventType: "agent.run.finished",
payload: { run_id: runId, outcome: "resolved" },
traceId: trace.trace_id,
});
const seal = await client.traces.seal(trace.trace_id);
console.log(seal.status, seal.message); // "sealing", "Seal initiated..."
// once status reads "sealed":
const proof = await client.traces.proof(trace.trace_id);
console.log(proof.composite_hash);What you can hand an auditor
A sealed trace gives you three artifacts. The proof bundle (GET /v1/traces/{trace_id}/proof) is a self-contained JSON document carrying every item's content, hash, signature, and public key, plus the composite hash and the signed seal record: everything needed to verify the run offline. The PDF proof is the same material as a branded document with a QR code pointing at the verification page, which is the version legal teams tend to file. And if you enable public verification for the trace (it is off by default), anyone can open the proof page at invoance.com/proof/trace/ followed by the trace id and check it in the browser; AI attestation payloads stay hash-only there unless you separately choose to expose them.
Be precise about what this proves. Verification is detection, not prevention. It establishes that every record in the trace is exactly what was signed at ingestion, that nothing in the sealed sequence was edited, and that nothing in the middle was removed. That is the claim an auditor can test with math instead of taking on trust.
Practical notes for agent builders
Anchoring belongs beside your loop, not inside it. Fire attestations after you have already acted on the model response, or push them onto a queue; the proof does not depend on blocking the agent, and the wall-clock cost of the calls is small either way. Derive idempotency keys from the run id and step number, as in the samples above, so a crashed-and-retried step lands exactly once.
Keep one trace per run rather than one per customer or one per day. The label carries the run id, metadata carries the rest, and traces are not a scarce resource: the free tier includes 250 traces, 50 AI attestations, and 1,000 ledger events per month, which is enough to trace a real run end to end before paying anything, and Builder raises the trace ceiling to 60,000 per month.
- Traces product overview— How sealing and composite proofs work, end to end.
- AI attestations quick start— Endpoints, limits, and the public proof flow for attestations.
- Start free— 250 traces and 50 attestations a month on the free tier.
Anchor every AI input and output as tamper-evident proof at generation time, one API call, no model changes.
Recommended
How to Prove Your AI Did What It Said: A Developer's Guide to Verifiable AI Outputs
Your AI's output is gone the moment it returns. Logs aren't proof. This guide shows how to attach a cryptographic receipt to every model call, in three lines of code, with a public URL anyone can verify, no Invoance account required.
AI Attestation: What It Is, Why It Matters, and How to Implement It
AI systems make decisions that affect loans, diagnoses, hiring, and contracts. When those decisions are challenged, organizations need proof of what the model produced, when, and with what inputs. AI attestation provides that proof.
ISO 42001 Compliance: What Engineering Teams Need to Know
ISO 42001 is the first international standard for AI management systems. For engineering teams, it means specific technical requirements around auditability, traceability, and governance. Here is what you actually need to build.
Invoance Audit Logs vs WorkOS Audit Logs: An Honest Comparison
Both products record who did what in your customers' accounts, and both ship a portal, streaming, and exports. The fork in the road is what happens after an event is stored: WorkOS asks your customer to trust the record, Invoance signs it so they can check. A feature-by-feature and price-by-price comparison, with sources.