Skip to content

AI agent audit log: what to record beyond tool calls

An AI agent audit log should do more than list tool calls. What to record, why the data's before and after matters, and how to undo a bad change.

Something looks wrong in your customer data, and you suspect the agent that ran last night. You open the log. It says update_record was called 1,200 times, each call returned success, and every call was allowed by policy.

That tells you the agent was busy. It does not tell you which values it overwrote, what they were before, or how to get them back. Those are the questions you actually have.

Most advice on AI agent audit logs is about logging the call. That is necessary, and this guide covers it. But a log of calls records what the agent asked for. For an agent that changes business data, you also need a record of what changed.

What an AI agent audit log is ​

An AI agent audit log is a lasting record of what an agent did: who it acted for, what it was allowed to do, what it called, and what changed as a result. It is written by the system around the agent, not by the agent, so that a person can reconstruct and answer for the work afterwards.

What to record for every call ​

The good guides agree on the basics. Obot's schema and MojoAuth's field list go deeper, and are worth reading if you are building this yourself. In short:

RecordWhy
Time and ids (event, session, parent call)To put events in order and follow one job across systems
The person the agent acted forSomeone has to answer for the work
The agent itself, and its model"An agent" is not an answer when you run several
What it was allowed to doTo tell a wrong action from a wrong permission
The tool, its arguments, its targetWhat was asked for
The policy decision, allow or denyRefused attempts are often the most interesting lines
The outcomeWhether it worked, and what came back

Keep secrets and personal data out, or store them redacted. A log is a copy of your data that many people can read.

Three questions a log of calls cannot answer ​

We counted our own work: in eight real Claude Code sessions on this project, the agent made 3,243 tool calls. A full log of those is long, and it still would not answer these.

What did the data hold before? ​

A call's arguments say what the agent wanted to write. They do not say what was there. If the agent set a customer's plan to Business, the log cannot tell you whether that customer was on Starter, on Enterprise, or on Business already. Without the old value you cannot judge the change, and you cannot restore it.

Arguments can also mislead about scope. "Update where status is active" says nothing about which 1,200 rows that was. A success status says little too: it can cover a change to every row, or to none.

Whose agent was it, and what did it hold? ​

If an agent uses a person's key, the record says the person did it. If it uses a shared service account, the record says nobody did. Neither helps. You need both names, the agent and the person it acted for, and what it held at the time, since a key can be wider than the job.

How do you put it back? ​

A log is a story about what happened. It cannot undo anything. If getting back to the earlier state means reading 1,200 lines and writing a repair script, then the audit log has told you what you lost and left you to recover it alone. And the repair script is one more bulk change, written in a hurry.

Record the change, not only the call ​

So keep two records. They do different jobs.

Log of callsHistory of changes
HoldsWhat the agent asked forWhat the data became
AnswersWhat did it do, and was it allowed?What changed, field by field, from what to what?
Reads likeOne line per callOne entry per record
CatchesMisuse, refused attempts, odd behaviourWrong values, wrong rows, wrong scope
Gets you backNoYes, if changes can be reverted

If you can only build one first, and your agents change data, build the history of changes. A person reviewing an incident needs the before and after. The call log explains how it came about.

How CodeKasten keeps this record ​

Here is what that looks like in practice, using CodeKasten as the example.

Every change has a before and after. An agent works on its own branch, and its work is saved as commits, each with a message saying what it did and why. Open a commit and you see each record that was added, modified or deleted, field by field, with the value before and after. A deleted record is shown with what it held.

The agent is the author. The first time an agent changes something in a workspace, it gets an Agent of its own. Its id is what the record, the commit and any merge request hold, and the app shows it as "Claude, for Maria": which agent, and whose. This post is an example: the record it was drafted in says it was created by "Claude, for" the person who started the session.

What it held is narrower than its person. An agent works with a grant made from a key: which types it may write, which branches, whether it may merge. Settings lists what each agent holds, and you can revoke a grant, or pause or stop the agent. A grant can only be narrowed, so a subagent never holds more than the agent that made it.

Decisions stay with the question. When an agent needs a person, it asks in the Inbox, and the answer is kept with the question: who decided what, and when. A merge into main is a person's act too, on the record.

Putting back is one action. Reverting a commit makes a new commit that undoes it, deleted records included. The history keeps both the mistake and the fix.

There are limits, and an audit log is the wrong place to be vague about them. A commit shows the net change since the last commit, not each step on the way. Reads and refused calls are not kept in the workspace's history. For a coding session the transcript holds every tool call, but it is private to the person whose session it is, so it is their record and not an auditor's. If you need a log of every read for compliance, you need something more than this today.

Keep the record where the agent cannot edit it ​

An audit log the agent can change is not evidence. Three rules cover most of it:

  • Written by the system, not reported by the agent. An agent's account of its work is a summary, not a record. It may be wrong in the same way the work was wrong.
  • Hard to change afterwards. Add to the record, never rewrite it. A correction is a new entry that points at the old one.
  • Out of the agent's reach. The agent should be able to read what it needs, and not be able to delete or rewrite its own trail.

Audit logs and the rules you answer to ​

Requirements depend on your field and your country, so check with whoever advises you. Two references are a useful start: the EU AI Act's Article 12 asks high-risk AI systems to record events automatically over their lifetime, and NIST SP 800-53's AU-3 control sets out what an audit record should contain. Neither says how to build it. Both assume you can reconstruct what happened, and for an agent that changes data, that takes the before and after.

A checklist for your own audit log ​

  1. Give each agent its own identity, with the person it acts for. No shared accounts.
  2. Record what it held at the time, not only what it did.
  3. Log every call, with arguments, target, decision and outcome. Include refusals.
  4. Record each change: every affected record, with its value before and after.
  5. Group changes into units with a reason, so a person can review the job and not a thousand lines.
  6. Link the two, so a change leads back to the job and the session that made it.
  7. Make undo a real operation, tested before you need it.
  8. Keep the trail out of the agent's reach.
  9. Redact secrets and personal data before anything is stored.
  10. Rehearse an incident. Pick a change from last week and answer: who, why, from what to what, and how would we undo it?

FAQ ​

What is the difference between an audit log and observability? ​

Observability helps engineers see how a system is behaving: latency, errors, cost, traces. An audit log lets a person account for what was done and on whose behalf. They overlap, but a trace that is sampled or dropped after a few days is not an audit log.

Should an audit log store prompts and model outputs? ​

Store them with care. They can hold secrets and personal data, so redact them or keep them separately with tighter access. CodeKasten's Claude Code plugin, for one, redacts a transcript before anything leaves the machine.

How do you audit what an AI agent did to a database? ​

Look at the data's own history, not only the agent's calls. If the database has no history of its rows, you only have the log's word for it, which is why it helps to give the agent a copy to work on and compare it with the original before anything goes live.

Try it ​

CodeKasten keeps every change an agent makes as a commit a person can read and revert, under the agent's own name. Open the app, or read about commits and history, grants and coding sessions. For the step before the record, the review, read AI agent approval workflows, and for the whole picture, AI agent guardrails.