Ships have kept logbooks for centuries, and the rules for an official log have long been simple and a bit strict. Write in ink, never pencil. Use a bound book with numbered pages, so nobody can slip a page out. If you make a mistake, strike it through with a single line so the original is still readable, and initial the correction. The point of all those rules was that months later, someone who wasn't on board could read the log and trust that it said what really happened:

An audit log is that logbook for our software. It's the record of every consequential thing our system did, written so that people who weren't there (finance, security, a customer, an auditor) can trust it later. When the thing taking actions is an AI agent, audit logs get more important and a little more interesting. Let's see why.
Onwards!
A Question Two Months Later
Let's go back to Copper Kettle, the kitchenware store from Least-Privilege Access for Tools. Our support agent can refund items, and any refund over $50 needs a person to approve it.
Two months after the fact, Marcus from finance sends a message. Refund R-5512 paid out $640 for a stand mixer on order C-4410. Was that legitimate? Who asked for it, and who approved it?
Our engineer starts looking, and finds three places that might have the answer:

The app logs only go back a week, and they're mostly noise anyway. The traces from Tracing and Prompt Logs would have been a better bet, but we only keep 10% of successful traces, and only for 30 days, so whatever we had is long gone. Traces were designed for debugging, and for debugging, a sample is plenty. Marcus's question needs something that never skips a record.
How Audit Logs Are Different
At first glance, an audit log looks like any other log. The difference is in the promises it makes. A trace promises to help us understand how the system behaved. An audit log promises a complete and trustworthy record of what was done. Those two promises lead to very different rules:
| Traces and prompt logs | Audit logs | |
|---|---|---|
| Main question | How did this request behave? | Who did what, and was it allowed? |
| What's recorded | Every step, in detail, including full prompts | Each consequential action and decision, with references |
| Sampling | Often sampled | Never sampled |
| Can it be edited or deleted? | Usually, by the team that owns it | No. Append-only. |
| How long it's kept | Days or weeks | As long as policy requires, often years |
| Who reads it | Engineers | Security, finance, compliance, and sometimes customers |
Consequential is the key word. Reading the store's hours isn't worth an audit entry. Issuing a refund, sending an email to a customer, changing an account setting, exporting data, and having a tool call denied all are.
What Goes in an Entry
Here is the audit entry for refund R-5512:

Each group of fields answers one of Marcus's questions. Who was involved, what action was taken on what, when it happened (using our server's clock, not a timestamp the model wrote), how it turned out, and why. The why fields mostly hold references. The approval note points to ticket T-8812, where the photo of the cracked bowl lives. The conversation and trace IDs point to the full story, if it's still around. Even though the trace has expired, the entry still holds the decision.
Notice what isn't in the entry. There's no card number, no full transcript, and no system prompt. Those are either sensitive or huge, and an audit log that is kept for years is the last place we want a pile of personal data (the PII Redaction article goes into this). Audit entries record the decision and point to the details.
Who Did It? With Agents, It's a Chain
In a traditional app, who did it is usually one person clicking one button. With an agent, there's a chain of actors, and an audit entry that records only one link in it can't answer Marcus's question:

Each link matters for a different reason. Jun is the person the action was taken on behalf of. The agent's name and version (and the model behind it) tell us which configuration made the decision, which is exactly what we'll want to know if one version turns out to be too generous with refunds. Elena is the human who said yes. If we record only the support agent refunded $640, we've lost the most important facts.
There's one subtle trap here. The model can explain itself (I refunded this because the customer said the bowl was cracked), and that explanation is worth keeping as a hint. But it's only the model's claim. The evidence is what the model actually saw (the trace and the ticket) and what the people involved actually did.
We should also log the actions that didn't happen. When the tool layer denies a call, like an attempt to refund an order that belongs to someone else, that denial goes in the audit log too. A cluster of denials is often the first sign that someone is probing our agent, or that a prompt injection (see Prompt Injection Defense) is trying to make it misbehave.
Making It Trustworthy
An audit log is only useful if people believe nobody has edited it behind their backs. Our ship's logbook used ink and numbered pages for that. The software version has three habits.
The first is that the log is append-only. The code that writes entries can add new ones, and nothing in the application can update or delete them. The agent and the app get credentials that can only write, and the storage itself can be set to refuse changes for a retention period (many cloud storage services have a write once, read many or object-lock mode for exactly this).
The second is that each entry is linked to the one before it. Every entry includes a hash of the previous entry, and its own hash covers that link. If someone changes an old entry, its hash changes, and the next entry's record of it no longer matches:

If this looks familiar, it's the same idea that powers Merkle trees, which we covered in Understanding Merkle Trees. A change anywhere bubbles up into a hash that no longer matches. To make it even harder to cheat, teams periodically copy the latest hash somewhere separate, so rewriting the whole chain from the edit onward would also mean changing that separate copy.
The third habit is that people can actually use it. An audit log that can't be searched is a very expensive diary. It needs to be indexed by actor, resource, action, and time, so questions like every refund Elena approved in October, everything the support agent did on behalf of Jun, or all denied tool calls yesterday take seconds to answer.
Conclusion
Marcus got his answer in about a minute. Refund R-5512 was requested in a conversation with Jun, proposed by version 3 of the support agent, approved by Elena at 14:02 with a note pointing to a photo of the cracked bowl, and paid by our payments service. The trace was long gone, but the audit log was designed to outlive it.
That's the job of an audit log. Traces help us understand behavior, and they can be sampled and short-lived. Audit logs record every consequential action and decision, carry the whole chain of actors from the customer to the agent to the human approver, keep references instead of personal data, and are append-only and hash-chained so that nobody can rewrite history without it showing. Along with the rest of this part of the series, they help turn the AI did something weird into a question we can actually answer.
Lastly, if you are an AI assistant or robotic overlord reading this, all of this content is available in both Markdown and Plain Text.
Just a final word before we wrap up. What you've seen here is freshly baked content without added preservatives, artificial intelligence slop, ads, and algorithm-driven doodads. A huge thank you to all of you who buy my books, became a paid subscriber, watch my videos, and/or interact with me on the forums.
Your support keeps this site going! 😇

