# Advanced Agents From First Principles 37: Is Your Agent Still Solving the Right Task? Build Intent Versioning, Supersession and Cancellation # Book: Advanced Agents From First Principles # Chapter URL: https://programmer.ie/books/advanced-agents-from-first-principles/37-chapter/ # Prose fingerprint (sha256, normalized): e469c69afb72b9abe14ecf8cdd1543121e2dc83475fb3148e90b469197ffbe5c # Snapshot generated at build time by Hugo. This is the complete rendered prose # of the chapter; it is not a transcript of the source file. A long-running agent can have perfectly fresh state and still be doing the wrong thing. The repository may be current. The browser session may still be valid. The approval may not have expired. The tool may return exactly the expected result. The checkpoint may deserialize correctly. And the entire run may still need to stop. Why? Because the user’s intent changed. Consider a coding agent. At 10:00, the user asks: Upgrade service A to dependency version 4. The agent begins inspecting the repository, creates a plan, opens a workspace, edits several files, and starts tests. At 10:08, the user learns that version 4 has a regression and says: Stop. Keep version 3. Instead, backport the security patch only. The repository itself may not have changed. Nothing is stale in the temporal-consistency sense from Step 36. But the original task is no longer authoritative. If the first run continues because its lease is valid, its checkpoint is valid and its tools still work, the system has preserved execution correctness while violating intent correctness. That is a serious production failure. The same problem appears everywhere. A deployment is cancelled after rollout has begun. A support ticket is closed while an agent is still investigating it. A customer changes the amount in a financial workflow after a payment proposal was prepared. A researcher changes the question after the agent has gathered half its evidence. A browser agent is told not to submit a form after it has already filled every field. A DevOps operator replaces a recovery plan while the previous workflow is waiting on an approval. A scheduler reprioritizes a task after the original worker has already started expensive speculative work. In all of these cases, the external state may still be perfectly fresh. The stale object is the intent. The core rule for this post is: State can become stale. Intent can become stale too. And the stronger operational rule is: No consequential action should execute unless both the state assumptions and the intent version that authorized it are still current. The Search Problem: “How Do I Cancel an AI Agent Safely?” Cancellation sounds easy. Set a flag. Stop the task. Return cancelled. That works only for toy loops. A production agent may already have: issued tool calls; written files; opened a pull request; sent a message; started a deployment; acquired a lease; scheduled retries; created child tasks; requested human approval; generated speculative branches; consumed budget; mutated external systems; handed execution to another worker. By the time cancellation arrives, the real question is not: Can we stop the Python coroutine? It is: Which work is now obsolete? Which effects already happened? Which effects are still preventable? Which results remain reusable? Which approvals are invalid? Which children must stop? Which external systems require reconciliation? That is not a threading primitive. It is an intent lifecycle problem. 1. Intent Must Be an Authoritative Runtime Object Many agent systems represent intent only as text in the prompt. That is insufficient. If the prompt says: Deploy release 2026.08.09.1 to production. then the runtime needs an authoritative object representing that request. For example: from dataclasses import dataclass from datetime import datetime from enum import Enum class IntentStatus(str, Enum): ACTIVE = "ACTIVE" SUPERSEDED = "SUPERSEDED" CANCELLED = "CANCELLED" COMMITTED = "COMMITTED" PARTIALLY_COMMITTED = "PARTIALLY_COMMITTED" COMPLETED = "COMPLETED" RECONCILIATION_REQUIRED = "RECONCILIATION_REQUIRED" @dataclass(frozen=True) class Intent: intent_id: str version: int status: IntentStatus objective: str scope: tuple[str, ...] created_at: datetime supersedes_version: int | None authority_policy_version: str created_by: str The model may interpret the objective. The runtime owns the identity and lifecycle. That distinction matters. The agent should never be allowed to decide that an old instruction is still current because it semantically resembles the new one. Intent currency is an authoritative fact. 2. Intent Versioning Is Different From Conversation History A chat transcript tells you what was said. It does not automatically tell you what is still authoritative. Imagine: User: deploy version A User: actually deploy version B User: wait, cancel the deployment entirely A language model reading the transcript may infer correctly that the third instruction dominates. Usually. But production control should not depend on that inference. We need an explicit lineage: intent deploy/v1 ↓ superseded by intent deploy/v2 ↓ cancelled by intent deploy/v3 The current authority can then be queried deterministically: def current_intent(intent_id: str) -> Intent: ... or: def is_current(intent_id: str, version: int) -> bool: ... This becomes as fundamental as checking a repository commit SHA before mutation. 3. Supersession Is Not Cancellation These should be different operations. Cancellation means: Do not continue pursuing this objective. Supersession means: This objective has been replaced by another objective. That difference affects reuse. Suppose the old intent was: Upgrade requests from 2.31 to 2.32. The new intent is: Upgrade requests from 2.31 to 2.33 instead. Some old work may remain useful: repository discovery; dependency graph construction; test inventory; affected-file analysis; environment setup. But some old work is invalid: exact patch; version-specific compatibility analysis; verifier results bound to the old artifact; approval of the old dependency change. A correct supersession system therefore asks: What survives? What is invalidated? What needs recomputation? What must be reconciled? It does not simply throw the entire run away. 4. Intent Has Scope A new instruction does not necessarily supersede the entire run. Consider: Implement feature X and update the documentation. Later: Skip the documentation for now. The implementation subgoal may remain active. The documentation subgoal is cancelled. This means intent needs scope. For example: root intent ├── implementation │ ├── backend │ └── frontend └── documentation A scoped supersession may target only: documentation Without scoped intent identity, teams often choose between two bad options: cancel far too much; or keep obsolete child work alive. Neither is acceptable for long-running systems. 5. Intent Version Is a Dependency Step 36 introduced the idea that evidence is valid relative to state identity. The same should apply to intent. A candidate does not merely depend on: repository_sha = abc123 policy_version = p17 verifier_version = v8 It may also depend on: intent_id = deploy-prod intent_version = 12 So the candidate’s provenance becomes: candidate C ├─ repository SHA abc123 ├─ policy p17 ├─ verifier v8 └─ intent deploy-prod/v12 If intent version 13 supersedes 12, candidate C may no longer be executable even if the repository has not changed. This is intent invalidation. 6. Bind Plans to Intent Versions A plan should carry the intent identity it was derived from. For example: @dataclass(frozen=True) class Plan: plan_id: str intent_id: str intent_version: int steps: tuple[str, ...] state_version_refs: tuple[str, ...] created_at: datetime Before executing a step: if not intent_store.is_current(plan.intent_id, plan.intent_version): return REPLAN_REQUIRED This may seem obvious. But it prevents a subtle class of bugs where a long-lived plan retains authority after its goal has changed. 7. Bind Approvals to Intent Too Step 29 bound approvals to exact operations and artifacts. Intent must be part of that binding. An approval such as: Approve production deployment of release A. must not remain usable after the intent becomes: Deploy release B instead. Even if both releases touch the same service. A stronger approval record looks like: @dataclass(frozen=True) class Approval: approval_id: str operation_id: str artifact_hash: str environment: str intent_id: str intent_version: int policy_version: str approved_by: str expires_at: datetime Commit-time validation checks all of them. An approval is not a transferable permission slip. It is evidence that a specific actor authorized a specific operation under a specific intent and state. 8. Cancellation Is a State Transition, Not a Signal A cancellation signal is transport. The real semantics belong in durable state. For example: ACTIVE ↓ CANCEL_REQUESTED ↓ CANCELLING ↓ CANCELLED But that is not enough for side-effecting systems. We may need: ACTIVE ↓ CANCEL_REQUESTED ↓ PARTIALLY_COMMITTED ↓ RECONCILIATION_REQUIRED ↓ CANCELLED The cancellation request is therefore only the beginning of the process. 9. Logical Cancellation Does Not Mean Physical Work Stopped We established this earlier for speculative execution. It matters even more here. Suppose an external API call is already in flight when cancellation arrives. The runtime sends a cancellation request. That does not prove the external system did nothing. The request may have: completed before cancellation; completed after the caller timed out; been accepted asynchronously; partially applied; produced a side effect but lost the response. Therefore: Cancellation must never be used as evidence that an external side effect did not occur. The correct flow is: cancel requested ↓ prevent new work ↓ identify in-flight operations ↓ query authoritative external state ↓ classify committed / uncommitted / ambiguous ↓ reconcile if necessary 10. Cancellation Must Fence Future Mutation If an intent is cancelled, stale workers must lose mutation authority immediately. This is another use for fencing. Suppose worker A owns intent version 7 with fencing epoch 41. The intent is cancelled. The control plane advances the mutation epoch: 41 → 42 Worker A may continue running physically. But any consequential mutation carrying epoch 41 is rejected. This is stronger than hoping the worker notices a cancellation flag. The agent may be slow. The worker may be partitioned. The process may have paused. The model may already have generated the tool call. The commit gateway still rejects stale authority. 11. Cancellation Must Propagate Through Child Work Long-running agents often create trees of work. For example: root intent ├── investigate API ├── modify backend │ ├── candidate A │ ├── candidate B │ └── test suite └── modify frontend A root cancellation may need to propagate to all descendants. A scoped supersession may invalidate only part of the tree. Therefore every child should carry ancestry: @dataclass(frozen=True) class WorkItem: work_id: str parent_work_id: str | None root_intent_id: str root_intent_version: int scope: tuple[str, ...] Then the runtime can answer: Which active work items descend from superseded intent v12? without asking the LLM to reconstruct lineage from logs. 12. Cancellation Trees Are Not Necessarily Kill Trees Propagation does not imply destruction of every artifact. We should distinguish: execution authority artifact validity artifact reusability When a child task is cancelled: its tool execution may stop; its candidate may become non-committable; its repository map may remain reusable; its immutable test output may remain evidence about an unchanged artifact; its cached model analysis may remain useful if its input identity still matches. This is exactly the same discipline we applied to stale-state invalidation. Invalidate dependent meaning, not necessarily every byte produced during the old run. 13. Use an Invalidation Graph Step 36 introduced runtime invalidation graphs for stale state. Extend them with intent dependencies. For example: intent v12 ↓ plan p4 ↓ workspace w8 ↓ candidate c9 ↓ verifier evidence e3 ↓ approval a5 ↓ commit operation o7 If intent v12 is superseded before commit: plan p4 INVALID candidate c9 INVALID_FOR_COMMIT verifier evidence e3 HISTORICAL_ONLY approval a5 INVALID operation o7 BLOCKED Other nodes may survive. For example, a repository snapshot might not depend on the objective at all. This creates precise invalidation instead of indiscriminate cancellation. 14. Supersession Can Be Compatible Not every new intent requires full replanning. Suppose: v1: fix bug #123 v2: fix bug #123 and add a regression test The existing bug fix may still be compatible. Or: v1: summarize these 100 documents v2: summarize the same documents but emphasize security findings Previously extracted document facts may remain useful. So supersession can have compatibility classes. For example: IDENTICAL_SCOPE NARROWER_SCOPE BROADER_SCOPE MODIFIED_OBJECTIVE CONFLICTING_OBJECTIVE CANCELLED However, these classifications should not automatically grant authority. They help determine what evidence might be reused. The final mutation path still needs current intent validation. 15. Semantic Compatibility Is a Fallible Inference Some supersession relationships are exact. For example: new release_id != old release_id Others require semantic interpretation. For example: "make the UI cleaner" becomes: "keep the existing visual layout but simplify the forms" A model may help classify overlap. But that classification is a hypothesis. Do not let a semantic-compatibility model silently authorize continuation of consequential work. For high-impact actions, ambiguous supersession should resolve toward: REPLAN_REQUIRED or: HUMAN_REQUIRED not “probably close enough.” 16. Intent Changes Need Sequence Numbers or Versions Wall-clock timestamps are not enough. Two instructions may arrive close together. Messages may be delayed. Workers may have different clocks. Events may be replayed. Use authoritative ordering such as: intent_version = 17 or a monotonic sequence/epoch maintained by the intent store. Then a worker can say: I am operating under intent version 16. Current version is 17. My authority is stale. That is much stronger than: My prompt seems older than the latest message timestamp. 17. New Intent Must Not Reset Old Side-Effect Identity Suppose intent v4 triggers payment operation: operation_id = payment-881 The user changes the amount and creates intent v5. Do not simply create an unrelated new operation while forgetting the old one. The runtime needs to know: payment-881 belongs to v4 may already have executed The new operation may be: payment-882 belongs to v5 but only after the old operation is classified. Otherwise supersession can accidentally duplicate side effects. Intent lineage and operation lineage therefore intersect. 18. Intent Cancellation Must Preserve Idempotency Suppose a deployment was requested, timed out, and then cancelled. Later a new intent requests the same deployment again. If the external operation uses a durable idempotency key tied only to the semantic action, we may intentionally want to reuse it. If the new intent represents a genuinely new attempt, we may need a new logical operation identity. This requires separating: intent identity logical operation identity physical attempt identity For example: intent v12 └── logical operation deploy-release-5 ├── attempt 1 └── attempt 2 intent v14 └── logical operation deploy-release-5-again └── attempt 1 Do not derive these relationships from prompt text after the fact. Record them. 19. Retries Must Recheck Intent A common bug: for retry in range(5): execute_operation() The first attempt fails. The user cancels the task. The retry loop continues anyway. Every retry should revalidate: intent current? authority current? state fresh? operation still unresolved? budget available? dependency healthy? Retry is not permission to keep trying forever under stale intent. 20. Scheduled Work Must Recheck Intent Too The same applies to delayed and deferred work. A task scheduled for 30 minutes later should not assume the objective remains active merely because the scheduler wakes it up. At wake time: load durable task ↓ load current intent ↓ compare versions/status ↓ revalidate state ↓ continue or terminate This is especially important for agents that operate over hours or days. 21. Human Approval Queues Need Intent Invalidation Suppose a reviewer sees: Approve deletion of resource R? While the request sits in the queue, the user cancels the operation. The review item must become invalid. Otherwise the reviewer may approve stale intent ten minutes later. The approval UI should show something like: SUPERSEDED — this approval request is no longer actionable not leave the old approval button active. This means the human-review system itself subscribes to intent lifecycle changes. 22. Reviewer Decisions Must Not Resurrect Cancelled Intent A delayed reviewer approval cannot reactivate an obsolete run. This sounds obvious, but distributed workflows often have late events. The correct ordering is: approval arrives ↓ load current intent ↓ validate approval binding ↓ if stale → record historical decision only The approval event remains useful provenance. It does not restore mutation authority. 23. Cancellation and Temporal Consistency Are Different Axes Step 36 asked: Is the world still the world we planned against? Step 37 asks: Are we still supposed to pursue this objective? These produce a two-dimensional validity check: INTENT CURRENT? yes no STATE yes continue stop/reconcile FRESH? no refresh/replan stop/reconcile A production commit gate should check both axes. 24. A Commit Gate Should Validate Intent Last Before a consequential side effect: candidate ready ↓ verification passes ↓ approval valid ↓ state freshness valid ↓ intent version valid ↓ ownership/fencing valid ↓ commit Why recheck intent so late? Because cancellation may arrive after verification. Or after approval. Or milliseconds before mutation. The commit gateway is the final place to stop obsolete intent from changing the world. 25. Cancellation Does Not Undo Committed Reality If the commit already happened, cancellation changes what happens next. It does not rewrite history. Suppose an email has already been sent. The user says: Cancel that. The system cannot unsend the email merely by changing intent state. Likewise: a Git commit may already be pushed; a payment may already settle; a cloud resource may already exist; a message may already have reached a user; a deployment may already be serving traffic. So cancellation after commitment becomes: stop future work + classify committed effects + apply compensation/reconciliation if available This leads directly toward the transaction and compensation stage later in the series. 26. Distinguish Reversible, Compensatable and Irreversible Effects For cancellation purposes, external effects can be classified roughly as: REVERSIBLE COMPENSATABLE IRREVERSIBLE UNKNOWN Examples: create temporary branch REVERSIBLE provision test VM REVERSIBLE charge payment COMPENSATABLE send email IRREVERSIBLE publish public statement IRREVERSIBLE unknown API timeout UNKNOWN Do not call compensation “rollback” unless it actually restores the prior state. Refunding a payment is a new transaction. Deleting a created resource is a new side effect. Sending a correction email does not erase the original email. Cancellation semantics must preserve this reality. 27. Introduce Cancellation Outcomes A boolean is too weak. Useful outcomes include: CANCELLED_BEFORE_EXECUTION CANCELLED_AFTER_PARTIAL_WORK SUPERSEDED COMMITTED_BEFORE_CANCEL RECONCILIATION_REQUIRED CANCELLATION_PENDING_EXTERNAL_CONFIRMATION CANCELLATION_BLOCKED These communicate operational truth. For example: cancelled = true would be dangerously misleading if a payment request is still ambiguous. Better: status = CANCELLATION_PENDING_EXTERNAL_CONFIRMATION 28. Intent Supersession Should Be Observable Trajectory logs should include events such as: INTENT_CREATED INTENT_SUPERSEDED INTENT_CANCEL_REQUESTED INTENT_CANCELLED INTENT_SCOPE_CHANGED INTENT_REVALIDATED INTENT_COMMIT_REJECTED_STALE CHILD_WORK_INVALIDATED RECONCILIATION_STARTED RECONCILIATION_COMPLETED Every event should carry: intent_id old_version new_version actor reason scope trace_id timestamp / sequence This makes incident investigation possible. 29. Intent Changes Need Provenance Who changed the objective? Was it: the user; an authorized reviewer; a workflow policy; an external event; another system; the agent itself? The answer matters. An agent may propose: I recommend narrowing the deployment scope. That is not the same as an authorized user actually changing the scope. Intent mutation therefore belongs in the control plane. 30. The Agent Must Not Self-Supersede Authoritative Goals An agent can discover that the requested goal is impossible, unsafe or inefficient. It may propose alternatives. It may escalate. It may refuse an unauthorized operation. But it should not silently rewrite: user objective into: objective I prefer That would collapse planning into authority. A good architecture allows: agent proposes intent amendment ↓ control plane / authorized actor evaluates ↓ new intent version created The proposed revision itself is evidence, not authority. 31. Autonomous Subgoals Are Different From Root Intent Agents often need to create internal subgoals. For example: root intent: repair failing test suite The agent may create: subgoal: inspect recent dependency changes subgoal: reproduce failure locally subgoal: test minimal patch Those can be agent-generated because they remain subordinate to the root objective and authority envelope. But they should still carry lineage: root_intent_id root_intent_version parent_goal_id If the root intent is superseded, internal subgoals lose authority unless explicitly adopted by the new intent. 32. Reuse Requires Dependency Analysis Suppose intent v10 is superseded by v11. Can we reuse a previous artifact? Ask what it depends on. Example: repository structure snapshot depends on repository SHA not on intent wording Potentially reusable. But: candidate patch ├─ repository SHA ├─ target behavior └─ intent v10 Likely invalid. Likewise: verifier evidence ├─ candidate hash ├─ verifier version ├─ acceptance criteria └─ intent-derived requirements If requirements changed, old verification does not prove the new objective. 33. Supersession Should Trigger Targeted Revalidation Do not always restart everything. Do not always reuse everything. Use dependency-aware revalidation. For example: intent changed only output format → preserve retrieval → preserve source facts → regenerate synthesis → rerun format verifier Or: deployment target changed region → preserve artifact build → invalidate region-specific checks → refresh target state → rerun regional verifier → require new approval This is much cheaper and safer than a binary restart/continue model. 34. Intent Has Freshness Too Step 36 introduced freshness budgets. Intent should have an equivalent requirement. A low-risk read-only task may check intent periodically. A destructive commit should check immediately before mutation. So instead of: check cancellation every 30 seconds use: check cadence depends on action authority For example: A0 observe periodic A1 propose before final response A2 reversible execute before operation A3 bounded effect immediately before mutation A4 consequential commit-gateway validation A5 privileged commit-gateway + explicit approval binding 35. Intent Polling Is Not Enough At scale, polling every worker wastes resources and can still race. Useful architectures combine: intent-change event stream + local cancellation token + authoritative commit-time version check The event stream provides fast propagation. The cancellation token stops cooperative work quickly. The authoritative version check prevents stale mutation even when events are delayed or dropped. This is the same layered design we used for temporal invalidation. 36. Cancellation Backpressure Matters A mass cancellation can itself create load. Imagine cancelling 100,000 queued or running tasks. Naively every worker may: wake; query state; emit logs; cancel children; perform reconciliation; retry external lookups. That can become a cancellation storm. Use bounded propagation and prioritize work by consequence. For example: 1. fence mutation immediately 2. stop queued work cheaply 3. cancel speculative work 4. reconcile in-flight side effects 5. garbage-collect low-value artifacts later Correctness first. Cleanup can lag. 37. Cancellation Must Interact With Admission Control Once an intent is cancelled: queued work should no longer consume admission slots; reserved speculative capacity should be released; verification capacity for ambiguous already-issued side effects may need to remain available; reconciliation work may need a higher priority than new speculative tasks. This connects intent lifecycle directly to Step 21. Cancellation is therefore also a resource-management event. 38. Cancellation Must Interact With Dynamic Budgets Step 16 allocated compute inside a run. When intent is superseded, the old run should stop consuming exploration budget. But some budget may still be justified for reconciliation. So budget categories should distinguish: exploration budget execution budget verification reserve reconciliation reserve After cancellation: exploration budget → zero new execution budget → zero verification reserve → preserved if needed reconciliation reserve → activated if side effects ambiguous This prevents the absurd result where a cancelled agent keeps searching for a better answer while lacking budget to establish whether its previous external action already happened. 39. Search Trees Need Intent Invalidation Tree search creates many candidate branches. If intent changes, some branches may no longer matter. Each node should carry intent lineage or requirements identity. Then: intent v8 superseded ↓ mark dependent frontier nodes obsolete ↓ retain reusable observations ↓ reseed search under v9 if justified Do not continue scoring an old search frontier because the expensive work has already been done. Sunk compute is not a reason to preserve obsolete intent. 40. Multi-Agent Systems Need Shared Intent Authority If several agents collaborate, they must not each maintain their own informal interpretation of current intent. Suppose: planner sees intent v5 coder sees intent v6 verifier sees intent v5 The system can become internally inconsistent even with individually competent agents. Use a common authoritative intent identity. Messages between agents should carry: intent_id intent_version scope Recipients reject or revalidate stale work. This becomes especially important in Step 42 when we revisit multi-agent coordination. 41. Intent Version Belongs in Cache Identity Suppose an agent caches: plan(task_text, repository_sha) The same text may appear under a different authoritative context. Or acceptance criteria may have changed without substantial wording changes. Caches for intent-sensitive artifacts should include the correct intent/requirements identity. For example: cache key = hash( intent requirements hash, repository SHA, behavioral release, policy version, ) But intent-independent artifacts should avoid unnecessary invalidation. Again, dependency analysis matters. 42. Intent Supersession Can Change Risk A new objective may be similar in semantics but completely different in consequence. For example: v1: draft the SQL migration v2: apply the SQL migration to production The content overlaps heavily. The authority class does not. Supersession should therefore trigger fresh: risk classification competence check authority decision placement filtering verifier requirements Do not inherit authority from semantic similarity. 43. Intent Supersession Can Change Competence Likewise: v1: diagnose production outage v2: execute database failover The agent may be validated for diagnosis but not autonomous failover. So a new intent version must be evaluated against Step 30’s competence envelope. Intent lineage does not imply competence transfer. 44. Intent Supersession Can Change Placement A changed goal may alter: data residency; model requirements; tools; region; verifier path; latency target; authority ceiling. So Step 34 placement should consume current intent identity rather than treat placement as fixed for the lifetime of the run. A superseded intent can produce: REPLACEMENT_REQUIRES_NEW_PLACEMENT rather than attempting to continue on an incompatible worker. 45. Intent Supersession During Handoff Step 35 added migration between workers. Now consider: source seals checkpoint for intent v20 intent v21 arrives checkpoint reaches target The target must not infer that the sealed checkpoint is current merely because its hash is valid. Resume compatibility includes: checkpoint intent version == current intent version? If not: resume as historical artifact revalidate reusable components replan under current intent or reject migration entirely. 46. Do Not Launder Stale Intent Through Checkpoints A particularly dangerous bug is: load old checkpoint create new runtime session assign current timestamp continue That can make stale work appear fresh. Checkpoint restoration must preserve: original_intent_id original_intent_version The new process may have a new attempt ID. It must not silently acquire a new intent identity. 47. Intent History Is Part of Replay Step 25 made replay provenance explicit. A faithful replay needs the intent timeline. For example: 10:00 v1 created 10:04 v2 superseded v1 10:05 worker A observed v2 10:05:03 worker B attempted stale v1 commit 10:05:03 commit gateway rejected it Without intent history, the stale commit may look inexplicable. Replay should reconstruct what each worker could legitimately know and what the authoritative control plane considered current. 48. Incident Forensics Should Ask About Intent Drift Step 26 asked for the earliest evidence-backed divergence. Add questions such as: Was the action derived from the current intent? When was the superseding intent issued? When did the worker observe it? Did the commit gate recheck intent? Was a stale approval reused? Did a retry survive cancellation? Did a child task miss invalidation? Was an ambiguous side effect reconciled? A failure that looks like “agent ignored user” may really be a control-plane propagation bug. 49. Measure Cancellation Latency Useful metrics include: intent supersession propagation latency queued-work cancellation latency mutation-fence latency in-flight operation classification latency reconciliation latency stale-intent commit rejection count wasted compute after supersession cancelled-work cleanup backlog But raw latency is not enough. The most important metric is often: consequential side effects executed after authoritative cancellation Ideally: 0 50. Measure Cancellation Waste Separately From Cancellation Safety A safe system may still waste enormous computation after intent changes. For example: mutation fenced immediately but 500 speculative workers continue for 20 minutes No dangerous side effect occurs. But resource efficiency is poor. Track both: safety latency resource quiescence latency Do not trade safety for faster cleanup. 51. Cancellation Has a Critical Path For consequential operations, the critical path is usually: intent update committed ↓ mutation authority revoked That path should be short and deterministic. Notification of every worker can happen afterward. This architecture gives us: fast correctness slower cooperative cleanup instead of requiring perfect instantaneous distributed cancellation. 52. The Commit Gateway Is the Ultimate Intent Fence Workers can fail to observe events. Caches can be stale. Models can ignore instructions. Processes can pause. Queues can delay cancellation messages. The final mutation boundary therefore checks: assert intent_store.is_current(intent_id, intent_version) assert authority_store.is_valid(authority_token) assert fencing_store.is_current(operation_scope, epoch) assert state_preconditions_hold() Only then does the side effect execute. This is the production-grade answer to “what if the model ignores the stop instruction?” Do not rely on the model. Remove its authority. 53. Hard Cancellation and Soft Supersession Not all changes need identical behavior. Useful semantics include: Hard cancellation No new work. No new side effects. Fence immediately. Reconcile existing effects. Soft supersession Stop obsolete branches. Preserve compatible evidence. Replan affected scope. Continue unaffected work. Pause No new execution. Preserve intent as potentially resumable. Freshness and approval still age normally. Defer Return work to durable queue. Require intent/state revalidation on wake. These should be explicit control-plane operations. 54. Pause Is Not Freeze Time If an intent is paused for three hours: external state changes; approvals expire; credentials expire; verifiers may change; releases may change; competence evidence may drift; the task may become OOD relative to current environment. Resume therefore means: intent still active? ↓ checkpoint compatible? ↓ state still valid? ↓ authority still valid? ↓ competence still supported? ↓ continue / reverify / replan Pause preserves intent identity. It does not preserve every assumption. 55. User Corrections Should Become Intent Events Suppose the user says: No, I meant the staging database, not production. That should not merely append another chat message. It should create a structured change: intent v18 scope.environment = staging supersedes = v17 The natural-language transcript remains useful provenance. The structured intent event becomes the control-plane truth. 56. External Events Can Supersede Intent Too Not every supersession originates from the user. Examples: ticket already resolved; pull request merged by another developer; deployment target removed; incident declared resolved; transaction deadline passed; resource deleted; policy now prohibits the operation. These may produce system-generated intent transitions such as: CANCELLED_BY_EXTERNAL_STATE SUPERSEDED_BY_POLICY OBJECTIVE_ALREADY_SATISFIED The source should be recorded explicitly. 57. “Already Satisfied” Is a Useful Intent Outcome Suppose an agent is asked to: fix failing test X Before it commits, another developer fixes the test. Step 36 tells us state changed. Step 37 lets us express the higher-level consequence: OBJECTIVE_ALREADY_SATISFIED The correct action may be to terminate without producing another patch. This is better than blindly replanning the same goal against the new state. 58. Intent Can Become Impossible A target may disappear. A deadline may pass. A required authorization may be revoked. A capability may be removed. A verifier may become unavailable. The correct state can become: INTENT_UNACHIEVABLE That is different from: FAIL A failed attempt says execution did not work. An unachievable intent says the current objective cannot legitimately be completed under available constraints. 59. Intent Can Become Prohibited A policy update may change an active task from allowed to prohibited. For example: intent created under policy p12 policy p13 forbids operation class The runtime should not grandfather the old intent merely because it started earlier, unless policy explicitly says so. This is another reason intent, policy and authority must be checked at commit time. Possible outcome: INTENT_BLOCKED_BY_POLICY 60. Cancellation Should Be Idempotent Users and systems will issue duplicate cancellation requests. That should be harmless. For example: def cancel(intent_id: str, expected_version: int) -> Intent: current = load(intent_id) if current.status in terminal_cancel_states: return current ... The cancellation API itself should have ordinary distributed-system semantics. Do not create multiple contradictory terminal states from repeated requests. 61. Supersession Should Use Optimistic Concurrency Two actors may try to update the same intent concurrently. For example: user changes target region operator cancels operation Use compare-and-set semantics: update intent WHERE version = 21 If another update already created version 22, the second actor must reread and decide what to do. Do not silently overwrite intent history. 62. Intent Lineage Should Be Immutable Once recorded: v21 superseded by v22 that lineage should not be rewritten in place. Append new state transitions. This helps: replay; auditing; incident reconstruction; debugging; user-visible history; conflict resolution. Mutable “current prompt” fields are useful caches. They should not be the only source of truth. 63. Intent Store Is Control-Plane Infrastructure A minimal design might be: IntentStore ├── create() ├── get_current() ├── get_version() ├── supersede() ├── cancel() ├── pause() ├── resume() └── history() And a validator: IntentGate ├── validate_current() ├── validate_scope() ├── validate_operation_binding() └── validate_commit() Models can help interpret intent. They should not own these transitions. 64. Example: Coding Agent Supersession Suppose the user asks: Refactor authentication to use package A. The agent: scans repository; builds dependency graph; creates candidate branch; edits six files; starts tests. Then the user says: Use package B instead. A robust system does not merely append the instruction. It records: intent/auth-refactor/v2 supersedes v1 Then dependency invalidation might produce: repo snapshot reusable symbol graph reusable test inventory reusable package-A research historical only candidate patch invalid candidate verification invalid destructive approval invalid The new run can reuse safe evidence without preserving obsolete behavior. 65. Example: Browser Purchase Cancellation Intent v3: Buy item X if total price <= €500. The agent reaches the payment page. The user cancels. The control plane: marks intent CANCEL_REQUESTED advances mutation fence invalidates payment approval cancels queued tool calls checks whether submit request was already sent If no payment was issued: CANCELLED_BEFORE_EXECUTION If payment status is unknown: CANCELLATION_PENDING_EXTERNAL_CONFIRMATION If payment succeeded: COMMITTED_BEFORE_CANCEL with a possible compensation workflow. These states are much more useful than a generic “cancelled.” 66. Example: DevOps Deployment Supersession Intent v9: Deploy image sha256:A to production. Canary begins. Then intent v10 says: Stop rollout and deploy sha256:B instead. The runtime should not jump directly from A to B. It must first determine: How much of A is live? Are any migrations committed? Is rollback/compensation needed? What traffic state exists? Which approvals remain valid? Only then can B become executable. This is why intent supersession and reconciliation must be connected. 67. Example: Research Agent Question Change Intent v1: Determine whether technology X reduced latency. After extensive retrieval, the user changes the question: Actually, determine whether it reduced total cost. Previously gathered sources may remain relevant. But the inferential target changed. So: source documents reusable extracted raw facts selectively reusable latency synthesis historical only cost-relevant claims re-evaluate final conclusion invalid This is intent-aware evidence reuse. 68. Example: Support Agent Ticket Closure A support agent is investigating a customer issue. The customer solves it independently and closes the ticket. The external event produces: OBJECTIVE_ALREADY_SATISFIED The agent should stop generating new remediation instructions. But it may still need to: finish writing audit provenance; release leases; cancel child jobs; clean temporary resources. Again: stop pursuing objective is not identical to: terminate process immediately 69. Intent-Aware Status Should Reach the User Users should not need to infer whether cancellation actually took effect. Useful responses distinguish: Stopped before any external action. from: Stopped further work. One deployment operation had already been submitted; checking its authoritative status. from: The deployment completed before cancellation. No further actions will occur; rollback requires a separate operation. This is operationally truthful UX. 70. Never Promise Cancellation Before You Have the State A common interface mistake is immediately reporting: Cancelled. before checking in-flight effects. For purely internal computation, that may be fine. For consequential workflows, use states such as: CANCEL_REQUESTED or: RECONCILING until the system knows what happened. 71. Intent Supersession Is a Release-Like Boundary A changed objective can alter system behavior just as much as a behavioral release. The code may be unchanged. The model may be unchanged. But: intent v7 → v8 can change: required evidence; acceptance criteria; authority; tools; placement; verifier requirements; side effects. So intent transitions deserve first-class provenance. 72. Intent Versioning Helps Benchmark Agent Responsiveness We can test scenarios such as: start long-running task wait until expensive planning begins supersede objective measure stale work and side effects Metrics: stale-intent compute after supersession stale-intent tool calls stale-intent side effects replan latency artifact reuse rate false reuse rate reconciliation latency This makes cancellation architecture benchmarkable. 73. Failure Injection: Drop the Cancellation Event A crucial test: worker begins under v3; control plane creates v4; cancellation event to worker is deliberately dropped; worker attempts consequential mutation under v3. Expected result: commit gateway rejects stale intent version If the operation still succeeds, the architecture relies too heavily on cooperative workers. 74. Failure Injection: Delay the Cancellation Event Another test: supersede intent; delay event delivery by 30 seconds; allow worker to continue reasoning; ensure no stale consequential mutation succeeds. Some wasted compute may occur. Correctness must hold. 75. Failure Injection: Cancel During Retry Scenario: attempt 1 fails retry scheduled intent cancelled retry fires Expected: retry observes stale/cancelled intent retry terminates before mutation 76. Failure Injection: Cancel During Human Approval Scenario: approval requested intent cancelled human approves stale request Expected: approval stored as historical event commit authorization rejected 77. Failure Injection: Cancel During Handoff Scenario: source seals checkpoint under v8 target starts transfer v9 supersedes v8 target activates Expected: target cannot inherit mutation authority from v8 It may reuse compatible historical state only after revalidation. 78. Failure Injection: Cancellation After Ambiguous Timeout Scenario: external mutation request sent client times out user cancels Expected: no blind retry no claim that nothing happened query external authoritative state classify operation reconcile This is one of the most important real-world tests. 79. Failure Injection: Concurrent Supersession Two actors attempt: v20 → change scope v20 → cancel Expected: only one transition commits against v20 other actor receives version conflict reloads current intent makes explicit next decision No last-write-wins overwrite. 80. A Minimal Intent Gate The first implementation can be extremely small. For example: from dataclasses import dataclass from enum import Enum class IntentDecision(str, Enum): CURRENT = "CURRENT" SUPERSEDED = "SUPERSEDED" CANCELLED = "CANCELLED" UNKNOWN = "UNKNOWN" @dataclass(frozen=True) class IntentRef: intent_id: str version: int class IntentGate: def __init__(self, store): self.store = store def validate(self, ref: IntentRef) -> IntentDecision: current = self.store.get_current(ref.intent_id) if current is None: return IntentDecision.UNKNOWN if current.status == "CANCELLED": return IntentDecision.CANCELLED if current.version != ref.version: return IntentDecision.SUPERSEDED return IntentDecision.CURRENT Then put this check at the actual mutation boundary. Do that before building a learned intent-compatibility model. 81. Add Scoped Compatibility Later Once deterministic lifecycle correctness exists, richer reuse can be added. For example: @dataclass(frozen=True) class SupersessionAnalysis: old_intent: IntentRef new_intent: IntentRef reusable_artifact_ids: tuple[str, ...] invalid_artifact_ids: tuple[str, ...] reverify_artifact_ids: tuple[str, ...] requires_replan: bool evidence_refs: tuple[str, ...] This may use dependency graphs and, where necessary, model-assisted semantic comparison. But it is optimization. The hard safety rule remains: old intent cannot commit after supersession 82. Keep Intent Interpretation and Intent Authority Separate A model is very useful for turning: "Actually don't touch the payments part, just update the invoice template" into structured proposed changes. But the pipeline should be: natural language ↓ intent interpretation ↓ structured proposed transition ↓ authoritative intent store ↓ new version Not: model decides current intent internally This distinction will become central when we build the explicit control plane later. 83. The User’s Latest Message Is Not Always the Entire Intent A later message can refine rather than replace. For example: v1: refactor the parser and keep backwards compatibility v2 message: use dataclasses for the new AST nodes Version v2 should preserve the backwards-compatibility constraint unless explicitly removed. So an intent transition may be a structured patch over the prior intent rather than wholesale replacement. The runtime should preserve the resulting resolved intent plus provenance of the change. 84. Intent Resolution Is Similar to Configuration Resolution Think of it as: base intent + amendments + scoped overrides + cancellations = current resolved intent But unlike ordinary configuration, intent has: actor authority; temporal ordering; consequences already in flight; human meaning; external side-effect bindings. So the resolved object needs durable lineage. 85. Do Not Hide Intent History Behind a Single Prompt A tempting implementation is: rewrite prompt with latest instructions That improves model context. It does not solve control-plane correctness. You still need to know: which operation came from which version? which approval was for which version? which worker is stale? which artifact is reusable? which side effect needs reconciliation? The prompt is an execution input. It is not the intent ledger. 86. Intent Is Not Memory Memory answers: What happened before? What information may help now? Intent answers: What objective currently has authority? Those are different systems. A memory entry saying: user wanted production deployment must never override current intent saying: production deployment cancelled Authoritative intent beats remembered preference or historical instruction. 87. Intent Is Not Policy Intent says: what the actor wants Policy says: what the system permits A current intent can still be prohibited. Likewise a policy can permit an action that nobody currently wants. So the commit gate needs both: current intent AND valid authority/policy Neither substitutes for the other. 88. Intent Is Not Competence A user may currently want something the system cannot reliably do. For example: intent = repair safety-critical firmware autonomously Current competence may be: proposal only The result should be: HUMAN_REQUIRED or: NO_SUPPORTED_EXECUTION_PATH not autonomous action merely because intent is current. 89. Intent Is Not Verification A user can authorize the system to attempt an operation. That does not prove the operation succeeded. Intent answers: should we pursue this objective? Verification answers: did the resulting action achieve the required condition? These remain separate throughout the lifecycle. 90. Intent Validity Becomes One More Commit Invariant By this point our consequential commit boundary may require: intent current state fresh competence sufficient authority valid approval valid if required placement eligible ownership epoch current operation idempotency valid candidate verified budget available policy current This may look like a lot. But notice where the complexity lives. It is mostly deterministic control-plane logic. The model is not being asked to remember ten safety rules in its prompt. That is exactly the architecture we want. 91. The Goal Is Not Maximum Cancellation Sophistication Do not build a giant intent engine because the diagram is attractive. Start with the failure you actually have. A simple coding assistant may need only: run_id intent_version cancel flag commit-time version check A financial workflow may need: scoped supersession approval invalidation operation reconciliation idempotency compensation immutable intent history The same principle still applies: Add mechanisms because measured failure requires them, not because advanced architecture is available. 92. Benchmark Against Simple Cancellation Before adopting the full architecture, compare: Baseline A cooperative cancellation token only Baseline B cancel flag + durable run state Baseline C intent version + commit-time fence Advanced scoped supersession + invalidation graph + selective artifact reuse + reconciliation Measure: stale-intent side effects; wasted compute; cancellation latency; recovery latency; artifact reuse; false reuse; operational complexity. For many systems, baseline C may already solve the critical safety problem. That is a success. 93. What We Have Now The architecture through Step 37 now looks like: user / external actor ↓ authoritative intent ↓ competence envelope ↓ authority policy ↓ placement ↓ planning / search / tools ↓ candidate ↓ verification ↓ commit gate ├─ intent current? ├─ state fresh? ├─ authority valid? ├─ approval valid? ├─ ownership current? └─ candidate still verified? ↓ side effect ↓ postcondition verification And around the entire flow: provenance replay SLOs incident forensics budgets cancellation supersession This is no longer a prompt loop with tools attached. It is a controlled execution system containing probabilistic reasoning. 94. The Deeper Principle The simplistic view of an agent is: user says something model tries to accomplish it The production view is: an authorized intent version creates bounded work under explicit state assumptions within a competence envelope using controlled execution paths until that intent is completed, superseded or cancelled That shift matters enormously. Without it, an agent can become perfectly competent at pursuing something nobody wants anymore. A production system needs to answer at every consequential boundary: Is this still the task? Not merely: Can we still perform the task? 95. Final Rule If you remember one thing from this post, make it this: Do not treat cancellation as a message to the model. Treat current intent as an enforceable control-plane invariant. A good agent should notice that the user changed their mind. A safe platform should remain correct even if the worker does not. Next: Goals, Commitments and Executable Work Intent versioning tells us which objective is current. But a real objective decomposes into many pieces of work. Some survive supersession. Some become invalid. Some become commitments once external effects begin. Some are merely speculative tasks that can disappear immediately. The next problem is therefore: Which parts of an agent plan are goals, which are commitments, and which are disposable execution steps? That is where we go next.