Notes on AI Agent Governance

Your AI Agent's Audit Log Is Probably Lying to You

Most AI agent audit logs record what the agent chose to admit. Here's why the log's position in the stack decides whether it's evidence, and how to build one an auditor can actually trust.

Ask an engineer how they'd prove what their autonomous agent did last week, and you'll usually hear one of two answers. Either "we log every tool call" or "the model provider keeps traces." Both are better than nothing. Neither is evidence. The problem isn't the format of the log. It's where the log lives.

This piece is about a single idea that changes how you design agent observability: an audit record is only as trustworthy as its position in the stack. Get the position wrong and no amount of cryptography saves you. Get it right and even a simple hash chain becomes something an auditor, a regulator, or a court will accept.

The self-reporting problem

Most agent logging is self-reporting. The agent framework wraps its own tool calls, writes them to a file or an observability backend, and moves on. LangChain callbacks, custom decorators around function-calling handlers, OpenTelemetry spans emitted from inside the agent loop. All of these produce a record of what the agent told you it was doing.

That distinction matters more than it sounds. When the logging code runs inside the same process as the agent, the log is a downstream effect of the agent's behavior, not an independent observation of it. If the agent skips a step, logs the wrong arguments, or a bug in the framework drops a call, the log faithfully records the fiction. You end up with a beautifully structured, timestamped account of something that may not have happened.

Security people have a name for this class of mistake. You're trusting the thing you're supposed to be watching. It's the same reason you don't let an application write its own firewall rules, and the same reason financial controls separate the person who approves a payment from the person who requests it. Self-attestation is not attestation.

"But we sign our logs"

Signing helps, but ask what you're signing. If the agent process holds the signing key and signs its own records, you've proven that this process wrote these bytes. You have not proven the bytes are true. A compromised or hallucinating agent signs false records exactly as convincingly as true ones. Cryptographic signatures answer "did this come from who I think, unmodified?" They say nothing about "did the described event actually occur?" Confusing those two questions is the most common mistake in agent audit design.

Position beats format

Here's the mental model worth keeping: an audit log is trustworthy in proportion to how hard it is for the observed system to influence it. Rank your options by that single axis.

In-process logging (callbacks, decorators, spans from the agent loop). The observed system fully controls the log. Weakest position. Fine for debugging, useless as evidence.

Sidecar or wrapper logging (a CLI wrapper, an MCP server the agent talks to). Better, because the log lives outside the agent's memory space. But agents with real system access route around wrappers constantly. If your agent can open a raw socket, shell out, or hit an API endpoint the wrapper doesn't intercept, the wrapper logged a subset of reality and called it complete. The gap is invisible precisely because the unlogged actions are the ones you'd most want to see.

Chokepoint logging (a component every action must physically pass through). Strongest position. If the observed system cannot complete its work without going through the recorder, the recorder sees everything by construction, not by cooperation.

The whole game is finding a real chokepoint. For an autonomous agent, there's a natural one that's easy to miss: nearly every consequential thing an agent does starts as a request to its model provider. The model proposes an action, the runtime executes it. If you sit on that connection, between the agent and the Anthropic, OpenAI, or Gemini endpoint, you observe the proposal before anything touches a filesystem, a database, or a production API.

That's the difference between watching what the agent admits and watching what the model actually asked for.

Why the network layer is the honest layer

Putting governance on the HTTP connection has properties in-process logging can't match.

The agent can't route around it. The model call is not optional. An agent that skips the model isn't doing agentic work anymore. Compare that to an MCP server, which is one tool source among many, or a sandbox, which the agent can sometimes escape or which breaks legitimate functionality by over-restricting.

It's honest about scope. A proxy on the API connection sees model-proposed actions. It's clear about what it does and doesn't cover, which is more than you can say for a wrapper that silently misses whatever it didn't think to intercept.

It decouples observation from the code being observed. Update your agent, swap frameworks, refactor the tool layer. The audit record doesn't care, because it isn't wired into your call sites. This alone eliminates a whole category of "we stopped logging that six weeks ago and nobody noticed" incidents.

The tradeoff is real and worth stating plainly. A network chokepoint governs actions that flow through the model connection. Out-of-band side effects (a cron job the agent wrote last week, a webhook it registered) execute on their own path later. No single layer catches everything, and anyone who tells you otherwise is selling. But the model connection is the widest, least-bypassable point in the agent's action loop, which is exactly why it's the right place to start.

Making the record tamper-evident, correctly

Once you're observing from a real chokepoint, you can make the record defensible. This is where the crypto everyone reaches for finally does useful work, because now you're signing observations, not confessions.

Two primitives do the heavy lifting.

Hash chaining makes the log append-only in a way anyone can check. Each record includes the hash of the previous record, so entry N commits to the entire history before it. Delete or edit any entry and every hash after it breaks. This is the same construction behind Git commits and Certificate Transparency logs (RFC 6962), and it's well understood. You can't quietly remove the embarrassing entry from the middle; you'd have to rewrite everything after it and hope nobody kept a later hash.

Signatures bind the chain to a key. Ed25519 (RFC 8032) is the sensible default: fast, small 64-byte signatures, and no dependence on a good random number generator at signing time, which has burned other schemes. Sign each record or checkpoint, publish the public key, and now anyone can verify authenticity independently, without access to your systems or your trust.

Combine them and you get a record with a specific, honest property: tamper-evident, not tamper-proof. You cannot stop someone with disk access from altering bytes. You can guarantee that if they do, verification fails and the alteration is detectable. That's the correct goal. Aiming for tamper-proof leads people to overbuild (HSMs, blockchains, notaries) when detectability plus an offsite copy of the latest hash gets you most of the value for a fraction of the complexity.

A verification you can hand to an auditor

The test of an audit trail isn't whether you trust it. It's whether someone who distrusts you can check it. A good design lets an outside party take your log, your public key, and a verification tool, and confirm three things without talking to you: every signature is valid, the hash chain is unbroken, and the record they're looking at is the same one you committed to earlier. If verification requires access to your infrastructure, you've built a log, not evidence. This is the line regulated teams care about, and it maps directly onto what frameworks like SOC 2 and the EU AI Act's logging and traceability expectations are reaching for: proof that survives independent scrutiny.

Classify before you execute, not after

One more shift falls out of sitting on the connection. If you're already inspecting each proposed action before it executes, you can decide about it, not just record it. Classify every model-proposed action as ALLOW or DENY before it reaches the system.

Be deterministic where determinism is honest. "Never let the agent DROP a production table" is a rule, not a judgment call, and should be enforced as one. Where a decision genuinely needs judgment, say so, and escalate to a human with a scoped, one-time approval rather than pretending a policy engine has an opinion it doesn't. The failure mode to avoid is dressing up guesses as rules. An honest governance layer tells you which decisions were mechanical and which were judgment, because that distinction is itself audit-relevant.

Deciding before execution also fixes the timing problem in after-the-fact logging: by the time your in-process log records the destructive call, the table is already gone. Prevention lives upstream of the action or it doesn't live at all.

The takeaway

Design your agent audit trail around one question: can the agent influence its own record? If yes, you have telemetry, which is useful for debugging and worthless as proof. If no, because the record is captured at a chokepoint the agent must pass through, then hash chaining and Ed25519 signatures turn that capture into evidence that holds up to someone who doesn't trust you.

Format is the easy part. Position is the whole thing.

This is exactly the architecture Atested implements. It installs as an HTTP proxy between your agent and its model provider with a single environment variable, in about five minutes, and works with Anthropic, OpenAI, Gemini, Claude Code, OpenClaw, and other HTTP-based agents. Every model-proposed action is classified ALLOW or DENY before execution, and each decision is written to an Ed25519-signed, hash-chained record anyone can verify with the public key. It sits on the connection rather than in the conversation, so it adds zero token overhead and imperceptible latency while preserving full agent capability. If you're running agents on your own machine, the free tier is a fast way to see what your agents are actually proposing. Learn more at https/www.Atested.com.