AI Agent Monitoring: Logs, Measures and Alerts Are Three Different Jobs
By Mara Voss · October 17, 2026
Category: defensive-architecture-security-controls
Agent failures pass every health check. Here is the field set a step record needs, the measures worth computing per task type, and how an alert earns an owner and an action.
Key takeaways
The problem Agents fail while every request succeeds, so uptime and error-rate dashboards show nothing while behaviour drifts, loops or gets manipulated.
Core insight Logging, measuring and alerting are three separate layers: a record describes one step, a measure needs a denominator and a per-task-type baseline, and an alert is a threshold with an owner and a written action.
Practical outcome A trusted step record, baselines kept per task type, and a short alert list with named owners and a rehearsed suspension path gets a team to real detection in weeks rather than quarters.
Nobody pages you when an agent starts behaving badly. The dashboard stays green, the latency graph is flat, the error rate is zero, and the support agent that used to open one customer record per conversation is now opening the whole account history every time a particular phrase appears in an inbound email. Every request succeeded. That is the problem.
Three activities get bundled together under the word monitoring, and they are not the same work: writing down what an agent did, computing measures from those records, and deciding which measures are worth interrupting a human for. Each one fails differently, and a team that skips the middle layer ends up either blind or buried in pages. This guide walks the three layers from a detection standpoint. The companion piece on monitoring agents at runtime covers the surrounding architecture; the material here is about what goes in the record, what you compute from it, and how an alert earns its place.
Three Jobs People Call by One Name
Split them and the design gets much easier.
- A log entry describes one event. It is a fact about a single step: this identity, this tool, these arguments, this result. It answers questions after the fact and it has no opinion about whether anything is wrong.
- A measure is an aggregate with a denominator. Tool calls per run, steps per run, denied actions per hundred runs, approvals requested per task type. A measure only means something against a reference period, which is why a baseline is part of the measure and not a nice extra.
- An alert is a measure, a threshold, an owner and a defined action. Drop any of those four and you have a chart. A threshold with no action attached is the fastest way to teach a team to dismiss notifications.
One clarification worth making early, because it changes what you build: the record you keep for detection is not the same artefact as the record you keep for evidence. Retention, immutability and chain of custody belong to the evidence question, which we treat separately in the evidentiary record an agent is expected to leave behind. Detection needs freshness, dimensions you can group by, and a query path fast enough to use during an incident.
Why a Service Dashboard Cannot See This
A conventional service has a narrow contract. Given an input it returns an output, and deviation shows up as a failure. An agent chooses: which tool, with what arguments, in what order, how many times, and when to stop. Two runs of one task can diverge completely and both be correct, so the only honest definition of abnormal is statistical rather than absolute. Three properties make that harder than it sounds.
The first is non-determinism, which removes your ability to assert on exact outputs. The second is that reasoning leaves no trace. You observe inputs, calls and results, never intent, so a manipulated agent and a confused one look identical from outside. The third is gradualism: a prompt revision, a model upgrade or a new document in the retrieval corpus can move behaviour by a fraction each day, with no request that ever fails.
There is a useful asymmetry in your favour. Anthropic's engineering write-up on building effective agents observes that an agent should gain "ground truth" from the environment at each step, and every one of those environmental returns is an observable you can hold against the agent's own account of what it did. When the model reports a successful write and the tool result says permission denied, that gap is a signal no statistical baseline was needed to find.
The economic side is treated as a security concern too. The OWASP GenAI Security Project lists comprehensive logging, monitoring and anomaly detection among the mitigations for LLM10:2025 Unbounded Consumption, which frames runaway resource use as abuse rather than as a billing annoyance. The advice generalises past cost: keep enough detail to recognise unusual use, and compare it against something.
Decide What One Step Record Has to Carry
Write one record per step, not one per run, and make it carry enough to reconstruct a decision without the transcript. A workable field set: timestamp, run identifier, the agent's own identity, the prompt or template version, the model version, inputs held by reference rather than inline, tool name, tool arguments, result status, the error if there was one, and the final output of the run.
Two constraints on that record matter more than the field list. Redact credentials and personal data as you write, not in a later pipeline stage, because a redaction job that runs on a schedule has already lost. And put the store somewhere the agent's own permissions cannot reach: an agent that can edit its tool inventory can usually edit its history too, and a record the subject can rewrite is not a record. Every layer above this one inherits whatever you leave out here, which is why the field set deserves an argument before the first alert gets written.
Compute Measures Per Task Type, Never Globally
Run the agent through a representative stretch of ordinary production work, then compute per task type: the number of tool calls in a run, the mix of tools used, steps and wall-clock duration, tokens and spend, the rate of tool errors, the rate of refused or denied actions, and the rate of human approvals asked for, granted and turned down.
Keep them separated by task type. A research assistant that fans out across dozens of reads and a payments agent that makes one call and stops have nothing in common, and a global average of the two describes neither. Version every measure against the four things that move behaviour: prompt, model, tool inventory and retrieval corpus. Without that tagging you will see a shift and have no way to say which change produced it.
Write a Short Alert List, Each Entry With a Named Owner
Resist the instinct to alert on everything you can measure. Start with a handful tied to outcomes a defender actually cares about.
- A tool appearing for the first time in a given task type. First use shortly after the agent consumed untrusted external content deserves a human read.
- Any egress attempt outside the allowlist, whether it was blocked or not. Blocked attempts are the cheaper signal and teams routinely discard them.
- An unusual volume of sensitive reads inside a single run, which is the shape that quiet exfiltration takes.
- Authorization denials clustering on one identity. Repeated refusals look like an agent feeling for the edge of its permission set.
- Spend or step count well outside the baseline for that task type, which catches loops, retry storms and deliberate abuse with one rule.
Each entry needs a name beside it and a written response: page somebody, suspend the agent, revoke a credential, or force approval on the next several actions. Rehearse the suspension path before you need it, because a stop button nobody has pulled is a hypothesis. Design work for that path sits in our guide to building a stop, containment and rollback path. For rules that judge an individual call rather than a rate, the detail lives in spotting malicious tool calls.
Track the Slow Shape Change as Well as the Spike
Spikes are the easy half. Compare distributions week over week: tool mix, steps per run, refusal rate, and the share of proposed actions a reviewer rejects. A rejection rate drifting upward says the agent is suggesting worse actions than it used to, and no single run in that trend would have tripped a threshold. Pair the automated side with a person reading a small random sample of runs each week plus every run that raised an alert, because rules only catch behaviour somebody already imagined. Treat those transcripts as sensitive material, and decide in advance who is allowed to open them.
A Shipping Agent, Read as a Worked Example
The split is easier to accept once you have seen a product that draws it. Claude Code's telemetry reference separates metrics from events, and the division is instructive because the metrics are useless for detection. They cover sessions started, lines of code changed, pull requests and commits, cost, token usage, accept-or-reject decisions on edits, and active time. Capacity and spend instruments, every one. None can place a particular command in a particular session.
The events hold the detection signal. The documented names include the user prompt, the tool result, the tool decision, API request, error and refusal, a permission mode change, authentication, a server connection and a skill activation. Two deserve a line on any alert list. The tool decision event carries the outcome and the source of that decision, separating an action a rule allowed from one a person approved. The permission mode change event is how you notice the mode shifting mid-session, which rewrites the meaning of every allowed action after it.
The limits on the same page are the part worth copying. Content is withheld unless you opt in: prompt text, tool parameters, tool content and assistant responses each sit behind a switch. Third-party agent, skill, plugin and server names report as generic placeholders until you enable tool detail, so an unregistered server arrives anonymous. Metrics omit high-cardinality fields, so an identifier present on an event is never attached to a metric. And subprocesses inherit none of the exporter settings, so tools, hooks and servers emit nothing by default. A deeper reading of those gaps sits in what a coding agent's session history leaves out.
On field names there is now a vendor-neutral vocabulary worth borrowing and not yet worth depending on. The OpenTelemetry generative AI conventions define spans, metrics and events for model calls, tool execution, retrieval, memory and whole agent runs, and they left the main semantic conventions repository for a dedicated one with an empty releases list and a placeholder schema URL. Take the attribute names. Do not build a dashboard that breaks when one is renamed.
Re-Baselining Is the Real Cost, and Almost Nobody Budgets It
The expensive part is not the step record and not choosing five alerts. It is that a baseline has a shelf life, and nothing in the usual advice says how short. Four things move behaviour: prompt, model, tool inventory, retrieval corpus. In a team shipping at any pace one of those changes most weeks, and a distribution comparison across that boundary is two different systems plotted on one axis. Add a pipeline that edits prompts or swaps a model on its own and the baseline can be stale before anyone reads it.
So the position: version the baseline against all four inputs, make re-baselining a scheduled task with an owner, and accept that re-establishing normal will cost more time than responding to alerts. A team that will not fund that should not claim to run statistical detection.
If you cannot fund it, the move is not a worse baseline. Drop the distributional alerts and keep the signals that survive a version bump, since they need no reference period. Egress outside the allowlist is wrong on day one and wrong after a model upgrade. A cluster of authorization denials on one identity means the same in both. A tool appearing for the first time in a task type is a set membership question, not a rate. And a mismatch between what the model reports and what the tool returned needs no history at all. Four deterministic rules you maintain beat nine statistical ones you do not.
The telemetry documentation says which half to lean on. Metrics drop high-cardinality attributes by design, so the dimensions needed to group a rate by prompt version or task identifier live on the events, not the counters.
Where this is wrong: on a system whose four inputs are frozen between quarterly releases, a distribution comparison is cheap and informative, and the drift section above becomes the most valuable part of the programme rather than the most fragile. The same holds for a high-volume agent on one narrow task type, where a weekly shift is real rather than noise. The test is whether you can name the date your baseline was last recomputed, and what changed since.
When to Bring in Security Operations and Compliance
Pull both in early if your agents touch regulated data, move money, or act on behalf of named customers. The alert list, the retention period and the access rules for transcripts are decisions with legal weight, and a monitoring store full of customer text becomes a sensitive system in its own right. This article is technical guidance and not a substitute for a formal review.
Place the whole effort inside a framework so it survives a reorganisation. NIST's AI Risk Management Framework names Measure as one of its four functions, alongside Govern, Map and Manage, and monitoring is how Measure stops being a launch checkbox and becomes routine. Begin narrow: a step record you trust, baselines per task type, five alerts with owners. Add the sixth only when an incident or a transcript review shows you what you were missing. And keep the limits in view, since logs record actions and not motives: an agent that looks quiet may simply be doing something you never thought to measure, which is why permission limits remain the control that caps damage while nobody is looking.
Frequently Asked Questions
Which fields should a step record carry at an absolute minimum?
Run identifier, agent identity, prompt and model version, the tool name with its arguments and result status, and the run's final output. Strip credentials and personal data as the record is written, and keep the store outside the agent's own permissions.
Can we build this on the observability platform we already run?
Usually yes for ingestion, storage and alert routing. What it will not have is the agent-specific dimensions, such as tool arguments, prompt version and task type, or any notion of a behavioural baseline. Those you add yourself.
What is the difference between a monitoring record and an audit record?
Purpose, and therefore design. Monitoring data has to be fresh, groupable and fast to query during an incident. Audit data has to be defensible later, which pushes it towards immutability, defined retention and chain of custody.
Will any of this detect a prompt injection attempt?
It detects consequences rather than attempts: a tool used for the first time, an egress attempt that was refused, a read volume well outside the baseline. Plenty of injection attempts leave no trace at all, so keep permission limits doing the load-bearing work.