2026-07-25T17:24:06.112Z
Agent Monitoring for Cancellation: Catch Orphaned Child Work
Build a cancellation receipt that proves child agents and external work actually stopped by joining lineage, acknowledgements, grace deadlines, and effect evidence.
A cancellation request is not proof that an AI agent stopped. Treat cancellation as verified only when every known descendant either completed before the request or acknowledged the stop, no monitored side effect appears after a bounded grace deadline, and any external job has a reconciled state. If a child keeps calling tools, writing artifacts, or spending tokens after that deadline, you have orphaned work. The practical agent monitoring primitive is a cancellation receipt : one record that joins the parent request, descendant lineage, acknowledgements, grace window, last observed effect, coverage, and final verdict. It turns “we sent cancel” into an inspectable claim that can be stopped , orphaned , or uncertain . Cancellation is a protocol, not a button Cancellation APIs usually start by communicating intent. Node.js describes AbortController as a utility that signals cancellation in selected Promise based APIs; its AbortSignal notifies observers after abort() is called. The signal’s aborted flag proves that the controller fired. Whether every downstream operation observed the signal, stopped creating effects, and reconciled remote work is a separate question. Python’s current asyncio task documentation makes another boundary visible. Cancelling a task raises CancelledError “at the next opportunity,” and coroutine cleanup belongs in try/finally . The same documentation says TaskGroup cancels remaining tasks after a non cancellation failure and waits for grouped tasks when the context exits. Structured concurrency gives related work an owned lifetime; detached “fire and forget” tasks require their own references and lifecycle discipline. Even a terminated local process does not retract an email, delete an uploaded object, cancel a provider side batch, or stop a child running on another host. Kubernetes similarly documents graceful Pod termination as a staged lifecycle with a grace period, and warns that a Pod phase is only a high level summary rather than a comprehensive state machine. The analogy is limited, but useful: a lifecycle command and a final external effect are different evidence. For agent operations, track three moments: 1. Requested: the parent or operator issued cancellation with a reason and authority. 2. Acknowledged: each reachable descendant observed the request and entered shutdown. 3. Verified: the grace deadline passed without a new monitored effect, and external work was reconciled. Skipping the third moment creates false recovery. The parent looks quiet while a detached child continues the behavior you meant to stop. Build a cancellation receipt around lineage and effects You cannot audit descendants you cannot name. Give each child a stable run identifier and retain its parent or root run identifier across handoffs, queues, and host boundaries. Trace IDs are useful transport, but the monitoring contract also needs the operational identity of provider jobs and side effects. A minimal receipt can use these fields: Field Required evidence rootRunId The parent cancellation scope descendantRunIds Every child known at request time, plus children discovered during shutdown cancelRequestedAt Source timestamp, reason, actor, and authority reference cancelAckAt Per descendant acknowledgement, not one aggregate boolean graceDeadlineAt The last acceptable time for shutdown effects lastEffectAt Last tool call, artifact mutation, queue claim, model call, or task specific effect effectCoverage complete , partial , or unavailable with source freshness externalJobState Provider receipt, cancellation state, or explicit unknown verdict stopped , orphaned , or uncertain , plus the deciding evidence Do not store prompts or raw tool payloads merely to prove lineage. Opaque run IDs, provider job IDs, operation classes, timestamps, and canonical artifact digests are usually enough. Redact secrets on the host. Use a conservative decision order: At the family level, any orphaned descendant makes the cancellation orphaned . Otherwise, any uncertain descendant makes it uncertain . Only an entirely stopped family earns stopped . Coverage precedes reassurance. A provider job that accepted a cancel request but exposes no status or effect signal stays uncertain; a missing observation must never be converted into “nothing happened.” Test the receipt against five cancellation families The accompanying artifact evaluates five synthetic parent child families containing six descendants. Each family has a predeclared expected verdict and a five second grace window. Five seconds is a fixture value, not a production recommendation. The executable report reproduced all expected verdicts: clean lineage contains two descendants. They acknowledge in one and two seconds, and neither produces a monitored effect after the five second deadline. already finished needs no acknowledgement because its child completed before cancellation was requested. Both families are stopped . post deadline effect is the adversarial case. Its child acknowledges in one second, but another tool effect appears nine seconds after the request—four seconds beyond the deadline. A monitor that records only cancelAckAt would report success. The receipt returns orphaned . missing ack has neither an acknowledgement nor a quiet effect channel: its detached worker produces an effect after the deadline. It is also orphaned . external unknown acknowledges promptly, but the external provider’s effect coverage is unavailable, so the verdict remains uncertain . The fixture proves the rule distinguishes those handcrafted cases. It does not estimate how often orphaned work occurs in production or validate a universal grace period. Instrument the boundary where effects occur Start with structured lifetimes inside one process. Prefer a task group or equivalent scope that owns descendants, propagates cancellation, and waits for shutdown. Pass a cancellation signal into model requests, tool calls, queues, and local subprocesses when the API supports it. A child that spawns another child must register it with the same root lineage before work begins. Then inventory effects that can outlive local control: provider side batches and background jobs; queued messages already claimed by a worker; subprocesses and remote sessions; uploads, commits, database mutations, and public messages; metered model or tool calls already accepted upstream. For each effect class, define the strongest observable stop condition. A local subprocess can expose exit time and PID identity. A provider job needs its own cancellation receipt and terminal provider state. An upload may be irreversible after commit; monitoring can verify that no later object version appeared, but it cannot pretend the first upload was undone. Choose the grace window from actual shutdown behavior. Measure acknowledgement latency and effect latency separately, then add explicit clock skew and transport buffers. A network tool may acknowledge immediately while a server completes an already accepted request. That interval belongs in the receipt. Keep event time and ingestion time. A telemetry packet arriving late can look like post cancel work even when its source timestamp predates the deadline. Classify using the trusted source timestamp when available, retain ingestion lag, and return uncertain when clocks or ordering cannot be reconciled. Finally, test the unhappy paths: the handler never reads the cancellation signal; a coroutine catches cancellation and keeps working; a child is missing from the root lineage; the local task stops but a remote provider job continues; a late event arrives after the monitoring window; the external status API is unavailable. Replay those fixtures before attaching alerts or recovery actions to the verdict. Respond to orphaned work without widening authority An orphaned verdict is evidence for investigation, not blanket permission to kill processes or reverse effects. Show the descendant, last effect, cancellation authority, elapsed grace, and safest bounded action. A reversible local child may be eligible for one approved stop attempt. A remote provider job needs its supported cancellation operation. A public message, destructive write, or credential change may require a person and a compensating action. Do not clear the issue because a second cancel command returned success. Clear it only after the descendant stops producing the monitored effect and the relevant external state is reconciled. If coverage remains partial, keep the verdict uncertain and say which signal is missing. The method also has limits. Lineage can be incomplete, identifiers can be reused incorrectly, clocks can drift, and some side effects have no queryable state. A quiet window only covers the effects you instrumented. It cannot prove the absence of an unknown child. The operating rule is narrow: send cancellation through owned lineage, collect per child acknowledgement, observe task specific effects through a bounded grace window, reconcile external jobs, and preserve unknowns. That is enough to catch the most dangerous false stop: a quiet parent with a child still acting. Sidewisp is currently in private preview. Its public site and article library are live, but production agent health collection, runtime adapters, and recovery are not generally shipped. Sidewisp is intended to work alongside existing runtimes, not as a replacement runtime or autonomous fixer. If cancellation integrity is a health signal you need, you can join early access without treating the preview as a deployed monitoring claim.