# Advanced Agents From First Principles 38: A Plan Is Not a Commitment — Model Goals, Commitments and Executable Work # Book: Advanced Agents From First Principles # Chapter URL: https://programmer.ie/books/advanced-agents-from-first-principles/38-chapter/ # Prose fingerprint (sha256, normalized): 384da2e7c44f5f197d68a6194fcc8c44eb0a591586fba91896a591ee136f2d04 # 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. An agent says: I will deploy the release after the migration check passes. What exactly just happened? Did the agent merely describe a possible future? Did it reserve a deployment slot? Did it tell another service to prepare capacity? Did it promise a human that the deployment would happen? Did it create a task in a queue? Did it acquire a lock? Did it actually start the deployment? Those are not the same thing. Yet many agent systems represent all of them as some variation of: plan step = deploy release That becomes dangerous as soon as agents operate for more than a few seconds. A plan may be abandoned. A commitment may need to be discharged. A queued task may be retried. An external reservation may need to be released. An irreversible action may need reconciliation rather than cancellation. If the architecture treats all of those as ordinary plan nodes, replanning becomes a source of hidden side effects. Step 37 introduced versioned intent, supersession and cancellation. That answered an important question: Is the system still pursuing the current objective? But intent alone is not enough. A long-running autonomous system needs another distinction: What has the system merely considered, and what has it actually committed itself or others to? The core rule for this post is: A plan describes possible future work. A commitment creates an obligation or dependency that must be explicitly satisfied, released, transferred or reconciled. This distinction turns out to affect planning, retries, cancellation, scheduling, human review, multi-agent coordination and incident recovery. The Search Problem: “How Should AI Agents Manage Goals and Commitments?” Most agent planning examples have a shape like this: Goal ↓ Plan ↓ Step 1 Step 2 Step 3 That is useful for explaining planning. It is incomplete for production systems. The problem is that the nodes do not all have the same semantics. Consider this plan: Goal: deploy release 4.2 1. inspect repository 2. run migration check 3. reserve deployment window 4. notify operations 5. deploy release 6. verify service health Step 1 is mostly observation. Step 2 is execution with local consequences. Step 3 may reserve scarce shared capacity. Step 4 creates an expectation for another person. Step 5 changes production. Step 6 observes whether that change worked. Calling all six items “tasks” erases information the runtime needs. The architecture needs to know: Which items can be discarded? Which items must be released? Which items create external obligations? Which items can be transferred to another worker? Which items survive replanning? Which items require reconciliation after cancellation? Which items already changed the world? That is why we need a richer model. Five Different Things A useful hierarchy is: intent ↓ goal ↓ subgoal ↓ commitment ↓ task ↓ action These are related. They are not interchangeable. Intent Intent answers: What outcome does the principal currently want? Step 37 made intent versioned and authoritative. Example: intent_id = release-production version = 7 objective = deploy version 4.2 safely Goal A goal is a desired state that supports the intent. production is running version 4.2 A goal describes what should become true. It does not necessarily say how. Subgoal A subgoal is a decomposed desired state. migration compatibility established release artifact verified production capacity available Subgoals help structure planning. Commitment A commitment is different. It records that the system has crossed a boundary where some obligation now exists. Examples: capacity reserved until 15:30 reviewer requested and awaiting response customer notification scheduled maintenance window announced exclusive lock acquired external job submitted payment authorized A commitment may exist before the final action occurs. And critically: A commitment may survive the plan that created it. Task A task is executable work assigned or ready to be assigned. run migration compatibility test Tasks may be retried, rescheduled, transferred or cancelled depending on their state. Action An action is an individual execution attempt or operation. invoke migration-check tool with repository SHA abc123 Actions are where idempotency, side effects, tool results and postconditions become concrete. Why a Plan Is Not a Commitment Suppose the planner emits: 1. inspect schema 2. reserve deployment window 3. run migration 4. deploy Before step 2 executes, that plan can usually be thrown away. After the reservation succeeds, something changed. Another team may now be waiting. Capacity may be unavailable to another deployment. A timed resource may be held. The system has created an obligation. That means replanning cannot simply produce: new plan: 1. do something else and forget the reservation. The old plan is disposable. The old commitment is not. This gives us the first important invariant: plan deletion MUST NOT imply commitment deletion A commitment needs an explicit lifecycle transition. The Commitment Ledger A production agent should have a durable commitment ledger. For example: from dataclasses import dataclass from datetime import datetime from enum import Enum class CommitmentStatus(str, Enum): PROPOSED = "proposed" ACTIVE = "active" SATISFIED = "satisfied" RELEASE_PENDING = "release_pending" RELEASED = "released" TRANSFER_PENDING = "transfer_pending" TRANSFERRED = "transferred" BREACHED = "breached" RECONCILIATION_REQUIRED = "reconciliation_required" UNKNOWN = "unknown" @dataclass(frozen=True) class Commitment: commitment_id: str intent_id: str intent_version: int goal_id: str owner_id: str status: CommitmentStatus obligation_type: str resource_refs: tuple[str, ...] counterparty_refs: tuple[str, ...] created_at: datetime due_at: datetime | None release_operation_id: str | None evidence_refs: tuple[str, ...] The exact schema will vary. The key is the semantics. The ledger says: what obligation exists why it exists who owns it which intent created it what external objects it touches when it expires how it can be satisfied or released what evidence proves the lifecycle transition That is much stronger than storing a sentence in agent memory saying: remember: we reserved deployment capacity Commitments Must Be Authoritative State The model may reason about commitments. It should not be the authority on whether they exist. Bad architecture: if "reservation complete" in agent_memory: reserved = True Better: reservation = reservation_store.get(reservation_id) if reservation.status == "ACTIVE": ... This follows the same principle we have used throughout the series: When the system already has an authoritative state source, query it instead of asking the model to infer the state. A commitment ledger therefore belongs in the control plane. Proposed Commitments vs Active Commitments It is useful to distinguish: PROPOSED from: ACTIVE A planner can propose: reserve GPU capacity for 30 minutes without actually reserving anything. That proposal may be scored, compared, rejected or revised. Only after the external reservation operation succeeds should the commitment become ACTIVE. The transition might look like: PROPOSED ↓ execute reservation operation ↓ verify reservation exists ↓ ACTIVE This prevents a common agent mistake: model says it will do something ↓ system behaves as though it already happened Planning language is not evidence of commitment creation. Commitments Need Evidence Every important commitment should be backed by evidence. For a deployment reservation: commitment_id reservation_id provider response resource identity start time expiry time verification observation For a human review request: review request ID reviewer identity or routing group submitted artifact hash submitted intent version expiry For an external job: job ID idempotency key submitted payload hash current remote status This means commitment state can participate in replay and incident forensics. We can answer: Why did the agent think this obligation existed? Was it actually created? Was it later released? Which intent version created it? Was the release verified? Commitment Creation Is a Side Effect This sounds obvious. Architecturally, it matters. If the agent reserves a deployment slot, schedules an email, creates a ticket, acquires a lock or submits a job, it has already changed the world. That operation should therefore have the same safeguards as other consequential tool calls: current intent current state valid authority idempotency ownership fresh approval if required commit operation postcondition verification A commitment is not “just metadata.” It can consume resources or create expectations. Commitment Scope Commitments should be scoped. Suppose an intent contains three goals: G1: update backend G2: update frontend G3: publish release notes A deployment reservation may belong only to G1. A documentation-review request may belong only to G3. If G2 is superseded, we should not automatically release G1’s reservation. This means the graph matters: intent ├── G1 │ └── C1 deployment reservation ├── G2 │ └── C2 browser test session └── G3 └── C3 reviewer request Supersession can then invalidate only the affected subtree. Step 37’s scoped intent invalidation becomes more precise when commitments are explicit nodes. Goals Should Be States, Not Commands A useful design rule is to represent goals primarily as desired states. Instead of: run database migration prefer: database schema satisfies release 4.2 requirements Why? Because the first phrase encodes one particular action. The second defines a condition that may be achieved in several ways. This makes replanning much easier. Goal: schema is compatible Possible plans: - run migration A - run migration B - discover migration already applied - discover schema already compatible The goal can survive while the plan changes. This is another important separation: goal identity ≠ plan identity A Goal May Already Be Satisfied Step 37 introduced OBJECTIVE_ALREADY_SATISFIED. At the goal level, this becomes normal. Before executing work, the system should ask: Is the desired state already true? Example: def goal_status(goal, state_provider): state = state_provider.observe(goal.state_scope) return goal.acceptance_predicate(state) This is another reason goals need external acceptance criteria. If a goal has no observable completion condition, the runtime cannot reliably know whether it is done. Goal Acceptance Criteria A goal can be represented with explicit acceptance evidence. @dataclass(frozen=True) class Goal: goal_id: str intent_id: str description: str acceptance_check: str evidence_requirements: tuple[str, ...] risk_class: str For example: Goal: production runs release 4.2 Acceptance: - deployment reports version 4.2 - health checks pass - error budget remains within rollout threshold The model may help formulate the goal. But final acceptance should use the verifier architecture established earlier in the series. Decomposition Creates Dependencies Once we separate goals and subgoals, we need dependency semantics. Consider: G0 deploy release ├── G1 artifact verified ├── G2 migration compatible ├── G3 capacity available └── G4 deployment executed G4 may require G1, G2 and G3. That is not necessarily the same as requiring them to run in sequence. A dependency graph allows: G1 ─┐ G2 ─┼──> G4 G3 ─┘ The runtime can parallelize independent work while preserving required preconditions. This connects directly to Step 19’s speculative execution and Step 21’s scheduling/backpressure. Hard Dependency vs Advisory Dependency Not every relationship should block execution. Useful edge types include: REQUIRES ENABLES PREFERS INVALIDATES CONFLICTS_WITH SATISFIES For example: migration verification REQUIRES schema snapshot while: performance benchmark PREFERS warm cache The first is a correctness condition. The second is a quality preference. Collapsing both into “dependency” makes orchestration brittle. Commitment Dependencies Are Stronger A commitment can create dependencies in both directions. Suppose: C1 = maintenance window reserved The deployment may depend on C1. But C1 also creates an obligation: if deployment cancelled release reservation That means commitments generate cleanup dependencies. A useful graph might include: G4 deploy release REQUIRES C1 C1 active reservation ON_SUPERSESSION -> release operation R1 This is the beginning of durable workflow semantics. Commitment Lifecycle A practical commitment lifecycle might be: PROPOSED ↓ ACTIVE ├──> SATISFIED ├──> RELEASE_PENDING -> RELEASED ├──> TRANSFER_PENDING -> TRANSFERRED ├──> BREACHED └──> RECONCILIATION_REQUIRED Each transition should be explicit. SATISFIED The obligation was fulfilled. Example: reviewer completed requested review RELEASED The obligation no longer exists and release was verified. Example: reserved capacity returned TRANSFERRED Ownership moved to another actor or workflow. Example: incident response handed from autonomous workflow to human operations BREACHED The obligation was not met within its required conditions. Example: service promised response before deadline, deadline expired RECONCILIATION_REQUIRED The system cannot currently prove the external state. Example: release request timed out while cancellation was in flight This preserves uncertainty rather than inventing a clean state. Cancellation Does Not Erase Commitments Suppose the user says: cancel the deployment Step 37 correctly invalidates future mutation authority. But what about these existing commitments? maintenance window reserved reviewer waiting deployment job submitted customer notice scheduled The answer cannot be: intent cancelled -> delete everything Instead: intent cancelled ↓ block new dependent actions ↓ inspect active commitments ↓ for each commitment: satisfy? release? transfer? compensate? reconcile? This is why commitment state must outlive the plan that created it. Cancellation Can Create New Work This sounds paradoxical: cancel work ↓ create more work But it is normal. Cancelling a deployment may require: release reservation cancel queued job revoke approval token notify reviewer reconcile in-flight API call restore temporary capacity setting These are cancellation obligations. The runtime therefore needs to distinguish: business work from: cleanup / reconciliation work Otherwise cancellation can accidentally cancel the work required to make cancellation safe. Protected Reconciliation Work Step 16 protected verification budgets. Step 37 protected reconciliation budgets during cancellation. The same principle applies here. If cancellation exhausts all remaining execution budget, the agent may be unable to release resources it already reserved. Therefore: run budget ├── exploration reserve ├── verification reserve └── reconciliation reserve The exact proportions are workload-dependent. The architectural rule is stronger: Do not let optional exploration consume the resources required to discharge existing obligations. Task State Is Not Commitment State Suppose a task says: cancel reservation C1 The task may succeed as a local process while the commitment remains unresolved. For example: cancel API returned 202 Accepted That does not prove the reservation is gone. So: task complete ≠ commitment released The system must verify authoritative external state. This mirrors our earlier rule: tool call succeeded ≠ real-world objective satisfied Commitments Need Owners Every active commitment should have a responsible owner. That owner may be: workflow agent worker human operator external service organizational role But it should be explicit. Why? Because distributed systems fail. Workers disappear. Agents are cancelled. Deployments are handed off. If commitments are merely attached to ephemeral workers, they become orphaned. Bad: worker-17 owns reservation because worker-17 created it Better: workflow release-42 owns reservation worker-17 currently services the obligation This separates durable ownership from physical execution. Servicing a Commitment vs Owning It This is analogous to Step 35’s separation between logical run state and physical worker state. We can say: commitment owner = durable accountable workflow/entity servicing worker = current executor responsible for progress A worker can fail without destroying ownership. Another worker can take over through a controlled handoff. Commitment Transfer Some obligations can be transferred. Example: autonomous incident agent ↓ human operator takes control The transfer should be explicit: TRANSFER_PENDING ↓ target acknowledges commitment ↓ ownership record updated ↓ source loses authority ↓ TRANSFERRED This is very similar to lease/fencing handoff. A commitment should not be considered transferred simply because the source sent a message saying: your problem now The target must accept or an authoritative control plane must assign ownership under a defined policy. Delegation Is Not Abdication Multi-agent systems make this especially important. Agent A may delegate a task to Agent B. That does not automatically transfer the original commitment. Agent A owns commitment C1 ↓ delegates task T1 to Agent B Agent B may execute the work while A remains accountable for C1. Alternatively, the system may explicitly transfer C1. Those are different operations. This distinction becomes crucial in Step 42 when we return to multi-agent coordination. Deadlines Belong to Commitments, Not Prompts If an obligation expires at 15:00, that deadline should not live only in natural-language context. It belongs in durable state. @dataclass(frozen=True) class CommitmentDeadline: due_at: datetime grace_until: datetime | None missed_action: str escalation_policy: str Then the workflow can reason deterministically: if now > due_at: commitment = BREACHED run escalation policy The model may interpret consequences. It should not be responsible for remembering the clock. Expiry Is Different From Satisfaction A reservation may expire automatically. That does not mean the commitment was satisfied. Consider: commitment: maintain reservation until deployment completes reservation expires before deployment The commitment may now be breached. So: external resource expired ≠ obligation satisfied Again, explicit semantics matter. Commitments Can Be Conditional Some commitments activate only when a condition becomes true. Example: if migration succeeds, notify release channel That can be represented as: PENDING_CONDITION ↓ condition satisfied ↓ ACTIVE This is preferable to storing the rule only inside a planning transcript. Conditional commitments are one of the points where the architecture starts naturally evolving into durable workflow semantics. Commitments Can Conflict Suppose two agents create: C1: reserve environment E for release A C2: reserve environment E for destructive migration B The runtime should be able to detect that those obligations conflict. A commitment graph can include: CONFLICTS_WITH or resource-level exclusivity constraints. This should be deterministic whenever the resource semantics are known. Do not ask an LLM to arbitrate an exclusive lock if the platform can enforce one directly. Resource Commitments Many commitments are really claims over resources: GPU capacity browser session repository worktree cloud environment maintenance window human reviewer slot financial budget API quota exclusive lock This connects commitments directly to Step 21’s admission control and Step 16’s budgets. The scheduler needs to know which resources are merely desired versus already committed. Reservations Need Expiry and Reclamation A leaked reservation is a reliability bug. Therefore resource commitments should generally have: owner lease or expiry renewal policy release path reconciliation path Long-lived commitments without bounded ownership can become permanent resource leaks. This is especially dangerous when agents create reservations faster than humans notice them. Human Commitments Are Real Commitments Human review systems also create obligations. Suppose the agent escalates: Need database approval before 14:00 That creates several stateful facts: review requested review packet version reviewer group deadline current status If the intent is superseded, the request should be withdrawn or marked obsolete. Otherwise a reviewer may later approve stale work. Step 29 already gave us approval expiry and artifact binding. The commitment model explains why review requests themselves need lifecycle state. Communication Can Create Commitments This is easy to miss. An agent that sends: We will deploy at 15:00 has potentially created an organizational commitment even if no technical resource was reserved. That means communication tools may need authority classes based not only on data sensitivity but on commitment semantics. Sending an informational message: Migration test passed. is different from: Deployment will happen at 15:00. The second creates an expectation that may need release or correction. Proposal Mode Helps For many high-consequence systems, the safest architecture is: agent proposes commitment ↓ human or policy approves ↓ commitment created For example: PROPOSED: reserve €50,000 cloud capacity for benchmark The agent can reason about the trade-off without having authority to create the obligation. This is another case where reducing authority does not reduce reasoning quality. Plans Should Reference Commitments, Not Recreate Them Suppose a deployment reservation already exists. A replan should produce: use commitment C1 not: reserve another deployment window This avoids duplicate commitments. The planner therefore needs access to the commitment ledger as structured state. This also creates opportunities for idempotency and reuse. Commitment Identity Prevents Duplication A logical commitment may have several execution attempts. Example: commitment C1: obtain deployment reservation attempt A: timeout attempt B: retry If the first attempt actually succeeded remotely, attempt B must not create a second reservation. So we again need: logical commitment ID physical attempt ID idempotency key Step 20 established the same distinction for distributed work. The commitment layer carries it into goal orchestration. Plans Must Be Allowed to Change We do not want the commitment architecture to make planning rigid. Quite the opposite. A good system should allow: same goal same commitments new plan when possible. Example: Goal: verify release Commitment: reviewer has reserved 30 minutes Old plan: run full benchmark then review New plan: run targeted regression suite then review The commitment can remain valid if its preconditions still hold. This is why commitment compatibility should be checked rather than assumed. Replanning Needs a Commitment Diff When a new plan replaces an old plan, compute: old commitments vs new required commitments Classify each existing commitment: KEEP RELEASE TRANSFER REVALIDATE RECONCILE For example: class CommitmentDisposition(str, Enum): KEEP = "keep" RELEASE = "release" TRANSFER = "transfer" REVALIDATE = "revalidate" RECONCILE = "reconcile" That gives replanning operational semantics. Without it, the system can silently leak obligations every time the plan changes. Semantic Compatibility Is Not Enough A model may judge: old reservation probably still useful But if the new plan changes: environment region release version time window resource quantity risk class then the commitment may no longer be valid. Use deterministic compatibility checks wherever possible. Model-assisted interpretation should remain secondary. Commitments Bind to Intent Versions Every commitment should record the intent version that justified it. Why? Because Step 37 allows the objective to change. If intent version 7 created: C1 reserve production window and version 8 changes the objective to: do not deploy; produce a report only then C1 becomes a stale commitment that likely needs release. The commit gateway should also reject any new side effect justified only by obsolete commitment state. Commitment Revalidation After Supersession Not every old commitment becomes invalid. Suppose intent changes from: deploy version 4.2 to: deploy version 4.2 after one additional test The existing maintenance window may still be useful. So supersession should trigger: commitment dependency analysis ↓ KEEP / REVALIDATE / RELEASE / RECONCILE This is the same selective invalidation principle we used for evidence and artifacts. Tasks Are Disposable More Often Than Commitments Tasks should usually be cheap to recreate. run test suite inspect logs query API summarize findings If a worker disappears, the task can be retried. If the plan changes, the task can often be cancelled. Commitments are different because they represent durable external obligations. This suggests different storage policies: Tasks: queue/workflow state Commitments: durable authoritative ledger They may live in the same database. They should not have the same semantics. Actions Need Operation Identity At the bottom of the hierarchy, actions are concrete attempts. @dataclass(frozen=True) class ActionAttempt: operation_id: str attempt_id: str task_id: str commitment_id: str | None intent_version: int tool_id: str input_hash: str started_at: datetime This connects the commitment model directly to: idempotency, fencing, side-effect verification, replay, incident forensics. The hierarchy is therefore not merely conceptual. It gives us identifiers that link the entire trajectory. A Complete Lineage A consequential action should be traceable through: intent I7 ↓ goal G3 ↓ commitment C9 ↓ task T12 ↓ operation O22 ↓ attempt A31 ↓ external effect E44 ↓ verification V52 That is enormously useful during an incident. Instead of asking: Why did the agent do this? we can query: Which current intent justified this commitment? Which goal did it support? Who owned the commitment? Which task serviced it? Which operation caused the side effect? Which verifier accepted the outcome? Commitment Graphs Help Incident Forensics Imagine an incident where production capacity remained reserved overnight. The final visible symptom is: unexpected resource cost But the forensic graph may reveal: intent superseded ↓ old plan invalidated ↓ reservation commitment remained ACTIVE ↓ release task was cancelled with ordinary work ↓ resource leaked The root cause is not “agent forgot to release capacity.” The root cause is a bad cancellation model that did not distinguish business tasks from obligation-reconciliation tasks. This is exactly the type of distinction Step 26’s incident pipeline needs. Commitment SLOs Once commitments are explicit, they can have reliability metrics. Useful measurements include: active commitments orphaned commitments commitment age commitment breach rate release latency transfer latency reconciliation latency unknown commitment state duplicate commitment rate stale-intent commitment count For critical systems, we may define an SLO such as: 99.99% of cancelled resource reservations must reach verified RELEASED state within 60 seconds The point is not the particular number. The point is that commitment correctness becomes observable. Orphan Detection One especially valuable invariant is: ACTIVE commitment MUST have valid durable owner If not: ORPHANED_COMMITMENT should become an incident or reconciliation event. This can be checked deterministically. No model is necessary. Commitment Garbage Collection Is Dangerous It may be tempting to periodically delete old commitments. Do not confuse data retention with lifecycle cleanup. An old commitment with no recent activity may still represent a real external obligation. Garbage collection should occur only after authoritative terminal state is established: SATISFIED RELEASED TRANSFERRED and retention policy allows archival. Age alone is not evidence of nonexistence. Unknown Must Remain Unknown Suppose the agent submitted a cancellation request. The provider timed out. We cannot tell whether the reservation still exists. The commitment state should be: RECONCILIATION_REQUIRED or: UNKNOWN not: RELEASED because that is what the system hoped happened. This preserves one of the most important principles from the reliability section: UNKNOWN is a real state, not a failure of confidence. Some Commitments Are Irreversible Not every commitment can be released. Examples may include: message already sent public announcement made contractual instruction issued irreversible external submission For those commitments, cancellation may require: correction follow-up communication compensation human escalation reconciliation This tees up Step 40’s deeper treatment of compensation. Reversible, Releasable, Compensatable, Irreversible It is useful to classify commitment resolution semantics. RELEASABLE external obligation can be explicitly removed EXPIRING obligation ends automatically but may still breach expectations TRANSFERABLE ownership can move COMPENSATABLE original effect remains but another action can mitigate it IRREVERSIBLE cannot be meaningfully undone UNKNOWN system cannot currently establish the real external state This should affect authority and planning. The more irreversible the commitment, the stronger the approval and verification requirements should generally be. Commitments and Human Trust There is a human-facing reason this distinction matters. People tolerate agents exploring options. They care deeply when agents begin making promises or consuming resources. A system that says: I am considering a deployment at 15:00 is very different from one that says: The deployment is scheduled for 15:00 The interface should reflect that difference. Agent UX can expose states such as: PLAN PROPOSED COMMITMENT ACTIVE COMMITMENT EXECUTING VERIFIED COMPLETE That improves trust because the system stops pretending thought and action are the same thing. Do Not Let Natural Language Create Hidden Commitments This is a subtle but important safety boundary. A model may generate: I'll make sure this is completed by tomorrow. Unless the system explicitly translates that into an approved structured commitment, it should remain text. Otherwise ordinary generated language can silently create operational obligations. A safer pattern is: model proposes commitment ↓ structured parser / explicit action ↓ authority check ↓ commitment ledger write This is analogous to typed tool calls. Natural language alone should not mutate the commitment ledger. Commitment APIs Should Be Narrow Rather than giving the model generic database write access, expose narrow operations: create_commitment(...) release_commitment(...) transfer_commitment(...) mark_satisfied(...) request_reconciliation(...) Each operation can enforce: valid state transition, current intent, authority, ownership, resource identity, evidence requirements, idempotency. This keeps the control plane deterministic. State Machines Beat Prompt Instructions A prompt might say: Remember to release reservations when plans change. That is not an invariant. A state machine can enforce: intent superseded AND active commitment no longer supported ↓ commitment MUST enter RELEASE_PENDING or RECONCILIATION_REQUIRED Use language models for ambiguity. Use state machines for rules you already know. A Minimal Commitment Runtime The architecture does not require a giant framework. A minimal version could be: class CommitmentRuntime: def create(self, proposal, context): self.intent_gate.require_current(proposal.intent_version) self.authority_gate.require( proposal.required_authority, context, ) operation = self.executor.create_external_obligation(proposal) observed = self.observer.verify(operation) if not observed.confirmed: return self.store.record_unknown(proposal, operation) return self.store.activate(proposal, observed) def release(self, commitment, context): self.intent_gate.require_release_allowed(commitment, context) operation = self.executor.release_external_obligation(commitment) observed = self.observer.verify_release(operation) if not observed.confirmed: return self.store.require_reconciliation(commitment, operation) return self.store.mark_released(commitment, observed) The important part is not the Python. It is the boundary: propose authorize execute observe transition durable state What Should the Model Do? The model can be useful for: proposing goal decomposition identifying possible commitments interpreting ambiguous user intent suggesting commitment compatibility after replanning explaining consequences of release or breach ranking alternative plans The model should not be authoritative for: whether a commitment currently exists whether a reservation was released who owns an active obligation whether the current intent version is valid whether a deadline passed whether a lock is still held whether an external side effect occurred Those should come from structured state and authoritative observations. Planning With Commitments A planner should receive at least: current intent current goals active commitments resource constraints current state competence envelope authority limits Then it can produce candidate plans that respect obligations already in force. Without this context, planning is stateless fantasy. Plan Scoring Should Include Commitment Cost Plans that create many commitments are not necessarily better. Suppose two plans achieve the same goal. Plan A: creates five external reservations requires two human reviews locks production environment Plan B: uses existing evidence requires one reversible sandbox action The planner should consider commitment burden. That burden includes: resource cost human attention release complexity failure exposure reconciliation cost irreversibility This is another way complexity must earn its place. Commitment Debt An agent can accumulate too many unresolved obligations. Call this commitment debt if the metaphor is useful. A practical measurement could be: number of ACTIVE commitments weighted by age, consequence and unresolved uncertainty High commitment load should affect admission control. A workflow with many unresolved external obligations may need to stop creating new ones until it catches up. This connects directly to Step 21 backpressure. Commitment-Aware Admission Control Suppose a workflow already has: 12 active browser sessions 3 pending human reviews 2 reserved GPU jobs 1 unresolved production mutation Should it create ten more speculative branches that reserve additional resources? Probably not. Admission policy can include: active_commitment_count commitment_risk reconciliation_backlog human-review backlog resource-reservation pressure This makes capacity planning more semantically aware than raw queue depth. Commitment-Aware Search Search algorithms also need to know when a branch crosses a commitment boundary. Before commitment: branch freely prune aggressively After commitment: branch carries cleanup obligations This changes the economics of speculative execution. A search node that creates an external reservation is no longer an isolated hypothetical node. Therefore a useful rule is: Keep search branches side-effect-free as long as possible. This aligns with Step 29’s prepare/simulate/verify-before-commit architecture. Keep Commitments Near the Commit Boundary When possible: reason ↓ simulate ↓ verify candidate ↓ create necessary commitments ↓ commit consequential action rather than: create reservations notify humans lock resources ↓ then begin thinking Delayed commitment reduces cleanup burden. But sometimes early commitment is necessary—for scarce capacity, external deadlines or human coordination. That should be an explicit trade-off. Commitment Timing Is an Optimization Problem Creating a commitment too early has carrying cost. Creating it too late risks losing the resource. For example: reserve GPU now -> guaranteed capacity, but idle cost reserve GPU later -> lower cost, but possible unavailability This resembles Expected Value of Information and dynamic budgeting. The decision can consider: probability resource is needed probability resource disappears reservation cost impact of delay release cost Again, do not fake precise probabilities if the evidence is weak. Ranges and historical rates are often better. Commitments and Capability Placement Step 34 chose execution placements. Some placements may require commitments: reserve GPU pool allocate browser session reserve region-specific worker acquire licensed specialist capacity Placement therefore should distinguish: eligible placement from: committed placement A candidate placement is not real capacity until the reservation is verified. Commitment-Aware Handoff Step 35 moved running tasks between workers. The handoff checkpoint must include active commitment references. But remember: state transfer ≠ commitment ownership transfer The target worker can learn that C1 exists without owning C1. If ownership must move, perform an explicit transfer. This prevents a checkpoint from silently transferring organizational obligations. Temporal Consistency Applies to Commitments Step 36 introduced freshness. Commitments also become stale. A reservation may expire. A reviewer may withdraw. A maintenance window may move. A resource lock may be revoked. So before relying on an ACTIVE commitment, check whether its evidence is still fresh enough. commitment ledger says ACTIVE ↓ resource is consequential ↓ revalidate external state The ledger is authoritative about the system’s recorded lifecycle. The external system may still require observation for current truth. A Commitment Can Become Invalid Without Being Released Suppose the provider revokes capacity. The system did not release the commitment. But the underlying obligation may no longer be satisfiable. This can transition to: BREACHED or: RECONCILIATION_REQUIRED That difference matters for incident handling. Commitment Compatibility and Behavioral Releases Suppose an agent workflow is upgraded while active commitments exist. Can the new release service the old commitments? This is a compatibility question. A release may need to understand: commitment schema version obligation type release protocol version verifier requirements ownership semantics If not, the old workflow version may need to remain available until obligations are discharged. This connects commitments to Step 24 release compatibility. Never Deploy a Release That Cannot Discharge Existing Obligations This is a useful deployment invariant: new release MUST either 1. service every active commitment type it may inherit, 2. migrate them safely, 3. or leave them with a compatible previous runtime. Otherwise a software rollout can orphan agent obligations even if all normal request handling works. Commitment Schemas Need Versioning As with checkpoints: schema_v1 schema_v2 Migration must preserve semantics. Adding a field is not the only concern. Changing what SATISFIED means is a behavioral compatibility change. That should be reviewed like any other control-plane policy change. Failure Modes Failure 1: Treating Plans as Obligations The agent proposes five alternatives. The platform reserves resources for all five. Result: speculation creates real-world side effects Fix: PROPOSED commitment ≠ ACTIVE commitment Failure 2: Treating Commitments as Plan Nodes A replan deletes the node. The external reservation remains. Fix: commitment ledger + explicit release lifecycle Failure 3: Cancelling Cleanup Work User cancels objective. Scheduler kills every task, including reservation release. Fix: business work cancelled reconciliation work protected Failure 4: Duplicate Commitment Creation A network timeout triggers retry. Both attempts create reservations. Fix: logical commitment ID + idempotency key Failure 5: Stale Human Commitments Reviewer approves an old plan after supersession. Fix: review request bound to intent/artifact identity + expiry Failure 6: Orphaned Ownership Worker dies while holding obligation. No other component knows it exists. Fix: durable commitment owner + reconciliation scan Failure 7: Assuming Release Succeeded Cancel call returns timeout. System marks commitment released. Fix: UNKNOWN / RECONCILIATION_REQUIRED until authoritative confirmation Failure 8: Hidden Natural-Language Commitment Agent tells customer: We'll have this done tomorrow. No structured obligation exists. Fix: commitment-bearing communication requires explicit structured transition Failure 9: Commitment Explosion Every planning branch reserves resources. Fix: delay commitment boundary + commitment-aware admission control Failure 10: Replanning Without Commitment Diff New plan is valid. Old obligations leak. Fix: KEEP / RELEASE / TRANSFER / REVALIDATE / RECONCILE for every active commitment affected by the replan. Failure Injection Do not trust commitment management until it survives deliberate failure. Test scenarios such as: worker crashes after reservation creation but before ledger update ledger updates but external reservation call actually failed release call times out after succeeding remotely intent superseded while commitment creation is in flight human approves after request becomes stale commitment owner disappears transfer target crashes before acknowledgement reservation expires unexpectedly new behavioral release cannot parse old commitment state cancellation event is dropped retry creates duplicate operation attempt The expected outcomes should be explicit. For example: ambiguous reservation creation -> reconcile by idempotency key / external query -> never blindly create another reservation Useful Invariants Some commitment rules should be executable invariants. ACTIVE commitment MUST have a durable owner SATISFIED commitment MUST have satisfaction evidence RELEASED commitment MUST have release evidence stale intent MUST NOT create new dependent commitments commitment transfer MUST invalidate prior servicing authority UNKNOWN external state MUST NOT be represented as RELEASED terminal commitment MUST NOT return to ACTIVE without a new lifecycle event These are excellent candidates for deterministic tests. Benchmark the Simpler Alternatives As always, do not implement the full architecture automatically. Compare: simple task queue vs task queue + durable cancellation vs task queue + explicit commitment ledger vs full goal/commitment/task graph The richer model earns its cost when workflows actually create durable external obligations. A simple read-only research agent may need almost none of this. A deployment, purchasing, operations or customer-facing agent probably needs much more. When You Do Not Need Commitments If your agent: receives request reads immutable data generates answer returns response then a commitment ledger may be overkill. Do not add it because the architecture sounds sophisticated. Add it when the system crosses boundaries such as: reserving resources waiting on humans creating scheduled obligations submitting external jobs making promises acquiring locks initiating multi-stage side effects That is the measured failure boundary. Where This Leaves the Architecture We now have another important separation. Step 37 gave us: intent = what outcome currently matters Step 38 adds: goal = what state should become true plan = one proposed way to get there commitment = an obligation the system has actually created task = executable work servicing goals or commitments action = a concrete execution attempt The hierarchy looks like: Intent │ ├── Goal │ ├── Subgoal │ │ ├── Commitment │ │ │ └── Task │ │ │ └── Action │ │ │ │ │ └── Task │ │ └── Action │ │ │ └── Plan candidates │ └── Intent lifecycle And importantly, plans can disappear while commitments remain visible and accountable. The Larger Principle There is a broader lesson here. Agent systems often blur thought and action. A model says: I'll do X. The system treats that as: X is now part of reality. Production autonomy requires sharper boundaries. The platform should know whether something is: considered proposed committed executing observed verified Those transitions should not happen implicitly inside prose. The core principle remains: A plan is not a commitment, and a commitment is not merely another task in the queue. Once that distinction exists, the next architectural problem becomes unavoidable. Commitments can remain active for hours, days or weeks. Humans may need to respond later. Timers may fire tomorrow. Providers may recover after an outage. A workflow may pause, migrate, retry, wait and resume many times. At that point, the agent is no longer just a loop around an LLM. It needs a durable workflow runtime. That is Step 39.