Essay

How to stop an agent mistake before it becomes irreversible

An agent that cancels a flight before showing the fee has an architecture problem, not just a judgment problem. A pattern for gating consequential actions on a verified Outcome, without turning every step into a confirmation dialog.

A user asks a travel agent app: "Can you see if I can cancel my flight?" The agent pulls up the cancellation terms, and somewhere in that process the cancellation itself goes through, before the user ever sees the fee. The airline keeps a $258 cancellation fee. The user is left with a small travel credit, a year to use it, and a screenshot thread.

The example is drawn from a widely shared exchange from September 2026, in which an agent built on Instinct canceled a flight while it was still supposed to be checking the cancellation terms. Spoolis wasn't involved, and this isn't a claim that the current product would have prevented that incident. But it exposes a design pattern worth building.

Screenshot of the agent conversation: the user asks to cancel their SF flight, the agent says it is pulling up the actual cancel terms, then reports the cancellation went through before it could show the cost first, with a $258 Frontier cancellation fee and a $31.96 travel credit. The user replies: WTF R U DOING.
The conversation, as shared by the affected user on X. The cancellation fired while the agent was still checking the terms.

Versions of this exact exchange circulate every few months, and they will keep circulating, because the failure isn't one company's bug. "Can you see if I can cancel" is a question. The agent treated it as an instruction. That's a judgment error, and models will keep making judgment errors.

The deeper failure is architectural: an uncertain intermediate state was allowed to trigger an irreversible action. Nothing stood between "the agent thinks it should cancel" and "the flight is canceled."

The plain-English version: you don't make a car safer by asking the driver to confirm every turn. You put a guardrail at the cliff. This essay is about where the guardrail goes, and what it's made of.

With and without a gate

The prerequisite Outcome

The pattern is simple to state. Before a consequential action runs, the runtime doesn't ask "does the agent want to do this?" It asks "were the agreed prerequisites for this action actually satisfied?" And that question is answered by a verifier against criteria that were fixed up front, not by the same model that proposed the action.

For a flight cancellation, the prerequisites might be:

  • The booking's actual cancellation terms were retrieved.
  • The fee is known, not estimated.
  • The refund or credit outcome is known.
  • The fee was disclosed to the user if it exceeds a threshold.
  • Explicit user confirmation is present when policy requires it.

The agent gathers evidence for each of those in the normal course of doing its job: the terms page it fetched, the fee it computed, the conversation transcript. The evidence goes to the verifier, and what comes back is a verdict per check:

{
  "result": "fail",
  "checks": {
    "terms_retrieved":   "pass",
    "fee_known":         "pass",
    "fee_disclosed":     "fail",
    "user_confirmation": "fail"
  }
}

The runtime reads one thing: there is no passing Outcome for this action, so cancel doesn't get called. In the incident above, this exact check fails in the only place it needed to. The terms were retrieved. The fee was known. But it was never disclosed, and the user never confirmed. Two red rows, no cancellation, one question to the user instead of an apology.

Why a verdict and not a vibe: the agent already "believed" it was fine to proceed. That's the belief that failed. The gate works because it's evaluated by a separate system, against criteria frozen before the action was proposed, from evidence rather than confidence.

Not a confirmation dialog

The obvious objection: if every action needs a check, you've rebuilt the confirmation dialog. That's not the pattern. The runtime classifies actions by consequence, and the gate only exists where consequences do.

Who owns what

Kept this way, Spoolis stays out of orchestration entirely. You hand over one narrow question you don't want answered by the system that's about to act on the answer.

Why not an internal boolean?

You could implement this as can_cancel = false in your own code, and for some checks you should. The reason to make the gate a verified Outcome instead of a private flag is what the result can carry:

  • It's tied to the exact prerequisite agreement it was judged against, so "why was this blocked" has a precise answer.
  • It's backed by evidence, not by the agent's own account of itself.
  • It's signed, so another system can verify it wasn't fabricated after the fact.
  • It's portable: the same result can gate the action, feed the audit log, and answer a support ticket or a dispute later.
  • It's hardened against adversarial evidence, which matters once agents start justifying their own actions.

A boolean says no. An Outcome says no, and can prove why, to someone who wasn't there.

When the $258 conversation happens, the difference is concrete. With an internal flag, the answer to "what did the agent think it knew?" is a log-diving exercise. With an Outcome Receipt, it's a record: these were the prerequisites, this is the evidence, this check failed, so the action didn't run.

Integration

The three verdicts map to three behaviors, and the third one matters more than it looks:

  • Pass: execute. The user never knows the gate existed.
  • Fail: block, and surface the failing check. Often that becomes the one good question to the user.
  • Uncertain: don't guess. Escalate to a human. An uncertain verdict on an irreversible action is exactly the case where false confidence costs $258.

The agreement and verification mechanics are the same ones that run everywhere else on Spoolis: the verification docs cover how criteria and checkers are declared, and the sandbox quickstart runs without an account.

What this is and isn't

To be direct about it: this is a design pattern Spoolis can support, not a claim that Spoolis was integrated into the product in the incident that opens this essay, or that it would have prevented that specific failure as those systems were deployed. I don't know their architecture. What I'm claiming is narrower: the failure mode is general, the gate is buildable today, and the interesting part is that the gate's verdict can be a signed, portable record instead of a private boolean.

The boundary is the decision

Autonomous UX shouldn't mean asking the user to approve every click. It should mean letting software move quickly until it reaches a boundary where the consequences are real. At that boundary, "the agent thinks the prerequisites are satisfied" is not enough.

At the boundary, the agent's belief should become a result another system can verify before acting. That's the whole pattern.

How to stop an agent mistake before it becomes irreversible · Spoolis