Blog Long-Running Agents

Long-Running Agents / Aug 30, 2026

An Honest Shutdown Contract for Long-Running Agent Cancellation

A stop request is not an undo. Learn a proposed five-commitment shutdown contract for safer, more truthful cancellation of long-running AI agent workflows.

By Virillio Code Editorial
A glowing stop control halts a long-running machine while separate residual-effect indicators remain visible for inspection.

“Stop the agent.”

It sounds absolute. In practice, it is a request that arrives in the middle of a distributed workflow.

The model may be generating. A tool may be waiting on a network response. A local command may have created partial files. A background job may already be accepted by another system. An approval may be pending. A write may have happened just before the caller lost its connection.

If the product changes a status label from Running to Cancelled without reconciling those facts, it has not stopped the work. It has stopped explaining the work.

Cancellation controls future execution. It does not retroactively erase effects.

That distinction is the foundation of a trustworthy agent shutdown design.

Stop, pause, abandon, undo, and compensate are different actions

Teams often overload the word “cancel” with several meanings. Name them separately.

  • Action: Stop request — What it means: A user or policy no longer wants new work to begin — What it must not imply: That running work has already ceased
  • Action: Pause — What it means: Work is intentionally suspended and may resume from durable state — What it must not imply: That the task is complete
  • Action: Cancel execution — What it means: The runtime asks active work to cease at safe boundaries — What it must not imply: That all tool effects are reversed
  • Action: Abandon — What it means: The system gives up waiting or acting further — What it must not imply: That the external world is unchanged
  • Action: Undo — What it means: A prior state transition is reversed — What it must not imply: That every action has a reversible inverse
  • Action: Compensate — What it means: A new, deliberate action reduces the consequence of an earlier effect — What it must not imply: That it exactly restores the old state

This is not semantic nitpicking. A team cannot choose a safe implementation or honest UX until it knows which outcome it is promising.

Python’s asyncio cancellation model captures a useful low-level truth: cancellation is requested, then observed at a subsequent opportunity; cleanup still needs to run. The task is not considered cancelled merely because someone asked. Agent systems need the same humility at a higher level.

A proposed five-commitment shutdown contract

Virillio Code Editorial proposes treating cancellation as a short lifecycle with five explicit commitments. This is an editorial design model, not a runtime standard, and implementations should adapt it to their own effect and policy boundaries.

  • Commitment: Acknowledge — Question it answers: Did the system receive and authorize the stop request? — Durable output: Stop request identity, source, timestamp, and scope
  • Commitment: Quiesce — Question it answers: What new work is now forbidden from starting? — Durable output: Active execution marked as stopping; future admissions gated
  • Commitment: Reconcile — Question it answers: What was already running or may already have changed state? — Durable output: Confirmed, partial, unknown, or safely not-started operation states
  • Commitment: Compensate deliberately — Question it answers: Which effects can or should be counteracted? — Durable output: Explicit compensation policy, approval, and result
  • Commitment: Close with evidence — Question it answers: What is the final truthful status and next safe action? — Durable output: Terminal or resumable state, evidence, and unresolved items

These commitments do not always happen in a straight line. A run can move from quiescing to waiting for a human because an external effect is unknown. It can reach a stable stopped state while one independent background task continues its own safely documented lifecycle. The point is to prevent invisible gaps.

1. Acknowledge: record the stop as a first-class event

The stop request needs its own identity, scope, and authority.

At minimum, capture:

  • who or what requested the stop;
  • whether it applies to one task, a session, a workspace, or a broader policy scope;
  • the time it became effective;
  • any stated reason or policy category;
  • the expected user experience: pause, abandon, or attempt to cancel active execution.

This matters for exact retries and for competing inputs. A repeated tap on a stop button should reconcile with the existing stop request. A later “resume” should be a new, explicit decision—not an accidental side effect of an executor returning after the interface changed.

Acknowledgment also protects the user from a common failure mode: the system says it received the stop request, but a queued plan step still starts because no durable boundary was updated.

2. Quiesce: prevent new work before chasing active work

The fastest route to a truthful shutdown is often to block new action first.

Quiescing should:

  • stop promotion of queued work that is now out of scope;
  • prevent a new model turn from choosing another consequential tool;
  • block scheduled retries that would restart the same effect;
  • mark active workers as stopping so they do not claim normal completion;
  • preserve enough state for the system to explain what was already in progress.

This is different from killing every process immediately. A sudden process termination can leave locks, incomplete files, missing results, or ambiguous external operations. Kubernetes termination guidance makes a related point for services: graceful termination and connection draining are distinct operational steps.

For agents, quiescing means “do not begin more work while we establish the truth of current work.”

3. Reconcile: classify effects before declaring success

Once new work is gated, the system must examine operations that were already active.

  • Operation class: Model generation with no tool effect — Safe question after a stop request: Did the provider turn settle? — Likely next action: Discard or retain the partial output under policy; do not treat it as a completed task
  • Operation class: Read-only tool call — Safe question after a stop request: Did it return, and is freshness still relevant? — Likely next action: Record or ignore the result; no compensation needed
  • Operation class: Local workspace change — Safe question after a stop request: Did the change complete, and is it still present? — Likely next action: Inspect the workspace or revert only under an explicit policy
  • Operation class: External job submission — Safe question after a stop request: Was the job accepted, running, completed, or unknown? — Likely next action: Query authoritative status before requesting more action
  • Operation class: External write — Safe question after a stop request: Did the target state change? — Likely next action: Verify the effect before retrying, compensating, or reporting
  • Operation class: Human approval wait — Safe question after a stop request: Was the action already authorized? — Likely next action: Preserve the pending decision or close it with an explicit reason

“Unknown” is a valid and necessary answer. A timeout, interrupted stream, or process crash tells the agent that it lacks confirmation; it does not prove the effect failed.

A July 31, 2026 v1 arXiv preprint on verified tool calls evaluates postcondition checks, verify-before-retry behavior, and idempotency keys in a controlled simulated environment with injected non-atomic failures. The authors report fewer duplicate actions under those experimental conditions. Because this is one preprint and the evaluation is simulated, the result should motivate production-specific testing rather than be generalized to every agent, tool, or deployment. The narrower design lesson is to make verification a first-class shutdown action.

4. Compensate deliberately: do not invent an undo

An agent should not confuse a cancellation request with broad permission to repair the world however it sees fit.

Some actions can be compensated:

  • release a reservation;
  • remove a newly created draft;
  • close a temporary local resource;
  • roll back a staged, explicitly reversible change.

Some cannot be safely reversed:

  • an email that was already sent;
  • an externally consumed webhook;
  • a public post;
  • a deletion without a documented recovery path;
  • a human decision that changed subsequent work.

Compensation is a new effect with its own authority, identity, and verification requirement. It can be riskier than the original action. The system should only attempt it when a policy explicitly permits the exact compensation and sufficient evidence says it is appropriate.

This leads to a helpful rule:

If you cannot describe the compensation before the original effect begins, do not assume cancellation will make it safe later.

For high-consequence operations, ask for approval before the effect, not after the stop request.

5. Close with evidence: make the final status honest

The final state should describe the outcome, not the button label.

  • Terminal state: Stopped before effect — Meaning: The request was acknowledged and no consequential operation began
  • Terminal state: Stopped after safe settlement — Meaning: Active work reached a safe boundary with no unresolved effect
  • Terminal state: Partially completed — Meaning: Some work or effects completed; the manifest identifies them
  • Terminal state: Awaiting verification — Meaning: The system cannot yet confirm the state of a consequential operation
  • Terminal state: Compensation pending — Meaning: A permitted corrective action needs approval or execution
  • Terminal state: Resumable pause — Meaning: Work is intentionally paused with durable state and a known resume path

“Cancelled” can be a convenient UI label. It should map to one of these more precise states internally.

The user-facing report should be short but specific:

  • what stopped;
  • what had already completed;
  • what is uncertain;
  • whether the system will take any further action;
  • what a human can do next.

That report is more trustworthy than an optimistic “Cancelled successfully” banner after an unverified external write.

Put stop points near effect boundaries

The best time to design cancellation is before adding the tool, not after the first incident.

For each consequential operation, decide:

  1. When does the operation become committed?
  2. Can the runtime distinguish not-started, in-progress, confirmed, partial, and unknown?
  3. Is there an idempotency or effect identity that makes an exact retry safe?
  4. Does it have an approved compensation action?
  5. What must be persisted before a pause or interruption?
  6. Which state should a user see if confirmation cannot be obtained?

LangGraph’s interrupt documentation highlights why placement matters: resuming an interrupted node can cause code before the interrupt to run again, so side effects before that point need idempotency discipline. The same pattern can inform other runtimes, although their replay and interruption semantics may differ. A stop boundary is not safe because the interface says “pause.” It is safe because the runtime has decided which effects can repeat, which require verification, and which must wait for a human.

Test shutdown behavior as a workflow

Cancellation cannot be adequately tested with one unit assertion that a controller receives a signal. Test the whole lifecycle.

  • Scenario: Stop while the model is reasoning — What to verify: No new tool effect starts after the stop boundary
  • Scenario: Stop during a read-only operation — What to verify: The final state remains truthful without unnecessary compensation
  • Scenario: Stop during a local write — What to verify: Partial artifacts are identified and the workspace state can be inspected
  • Scenario: Stop after an external request times out — What to verify: The system verifies rather than blindly repeats the action
  • Scenario: Stop during an approval wait — What to verify: The pending decision is preserved or explicitly closed
  • Scenario: Repeated stop requests — What to verify: They reconcile without creating contradictory state
  • Scenario: Resume after pause — What to verify: The system continues from durable evidence, not a guessed transcript

Track not only whether a stop “worked,” but whether it was explainable:

  • time from request to acknowledgment;
  • amount of new work started after quiescing;
  • percentage of active effects reconciled to a known state;
  • duplicate-effect rate after stop or retry;
  • compensation success and failure rate;
  • duration of unknown-outcome states;
  • proportion of final reports with evidence.

These measures reveal whether the platform is genuinely becoming safer or merely becoming better at hiding incomplete work.

Common anti-patterns

Cancelling the model and calling the task cancelled

The model is one participant in the workflow. The task may already have invoked tools, created artifacts, or changed external state.

Assuming a timeout means nothing happened

A lost response is an information failure, not proof that the requested effect failed.

Retrying on behalf of the user after a stop

If the user asked to stop, a background retry may violate the user’s intent even if the operation would have been technically safe.

Suppressing cancellation to preserve a happy-path result

Cleanup can be necessary. Pretending the stop never happened is not.

Compensating without an authorization model

An automatic “undo” can become a second unsafe write. Compensation must be scoped and verified like any other effect.

A practical adoption path

  1. List the agent’s consequential operation classes.
  2. Define stop, pause, abandon, and compensation separately.
  3. Add an explicit stop-request record and quiescing gate.
  4. Give every external effect a confirmation state and, where appropriate, an effect identity.
  5. Define what the UI says for unknown and partial outcomes.
  6. Test cancellation at each operation boundary.
  7. Add compensation only where the original action and the compensating action are both well understood.

Trustworthy autonomy does not mean every operation can be stopped instantly. It means the system is candid about what a stop request can and cannot change.

What we are learning building Virillio Code

Virillio Code’s session architecture remains in development, but it reinforces a simple principle: interruption targets active execution; durable records preserve what the user asked for and what the system can truthfully establish. A stop request should reduce future work without rewriting history or concealing an effect that requires verification.

That distinction turns cancellation from a cosmetic button into a dependable contract with the user.

Sources and further reading

Editorial disclosure

This article was substantially researched, drafted, and revised with AI through the Virillio Code editorial workflow. Virillio Code publishes the final text under its editorial byline, and the supporting primary sources are linked above.