What to Log When an AI Agent Acts on Your Behalf
The minimum audit trail that lets you reconstruct why an autonomous job did what it did — including the one artefact you cannot trust.
- Author
- Prabhash Jha
- Published
- Reading time
- 14 min read
The reason I know exactly what to log when an AI agent acts on your behalf is that I once ran a job whose only record of having ever fired was an untracked file and a broken connection. Seventy minutes of unattended writing, a complete draft, and no evidence anywhere else that the run had ever started. If you had asked me the next morning whether the agent had done what it was told to, I could not have honestly answered, because there was no artefact I could point to other than the one produced by the agent itself — and the one produced by the agent itself is exactly the one you cannot trust.
This post is the operating manual that came out of that morning. It is not the compliance guide the platform vendors are writing. It is the honest small-shop version: the minimum log you need if you have decided to hand a machine the authority to write to your git repository, push to your live site, send an email under your name, or move money in your account. Everything below is from having run agents that do at least the first two of those things, on this website, unattended.
The morning that made me write logs
The first autonomous publishing run on this site was supposed to write three posts overnight and commit them. It died at seventy minutes. The connection that carried the agent’s session to my machine dropped, the process on the far side terminated, and the local environment had exactly what a local environment has when a process dies: an untracked file, no commit, no log entry, no evidence that the job had ever started.
I found this out the next morning by looking at git status. There was a file. There was no cover for it. There were no internal links from any older post to it. There was no line in a run log saying “at 21:04 the agent picked topic X”. There was nothing except a Markdown file with a plausible slug and 3,141 words of prose that could have been written any time in the previous six hours.
The failure was not the connection. The failure was that the entire evidence chain for whether the agent had done its job lived inside the agent’s own process. When that process died, so did the evidence. I could see that a thing had been written; I could not see why it had been written, when, what topic it had rejected on the way, or whether any of the three posts it was supposed to write had actually been attempted. I had to reconstruct all of that from the file itself, which is the equivalent of asking a defendant to write their own witness statement.
The very next thing I did that day was change the procedure so the run log was opened at the start of the run, not at the end. Every step in this post is a scar left by that morning.
Two categories: intent and effect
There are two kinds of thing you have to log when an agent acts on your behalf, and confusing them is where most audit trails go wrong.
Intent is what the agent chose to do. Which action it decided on, why, what other actions it considered and rejected, and — the field almost every vendor logging framework leaves out — what it explicitly refused to do.
Effect is what actually happened as a result. The commit sha, the API response, the file that landed on disk, the row that was inserted, the money that moved.
Intent without effect is a plan. Effect without intent is a mystery. You need both, and you need them cross-referenced by a stable identifier that survives whether the agent finished, crashed, was killed by the operator, or was rate-limited by an upstream API.
The distinction matters because you are going to have exactly one job in the middle of the night, one day, that only produced half of these things. When that happens, you need to be able to look at the log and answer, in under a minute, whether the agent got as far as deciding what to do but crashed before doing it (safe, retry), decided what to do and did some of it (dangerous, investigate), or did the thing but never got to record that it had done it (worst, because the next run will probably do it again).
The one artefact you cannot trust
The agent’s own summary of its run is unreliable, for three reasons that stack.
First, the summary is written by the same actor whose behaviour it describes. This is a category of evidence a court would exclude, and there is no reason to hold your own audit trail to a lower standard than the one you would demand of a witness in a room.
Second, the summary is written from inside the process it summarises. If the process died before the summary got written, there is no summary. If the process died after the summary got written but before the effect landed, the summary reports an effect that did not happen. The only summary you can trust is one you would still have if the process were killed at any point in its execution, and the summary written by the process itself is not one of those.
Third, and this is the failure mode most people underestimate: the summary is optimised. The model has been trained to produce a coherent narrative of what it did, which means it will fill in gaps to make the narrative hang together. It is not deliberately lying. It is doing the thing it was trained to do, which is to produce fluent explanation. If you rely on the agent’s own after-action report as your evidence chain, you are relying on a fluent explanation, which is exactly the wrong thing to rely on when you need to know what really happened.
The rule that comes out of these three: log the effects from outside the agent, log the intents from inside the agent, and never let the agent be the only witness to its own actions.
The minimum log
The compliance guides are proposing thirteen-field logs with policy pointers, tenant IDs, GDPR retention markers, and a five-layer taxonomy. If you work at a bank, follow the compliance guides. If you are a founder who has given an agent access to your git repository and your Cloudflare account, you need something considerably shorter, considerably more honest, and considerably more likely to actually get written every time. Here it is.
1. Run ID. A UUID or a timestamp-slug generated at the start of the run and written to disk before the agent does anything else. Every subsequent log line, every commit message the agent writes, every file it creates, references this ID. If the process dies at second three, this file is your evidence that the run happened. If the process dies at second thirty and produces an orphan file with the run ID in its filename, you know at a glance which run to look at when reconstructing.
2. Started-at, ended-at, exit reason. Stored outside the agent’s own process, in a file the wrapping script owns. The exit reason is the honest one: “clean exit”, “operator killed”, “connection dropped”, “hit iteration cap”, “raised exception”. “Completed successfully” is not an exit reason; it is a summary, and it belongs elsewhere.
3. Inputs. The prompt the agent was given, the configuration file it read, the environment variables that were set, and — critically — the versions of any tools or models it used. If the agent picks up a slightly different model tomorrow because you upgraded the endpoint, the log for today needs to say which model ran today, because next week when you compare outputs you will not remember.
4. Intent-per-step. For each decision the agent makes — pick a topic, choose a category, decide to refresh vs write new, decide to commit — record the choice, the alternatives that were considered, and the reason the chosen one won. This is where the “the agent’s own summary” concern applies most: keep this log line short and factual, not narrative. “Chose X over Y because Y failed the four-part test” is auditable. “Considered several options and settled on X after careful thought” is prose.
5. Effects, from outside. Every write the agent commits — a git commit sha, an API call and its HTTP status, a file created on disk with its byte size, an email queued with its message ID — is recorded by the wrapping script or the platform, not by the agent itself. The record survives the agent dying, and it cannot be embellished by the same process that produced it.
6. Declines. The single most useful field, and the one nobody writes. Every time the agent explicitly decided not to do something — rejected a topic as failing a safety rule, refused to publish a draft under the word-count floor, backed off a commit because the build gate failed — log it, with the reason. When you audit an agent’s behaviour six weeks later, the declines tell you as much about whether the safety constraints are working as the actions do.
7. Retries and failures inside the run. Not just the final exit — every attempt that failed and was retried. A run that hit the API three times before succeeding is a different animal from a run that succeeded first go, and if you never log the difference, you will not spot the day an upstream provider quietly starts failing.
Seven fields. Compliance vendors will tell you to log fifty. If you can write seven honestly, every time, the seven you write will be worth more than fifty that get logged once and skipped whenever the run is under time pressure.
Where to store it so it survives the run dying
The one lesson from the morning that started this post is that the log has to live outside the process it describes. That means:
- The run ID gets written to disk in the first thirty seconds of the run, before the agent does any real work, in a file whose name contains the run ID.
- Every log line is flushed to disk as it is written, not buffered. Buffered logs are lost logs when the process dies.
- The exit is recorded by the wrapping script, not by the agent. If the agent is the one recording that it exited cleanly, the case where the agent lied about that is exactly the case you cannot detect.
- Wherever practical, log to two places — a local file and something the operator can inspect from another device. On this site, that means a Markdown run log in the repo and, for the failures that matter, an issue in the repo’s own issue tracker. If the machine that ran the job is not reachable, the issue on GitHub is.
The two-places rule is the small-shop equivalent of what large systems call “log shipping” or “immutable audit sinks”. You do not need Kafka. You need any two places that are not both going to be down at the same time as the process that generated the log.
What “reconstruct why the agent did X” actually looks like
The test of whether your log is working is not whether it has the right fields. It is whether, six weeks after a run, you can pick a specific action and answer the question: why did the agent do this? without asking the agent.
Concretely, for this site: pick any published post. Now, using only the log, answer: which topic ID did it come from, why was that topic chosen over the others in the same category on that day, which alternatives were rejected during research, and what commit sha carried the file to main? If any of these four cannot be answered from the log without opening the post itself, the log is missing something.
For a customer-facing agent, the test is: pick any message the agent sent to a customer. Answer: which conversation context produced it, which policy check ran on it before it was sent, which alternative responses were generated and rejected, and which message ID the outgoing channel returned. Same test, different verbs.
If you cannot pass the test, add fields until you can. If you can pass the test easily, resist the temptation to add more fields “just in case” — the fields you never use are the fields your successor will not write when the log system gets ported to a new stack in eighteen months.
Retention: shorter than you think, longer than you want
The compliance frameworks give retention numbers, and they are worth citing because they are the floor: SOC 2 evidence typically covers twelve months, and the EU AI Act guidance for high-risk systems points to at least six months of decision logs unless another law extends the window. If you are anywhere near either regime, you meet the floor.
Under the floor, be honest about what you are trying to answer. For a solo operator running agents against their own systems, the useful retention is “long enough that any pattern of behaviour that would concern you has had time to become visible” — which in my experience is roughly one to three months of full logs plus a summarised long tail. Longer than that and the logs stop being read; shorter and you cannot see the drift.
Whatever you settle on, write it into the procedure. An unstated retention rule becomes “as long as the disk lasts” by default, and disks are neither compliant nor useful.
The specific traps that catch small teams
Six things that have caught me or someone I know running agent workflows on their own infrastructure. Fix them once and never think about them again.
Trap one: logging into the same file the agent is writing. The log line and the agent’s output land in the same file, and the log line is what gets truncated when the agent crashes mid-write. Separate the log file from the artefact file. Always.
Trap two: logging via the same network call that is failing. A remote logging endpoint is fine until the day the network is the thing that broke, at which point the log of the network failure is the log line that could not be written because the network was broken. Log to disk first, ship to remote later.
Trap three: logging only in the happy path. The try block logs “action succeeded”; the except block logs nothing because the developer assumed the exception itself was the log. The exception is not the log. The exception is the reason for the log line that also needs to say what the agent was trying to do when the exception fired.
Trap four: logging the agent’s chain-of-thought verbatim. Model chain-of-thought can be enormous, unstable across model versions, and often contains material that should not be persisted (customer data quoted back to the model, tokens, error messages containing secrets). Log the intent — the decision, the alternatives, the reason — as a short structured field, not the whole reasoning trace.
Trap five: logging without a run ID that links intent to effect. If your intent log lives in one file and your effect log lives in another and they share no identifier, you have two logs, not one audit trail. Every log line, everywhere, carries the run ID.
Trap six: assuming the model’s summary of the run is the log. It is not. The model’s summary is a piece of evidence produced by the actor being audited. It is useful; it is not sufficient. Read it and then read the log the wrapping script wrote, and if the two disagree, believe the log.
The five-minute test for any agent you run today
If you already run agents on your own systems, do this: pick a run from any time in the last week. Pick one action inside that run — one commit, one email, one API call. Now, without opening the agent’s output, answer four questions from your logs.
- Which run did this action belong to?
- What was the agent trying to do at that moment?
- What did it consider doing instead, and why did it choose this?
- Did the action succeed, and what was the effect on the outside world?
If you can answer all four in under two minutes, you have a log. If you cannot, you have hope, and hope does not stand up in a review.
Fix the missing field this week. Not next quarter. The next agent run is either going to prove the log works or expose that it does not, and it is far cheaper to be the one who discovers the gap than to be the one whose customer discovered it first.
Where this fits with the rest of the work
The reason to log at all is that the space of failures an agent can produce is larger than the space of failures a human can. A human who forgets to send an email leaves an inbox; an agent that forgets to send an email leaves a log line that is not written, which is a different — and easier to miss — kind of evidence. The specific case where the workflow reports success and does nothing is covered in The automation failure nobody catches: the workflow that runs green and does nothing.
If your problem is upstream of “what do I log” — you have not yet decided which tasks to hand to an agent at all — start with How to automate your work with AI, which frames the choice.
If your interest is broader — where the whole direction of unattended AI systems is heading, and what that means for jobs and organisations built around human sign-off — the further-out picture is in AI is heading toward autonomy: what dark factories tell us about what’s next.
The one-sentence version
Log intent from inside the agent, log effect from outside the agent, cross-reference both by a run ID that survives the process dying, and treat the agent’s own summary of its run as evidence to be checked against the log rather than as the log itself. Everything else is variation on those four rules, and the day you skip any of the four is the day you find out which one you skipped.