Monitor a long-running agent task with a stable operation identity and an explicit lifecycle across requests. A successful tool invocation may only start the job. The task remains pending until the required result arrives or a terminal failure is confirmed.
This matters for exports, research jobs, document processing, support transfers, and workflows waiting for human approval.
Keep request, attempt, and operation separate
The request is what the user asked. An attempt is one execution segment. The operation is the work that continues across segments. One operation may involve several queue deliveries, retries, and status checks.
| Identifier | Purpose |
|---|---|
| Conversation ID | Connects the user’s interaction history |
| Operation ID | Names the durable task |
| Attempt ID | Distinguishes execution or delivery attempts |
| Trace ID | Connects one distributed execution trace |
| External reference | Resolves the job in the owning system |
Do not assume the trace ID can replace all of these. A multi-day operation may outlive a single request trace. OpenTelemetry’s trace model provides spans and relationships for execution; the business lifecycle still needs application identity.
Make lifecycle transitions explicit
A proposed sequence is accepted, queued, running, and completed. Rejected, failed, canceled, and unknown need their own meanings. Waiting for approval may be a separate state rather than a failure or an actively running worker.
Store transition time, previous state, new state, and the actor or event that caused the transition. Define how duplicate and out-of-order events are handled. A delayed “running” notification should not overwrite a confirmed completed state.
The final user message should reflect the latest verified state. “I started the export” is different from “Your export is ready.” If the product promises a later notification, track that notification as a separate delivery outcome.
Poll without creating a loop
A status tool may legitimately run several times. Mark the polling purpose and the target operation. Use a bounded interval, deadline, and stop condition. Do not classify each repeated status query as redundant work merely because its arguments match.
On timeout, preserve the distinction between “the operation failed” and “we stopped waiting.” A job might complete later. Reconcile it with the provider or worker rather than restarting blindly.
For actions that can create duplicate effects, preserve the same idempotent action identity across retries and resumes.
Detect stuck work using age and state
Monitor pending age, time in queue, active execution time, and time since the last meaningful update. Select thresholds by operation type. A file conversion and a human review should not share one arbitrary timeout.
Keep still-open operations in the report. A completion-time chart built only from finished jobs omits the jobs that never finish. Show counts and age distributions for pending work separately.
For a graph-based application, LangGraph persistence explains how state can continue across invocations. Your monitoring should preserve that continuity rather than marking every invocation as an independent user success.
Test the awkward transitions
Exercise duplicate completion events, worker crashes, cancellation racing with completion, a lost callback, and a status query returning an unknown operation. Include a healthy job that takes a long time so the detector does not confuse duration with failure.
A useful incident record connects the original user request, operation history, latest authoritative result, and what the agent told the user. If those records disagree, the failure may be in execution, event delivery, state reconciliation, or communication.
In Agnost, preserve the operation reference in the events you send and use conversation evidence to inspect the user’s experience. The latency guide explains why approval waiting and active compute need separate measurements.
