DEV Community

Cover image for Your AI agent's logs are lying to you (or don't exist)
Mr Recruiter
Mr Recruiter

Posted on

Your AI agent's logs are lying to you (or don't exist)

Ship an agent to production, have something go wrong, and try to answer a simple question: what did it actually do? For a lot of agent setups, you can't. Not really. And that gap is a security problem hiding as an observability problem.

Here's why it happens. When you build an agent, the interesting stuff is the behaviour, and the logging is the thing you'll add later. So the agent authenticates to your systems, often as a single service account or with one shared key, and it starts making calls. Your downstream systems dutifully log those calls. But they log them as coming from that one identity, doing generic operations. Read. Write. Query. There's no thread tying them back to which agent run caused them, which user request kicked it off, or what the model was actually trying to accomplish when it made the call.

So when you go to investigate, you get a pile of technically-true log lines that tell you almost nothing. The service account read these records. Great. Why? On whose behalf? As part of which task? Was that the agent doing its job, or the agent being manipulated into doing something else? The logs can't tell you, because they were never structured to carry that context.

This gets worse with autonomy. A human doing something suspicious leaves a human-shaped trail you know how to read. An agent in a loop can make hundreds of calls in seconds, and if they all look identical in your logs, spotting the handful that were the actual problem is nearly impossible after the fact. You don't have a needle in a haystack, you have a needle in a stack of identical needles.

A few things help, and they're worth building in from the start rather than bolting on after an incident.

Give every agent its own identity, not a shared service account. This is the foundation for everything else, because it's the difference between "something read the database" and "the invoice-agent read the database." When you've got fifty things sharing one identity, your logs are useless before you even start.

Propagate a trace or correlation ID through the whole chain. When a request comes in and the agent starts making tool calls, tag every one of those calls with an ID that ties back to the originating request and the specific agent run. Then when you investigate, you can pull the whole story of one task instead of guessing which scattered log lines belong together.

Log the agent's decisions, not just its actions. The system call tells you what happened. What you actually want during an incident is why. Log the tool the agent chose, the inputs it decided on, and ideally the reasoning, so you can reconstruct not just that it deleted a record but what convinced it that was the right move. That "what convinced it" is often where a prompt injection reveals itself.

Treat the agent's action log as security telemetry, not debug output. It should go somewhere durable, be retained, and ideally feed whatever monitoring you already run. Debug logs that roll over in an hour are worthless when the question comes three days later.

The uncomfortable test for any agent you've deployed: if it did something harmful right now, could you reconstruct exactly what it did, in what order, triggered by what, within the hour? If the honest answer is no, you don't have an observability gap you'll get to eventually. You have an agent operating in your systems that you fundamentally cannot account for, and that's a security posture whether you meant it to be or not.

Build the logging like you'll need it in a courtroom. Because the day you actually need it, you will.

Top comments (1)

Collapse
 
hannune profile image
Tae Kim

The correlation ID was the piece we kept pushing off and paid for every time something broke. We'd get an alert, dig through logs tied to a shared service account, and still couldn't tell you an hour later which agent run actually caused it. I'd emphasize the log-the-decision part the most: the raw action is almost never enough on its own, what you want is what the model was given, what it chose, and in what sequence, because that's what shows a prompt injection. Also: put the trace ID in the tool call body itself, because a lot of downstream systems rewrite custom headers before writing their own logs.