2026-07-26T17:08:47.856Z
AI Agent Observability: Separate Approval Waits from Stalls
A six-request audit shows how action identity, routing, resume handles, and continuation receipts distinguish a legitimate human wait from a stalled agent.
An agent that has stopped producing events is not necessarily stuck. It may be doing exactly the safe thing: waiting for a person before it sends a message, changes production state, or spends money. The operational question is not “how long has the process been quiet?” It is whether the approval request is still relevant, reached someone authorized to decide, and can resume the same interrupted run. That gives AI agent observability a firmer rule. A pause is healthy only while four proofs hold: the proposed action has not changed or expired; the request has a verified route; the requester retains a durable continuation handle; and, after approve or reject, a receipt shows that the run consumed the decision. A timer is useful only after those facts are known. A valid wait has four proofs Most monitoring collapses approval into a single state such as pending approval . That label hides failures with different owners and different remedies. Consider an export agent waiting for a release owner. The process has emitted no tool calls for 25 minutes. If the exact export action is still current, the release owner received the request, and the run can resume from its saved interruption, the inactivity is legitimate waiting. Restarting it would be harmful: the new run might produce another request or lose the decision context. Now change one fact at a time. The data selection changed after the request was created. The old request is stale , even if somebody approves it. Notification delivery failed and no approver is attached. The request is unroutable , not merely slow. The approval card exists, but the interrupted run has no durable resume handle. The request is orphaned . Approval arrived, but the run did not consume it within the declared grace period. The agent is stuck after the decision . The person declined. The request is closed , not late. This separation follows the control flow exposed by current agent frameworks. The OpenAI Agents SDK comparison lists resumable run state and resumable approval flows as distinct capabilities. OpenAI’s migration validation checklist is more explicit about the lifecycle: an approval gated action should pause, surface an interruption, and then resume or reject cleanly. “The approval exists” proves only the middle of that sequence. The fourth proof matters because a human decision is not the intended outcome. It is permission for the run to continue, or a refusal that the run must handle. Observability should therefore record both a decision event and the later continuation receipt. Without the latter, a green approval badge can conceal a stopped agent. Record a decision lifecycle, not a modal The smallest useful record is deliberately boring. It needs stable identities and timestamps, not a transcript of the model’s reasoning. requestId deduplicates notifications and responses. The action digest binds the decision to a specific proposed effect; it should change when material arguments, target, authority, or scope change. approverRef names a role or policy subject rather than copying a person’s private data into telemetry. The resume handle points to the durable interruption. The resume receipt says that the requester accepted the decision and moved into its next state. The decision vocabulary must also preserve what the person did. The MCP elicitation specification distinguishes accept , decline , and cancel . Decline is an explicit answer. Cancel is dismissal without the same commitment. Treating both as “no response” invites an automated system to ask again after the person already said no. The same specification says servers must not request sensitive information through elicitation, and clients should make the requesting server and purpose clear. That boundary applies to health evidence too. Store the minimum fields needed to establish state. A route reference, action digest, and decision code can diagnose most approval failures without retaining secrets, raw prompts, or the response content. There is an important limit: delivered: true is transport evidence. It does not prove that a person saw, understood, or accepted the request. For high risk actions, add an acknowledgement or use a policy that requires an explicit decision before expiry. Do not silently reinterpret delivery as informed consent. A six request audit changes the incident queue The accompanying fixture fixes evaluation time at 2026 07 26T16:30:00Z , allows five minutes for a decided run to resume, and treats a requester heartbeat as fresh for ten minutes. It contains six snapshots. Run the audit with: The result is intentionally one of each state: Four records initially look like unanswered approvals. Their ages alone do not explain what to do. The export request is a healthy wait. The deletion request expired. The rotation request has no verified route. The invoice request cannot resume because its continuation handle is missing. One status string would have put all four in the same alert queue. The deployment record exposes the less obvious failure. Its human decision is already present, so measuring “time awaiting approval” would report zero. Yet no resume receipt arrived during the five minute grace period. This incident should go to the runtime owner, not back to the approver. Asking the person to approve again would add noise while leaving the failed continuation untouched. The declined message request demonstrates why evaluation order matters. Terminal decisions are checked before timeouts. The audit closes the request rather than escalating it or generating another prompt. That is not merely polite UX; it preserves the human authority boundary. The sample thresholds are not universal. A low risk content preview might resume within seconds. A controlled production change may deliberately wait for a maintenance window after approval. Set the resume grace from the runtime’s documented behavior and the action’s operating policy. Record the chosen threshold beside the verdict so an operator can tell whether “stuck” came from evidence or an arbitrary default. Act on the state, not the silence Once the states are separate, the incident response becomes bounded. State Evidence Safe next move WAITING Current action, verified route, live continuation, no decision Leave the run paused; notify only under the agreed escalation policy STALE REQUEST Expired request or changed action digest Cancel the old request and create a new one only if the current action still needs authority UNROUTABLE WAIT Missing approver or failed delivery Repair routing or escalate to the policy owner; do not restart the action ORPHANED WAIT Missing resume handle or stale requester Preserve the decision record, then recover the run with explicit authority STUCK AFTER DECISION Decision present, resume receipt absent after grace Investigate the continuation path; do not ask for the same approval again CLOSED BY DECLINE Explicit decline Stop the action or offer a non destructive alternative Automatic recovery should remain narrow. Retrying a notification can be reversible when the request ID stays stable. Recreating a changed request may be safe after the old one is cancelled. Restarting the underlying action is different: it can duplicate effects, bypass the original scope, or detach the eventual human response from the new run. When evidence is incomplete, mark the state uncertain and ask before acting. The practical conclusion is simple: silence is not the health signal. A valid approval wait is a live contract between one proposed action, one authorized route, and one resumable run. A decision ends the waiting phase, but only a continuation receipt proves operational progress. Sidewisp is currently in private preview. Its planned health model includes waiting versus stuck diagnosis and explicit approval boundaries, but production agent health collection, runtime adapters, cron management, token cost analytics, and recovery are not generally shipped. Sidewisp is not a replacement runtime, mandatory gateway, raw tracing product, enterprise control plane, or autonomous fixer. If this evidence model matches a failure you operate today, joining the private preview is the restrained next step.