Why AI agent observability starts with events, not dashboards
← Back to Blog
August 2026·AI Engineering·12 min read

Why AI agent observability starts with events, not dashboards

A dashboard can tell me that an agent failed. A useful event trail tells me which decision, tool call, approval, or external dependency caused the failure — and whether the system recovered safely.

The Green Dashboard That Explained Nothing

Traditional application monitoring gives us a comforting vocabulary: uptime, response time, error rate, CPU usage, and database latency. Those signals still matter in an AI system. The API can be healthy, the queue can be moving, and every request can return HTTP 200 — while the agent is doing the wrong thing.

An agent can select an irrelevant tool, retrieve the wrong record, misunderstand an approval, repeat an expensive call, or produce a confident answer from incomplete evidence. None of those failures necessarily throws an exception. From the infrastructure dashboard, the run may look perfect.

This is why I think about agent observability as a product feature rather than a collection of charts. The goal is not merely to know that something happened. The goal is to reconstruct what the system knew, what it decided, what it attempted, what changed outside the model, and what the user eventually experienced.

That reconstruction begins with events. Dashboards, alerts, traces, and reports are views built on top of them. If the underlying events are vague or disconnected, a more impressive dashboard only presents the same uncertainty more attractively.

An Agent Run Is A Distributed Workflow

A useful mental model is that an agent run is not one model response. It is a workflow spread across several components. The user provides input. The application assembles context. A model proposes the next step. A tool talks to another service. A queue may delay execution. A person may approve an action. The system may retry, summarize, or hand the task to another process.

Each boundary can change the result. A correct model decision can fail because a tool schema changed. A successful tool call can still produce the wrong business outcome because it used a stale identifier. A retry can duplicate an external side effect. An approval can arrive after the operation has expired.

Logging only the final answer erases this structure. Logging every raw prompt and response creates a large pile of sensitive text without necessarily explaining the workflow. Good observability sits between those extremes: it records structured events that describe important transitions and connects them into one run.

The question I want the data to answer is simple: if a user reports a problem tomorrow, can I follow the operation from request to final state without guessing?

Give Every Operation A Stable Identity

The first requirement is correlation. One user request can generate several model calls, tool calls, retries, queue jobs, and approval messages. They need a shared operation ID that survives those boundaries.

I distinguish the overall operation from an individual attempt. The operation represents the user's intended job. An attempt represents one execution of part of that job. If a worker crashes and retries, the operation remains the same while the attempt changes. This makes it possible to see that three successful HTTP calls were actually three attempts to perform one action.

Child identifiers are useful for model calls and tool calls, but they should always point back to the operation. The same applies when one agent delegates work to another. Without that parent relationship, logs become isolated fragments ordered by timestamp, and timing alone is a poor way to reconstruct causality.

A stable identity also supports idempotency. Before repeating a write, the system can ask whether this operation already produced the intended side effect. That turns observability from passive inspection into part of the safety architecture.

Record State Transitions, Not Diary Entries

Free-form log messages are easy to add and difficult to query. “Agent processing request” says almost nothing. “Tool failed” leaves the most important questions unanswered.

I prefer explicit event types such as operation.started, context.prepared, model.completed, tool.requested, tool.succeeded, tool.failed, approval.requested, approval.received, operation.completed, and operation.escalated. The exact names matter less than consistency.

Each event carries a small common envelope: event name, timestamp, operation ID, attempt ID, component, version, environment, and outcome. Event-specific fields then describe the transition. A tool event may include the tool name, permission class, duration, result category, and whether a side effect was confirmed. An approval event may include the policy that required review and the decision, without copying the entire private conversation.

These are facts about the workflow, not a narrative written for a human. A human-readable explanation can be generated later. Structured facts let me query every operation that called a write tool twice, every run that completed after an authorization error, or every model version associated with an increase in escalations.

Observe Decisions Without Pretending To Read Minds

Teams sometimes try to log the model's hidden reasoning as if it were a reliable explanation. That creates security, privacy, and product problems. It also confuses generated text with the actual cause of system behavior.

I care about observable decision artifacts instead: which action was selected, which alternatives were available, which policy applied, which evidence identifiers were supplied, and what confidence or uncertainty signal the workflow exposed. If the model chose a customer lookup tool, I record the selection and the validated arguments. I do not need an unrestricted internal monologue.

The distinction matters during debugging. The system may produce an elegant explanation after the fact that does not match the tool trace. The trace is stronger evidence. Likewise, if a model claims that an email was sent but there is no successful send event or provider identifier, the operation is not complete.

Explanations are valuable when they are tied to verifiable inputs and events. “I stopped because the account lookup returned two matching records” is useful when the trace actually contains two candidate identifiers and an escalation event.

Tool Calls Are The Most Important Boundary

Model output becomes operationally important when it crosses a tool boundary. Reads introduce evidence. Writes introduce side effects. Both deserve more detail than ordinary debug logging.

For a tool request, I record the tool name, schema version, argument shape, access policy, timeout, and a safe fingerprint of important inputs. Sensitive values should be redacted or tokenized. The objective is to distinguish calls and validate behavior, not to copy secrets into another database.

For the result, I record the status, duration, retryability, number of returned items, provider request ID when available, and whether the expected external state was confirmed. A timeout is not proof that a write failed. The provider may have completed the action and lost the response. That should produce an uncertain state, followed by reconciliation, rather than an automatic duplicate.

This event trail makes partial failure visible. It shows the difference between “the agent never attempted the action,” “the provider rejected it,” “the provider accepted it,” and “the outcome could not be confirmed.” Those cases require different recovery paths and should not collapse into one red error badge.

Version Everything That Can Change Behavior

An operation is difficult to reproduce if its trace says only that a model was called. Agent behavior depends on the model, prompt, tool descriptions, schemas, routing rules, retrieval configuration, memory policy, and application code.

I attach versions or content hashes to the relevant events. The data does not need to contain the complete prompt; it needs a reliable reference to the version stored elsewhere. This lets me compare failures before and after a deployment and prevents a silent prompt edit from becoming an invisible production change.

Model providers can also change behavior behind a stable product name. When available, I record the resolved model version and provider request ID. I capture generation settings that materially affect output, along with token usage and latency.

Version data turns “the agent became worse recently” into a testable question. I can segment completion, correction, and escalation rates by release instead of relying on memory and anecdotes.

Separate Technical Success From Product Success

A tool can return successfully while the user's job remains unfinished. An operation can finish without an exception while producing a result that a person immediately corrects. Infrastructure success, workflow success, and product success are different measurements.

I track stage outcomes: whether context was available, whether the expected evidence was retrieved, whether tools completed, whether approval was obtained, and whether the final state matched the requested job. Then I add product signals such as user correction, escalation, abandonment, repeated request, and confirmed completion.

This prevents a misleading metric like “99% successful agent runs.” Successful according to which layer? A 200 response measures transport. A completed event measures workflow termination. Neither proves that the correct customer record changed or that the answer was useful.

The most useful metrics are close to the job. For a support workflow, that may be correct routing and resolution without an avoidable handoff. For a publishing workflow, it may be a validated draft, explicit approval, exactly one publication, and a stored public URL.

Design Redaction Before Collecting Everything

Agent systems touch unusually rich data: conversations, documents, account records, credentials, and tool results. “Log everything now and clean it later” is not a safe observability strategy.

I start by deciding which questions the event stream must answer. Then I collect the smallest fields that answer them. Identifiers can often be hashed or replaced with internal references. Request categories can replace raw text. Counts, status codes, and schema validation results are usually more useful for aggregate analysis than full payloads.

When raw content is genuinely necessary for a limited debugging workflow, it should have stricter access, shorter retention, and visible audit records. Secrets should never enter normal logs. The same applies to hidden credentials embedded inside tool arguments or provider errors.

Redaction needs tests. It is easy to redact the main prompt and forget that a tool exception echoes the full request. Observability code is part of the data boundary and should be reviewed with the same care as the feature itself.

Build Dashboards From Questions

Once the events are trustworthy, dashboards become useful. I avoid starting with whichever charts the monitoring platform makes easiest. I start with operational questions.

Which workflow stage fails most often? Which tools create the highest tail latency? How many writes enter an uncertain state? Which task types require human approval? Did a release change the escalation rate? Are retries recovering temporary failures or merely multiplying cost?

A small overview can show operation volume, verified completion, escalation, correction, cost, and latency. From there, every number should lead to a trace or a segmented view. An aggregate spike without a path to representative operations creates awareness but not understanding.

I also preserve a view of individual timelines. Agent incidents are often about sequence: approval arrived, a retry started, an earlier attempt completed late, and the final state became duplicated. A table of totals cannot explain that race. A chronological event trail can.

Alert On Consequences And Broken Invariants

Alerts based on every tool error quickly become noise. Temporary errors are expected in distributed systems, and a retry may recover without affecting the user.

I prefer alerts for broken invariants and meaningful consequences: a write executed without the required approval, one operation produced multiple external side effects, an operation remained uncertain beyond its reconciliation window, a privileged tool was selected outside its allowed workflow, or verified completion dropped sharply for a high-value task.

Technical alerts still matter for queue depth, provider errors, and latency. The event model lets me connect them to user impact. A provider error affecting an optional enrichment step is different from the same error blocking every account update.

An alert should include enough context to begin investigation: affected workflow, release version, operation IDs, failed invariant, and a link to representative traces. “AI error rate high” sends the engineer back to the beginning.

Use Production Traces To Improve Evaluation

Offline evaluation and production observability should form one loop. Evaluation tests expected behavior before release. Production events reveal failure shapes the test set did not anticipate.

When a trace exposes a new problem, I turn the safe, anonymized shape of that operation into a regression case. That may be an ambiguous identifier, a delayed tool response, a correction after summary compression, or an approval that arrives out of order. The expected outcome becomes explicit, and future versions must handle it.

The event schema should therefore be compatible with the evaluation schema. If production records tool selection, policy decisions, side-effect confirmation, and final outcome, the test harness should assert the same concepts. This avoids two separate definitions of success.

Over time, the most valuable evaluation dataset is not invented in a workshop. It is distilled from real work, incidents, corrections, and successful edge cases — with private data removed.

Start Small, But Make The Trail Complete

A useful first version does not require a specialized AI observability platform. It requires disciplined events and stable correlation. An application log, database table, or existing tracing system can be enough if it preserves the workflow structure.

I would begin with one important operation and instrument it end to end. Give it an operation ID. Record start and completion. Record every model and tool boundary. Record approval and external side-effect confirmation. Attach versions. Add redaction tests. Then reconstruct several real runs manually.

That exercise reveals missing events quickly. If I cannot explain a run without opening unrelated logs or guessing from timestamps, the trail is incomplete. Once the event model works for one workflow, shared libraries can make it consistent across the rest of the system.

Only then do I invest in elaborate charts. The event stream is the durable asset. Monitoring vendors, visualization tools, and dashboards can change without losing the history of how the product behaves.

Observability Is How An Agent Earns Trust

AI systems will make unexpected decisions, and external services will fail in ordinary ways. Trust does not come from pretending that uncertainty can be removed. It comes from making the workflow inspectable, limiting consequences, and providing a clear recovery path.

Good agent observability connects the user's job to model decisions, tool calls, approvals, and verified external state. It distinguishes an attempt from an operation, a successful request from a successful outcome, and an explanation from evidence.

A dashboard is useful after those distinctions exist. Before that, it can only count events the system failed to define.

If I cannot reconstruct why an agent acted, what changed, and whether the outcome was verified, I do not have observability. I have logs.
Igor Gawrys
Igor Gawrys
AI Engineer & IT Consultant · Katowice, Poland