AI Agent Monitoring: Why Exit Codes Aren't Enough

Each monitoring signal proves less than its label implies. What process state, exit codes and the repository diff can each tell you, and what none of them can.

->::&&~$AI AGENT MONITORINGAuricIDE · Blog

The quiet terminal and the clean exit

Three terminals sit open on a second screen. Two keep printing. The third has shown one line for nine minutes, its cursor blinking, no error anywhere.

That agent might be thinking. It might be running a slow command. It might be waiting for permission it never asked for out loud. It might be stuck. The terminal looks the same in all four cases. A live process proves only that the operating system has not ended it, which says about as much as a lit office window says about the work inside.

A finished process can be just as unclear. An agent can look in the wrong folder, change nothing useful, and exit with code 0. Another can make exactly the right change and then crash while cleaning up. Both process states are accurate. Neither says anything about whether the task went well.

Exit code vs. what actually happened
Two separate facts
Exit code0
Task outcomecorrect

The common case, and the one that makes exit code feel trustworthy. It only holds because the two facts happen to agree here.

Why doesn't more monitoring fix this?

Because the problem is not how many signals you have. Each one proves less than its label implies.

The obvious explanation is that there is not enough monitoring, so the reflex is to add some. A dashboard. An alert. A third pane on the second screen. That explanation is right about the risk and wrong about the problem in front of you. A 2026 state-of-market survey found 52% mean monitoring coverage across deployed agents, leaving 48% without monitoring or security coverage. It also found that 54% of organizations had experienced or suspected an AI agent security or data-privacy incident in the previous 12 months, as reported by the AI agent security market survey. Gravitee surveyed 750 engineering leaders in April 2026, and the gap those numbers describe is real enough.

Coverage and clarity are different problems. Watching three uncertain output streams instead of one resolves none of them. Liveness says the process exists. An exit code covers the ending. Neither answers whether the diff is any good, and adding a fourth pane that also cannot answer it does not help.

So the question worth asking about any signal is not whether you have it. It is what that signal is unable to prove, and which other signal covers that gap.

What can each signal actually prove?

Less than its name suggests. That is why a useful view shows several of them side by side.

Signal Useful for Still cannot tell you
Process state Whether the agent is running or finished Whether current activity is useful
Exit code Whether the child process reported success or failure Whether the requested result is correct
Recent activity Whether output or tool activity continues Whether the agent has a sound plan
Terminal tail Recent errors, prompts, retries, and commands Full intent or complete history
Dispatch history Assignments, retries, and stop decisions Reasoning that was never recorded
Repository diff and tests What changed and whether checks pass Whether the change satisfies the request

Process state and recent output are good for sorting cases and poor at measuring progress. A build runs silent for minutes. A permission prompt can redraw itself and look like activity while the agent is blocked on you. A bad plan prints as busily as a good one.

The terminal tail carries more. It is still free-form text. It might show the prompt or the rejected command. It might have scrolled past the thing that mattered.

The agent edited the wrong file, ran no failing command, and stopped.

Which signal do you check
What it shows
Catches the problem?no

finished

Confirms the process ended. Says nothing about which file it touched.

The last row is the one that closes the loop, and it is the one that costs a person's attention rather than a glance at a screen. Read exit codes after a run ends, then compare them with the diff, the tests, and what was actually asked for. A failed run can leave a useful partial change behind. A clean exit can leave the repository untouched.

Dispatch history is worth logging for the same reason. It records why work was assigned, retried or stopped, so a single case can be reviewed later without reading a second activity feed. A long-running benchmark illustrates why control flow belongs in the record. GPT-5.4 using wait_for reached a 69% success rate at a median cost of $0.48 per task, while sleep reached 56% at $4.65, a 9.7× cost difference, according to SentinelBench's monitoring-agent benchmark. Those particular figures are for tasks running around forty minutes; the same benchmark reports a 5.1× gap on shorter ones, so the lesson is the shape rather than the multiplier. Record whether an agent is waiting, polling, retrying or progressing, because that choice moves both reliability and cost.

How does AuricIDE turn that into one screen?

By ranking them. Not by showing all of them.

Each CLI agent runs as a real PTY child process, so its exit code is a real exit status rather than a summary. External CLIs load through dynamic providers, one JSON config per CLI, imported under Settings → Agent. Shared project state lives behind MCP and holds goals, tickets, requirements, test cases, dependencies and history, which is where the MCP server patterns for AI come in.

The Fleet view groups agents by repository and applies one fixed order: error, then blocked-on-input, then stalled. Each repository shows a single count of agents needing attention, and a tile reads "all quiet" when none do. It tells you where to look. It does not tell you what happened. That distinction is the design: the badge is a queue, not a diagnosis.

The three states mean different things. One is a guess:

  • Error means the process failed. Useful work may still be sitting in the repository.
  • Blocked-on-input means the agent appears to need a human answer. A redrawing permission prompt can produce output that looks like progress.
  • Stalled means no qualifying output during the product's fixed time window. A genuinely slow command looks identical.

Chains use the same terminal tail as their handoff: ANSI codes stripped, interface chrome removed, repeats dropped, and AuricIDE caps what is left at 2,000 characters. Optional auto-dispatch logs each decision with a timestamp and bounds the retries.

What does this view not do?

Several things. Worth knowing before you rely on it.

You cannot set the stall timer or an alert threshold. AuricIDE has no separate monitoring dashboard. Alerting an actual person needs a separate MCP tool that writes to a notification inbox, so nothing pages you on its own. The attention count is a review queue for somebody who is already looking, not a pager for somebody who is not.

Acting on it stays manual, and the right action differs by state. For an error, read the last terminal lines and check the diff before restarting anything, because a quick retry can repeat edits or overwrite work worth keeping. For blocked-on-input, find the exact question and answer it if that is safe and in scope; if the request is unclear, fix the shared project state before work continues. For stalled, look for a long command, a prompt, or a loop, and park the agent while you check. Parking keeps the process alive. It fixes nothing.

Killing is the last option. Kill one agent when recovery makes no sense. Kill the fleet when the problem affects the shared repository run, and accept that you lose more context that way. AI agent workflow design covers the routing side of that decision.

Record the task result afterwards. Fixing the process is not the same as finishing the work.

What carries over to any other tool?

Six rules. None of them need this product.

  1. Track liveness, activity, exit status and task correctness as four separate facts.
  2. Rank the attention states so an operator has one place to start.
  3. Keep recent terminal output behind each summary.
  4. Log dispatch decisions and bounded retries as work moves between agents.
  5. Check finished work against the diff, the tests, and the original request.
  6. Keep the quiet state quiet. An empty queue should not need a second look.

The sixth rule is the easiest to lose. A view that reports something for every agent demands a scan even when nothing needs attention, and repeated scanning turns the view into another output stream. AuricIDE is one worked answer: when no agent needs attention, the tile says "all quiet" and leaves nothing else to inspect. A fleet view earns its place when it answers where help is needed, and stays silent when the answer is nowhere.

AuricIDE is open source

AGPL v3, alpha, and built in the open. If the loop above sounds like the way you want to work, the code is the fastest way to judge it.

★ Star on GitHub