Skip to content

Agentic AI & Orchestration

Make Your AI Agent Recheck a Price After Approval

A sandbox purchasing agent submitted an approved order from stale data. Binding approval to a source snapshot made the same agent stop when the catalog price changed.

Mara QuinteroAgents & Orchestration Writer

October 10, 2026 · 8 min read

A laptop showing an approval diff beside a vendor catalog record for a USB-C dock order.
A laptop showing an approval diff beside a vendor catalog record for a USB-C dock order.

I tested this with a sandbox purchasing workflow for a batch of USB-C docks. The agent read a vendor catalog record, prepared a purchase order, and paused for human approval. After approval, I changed the catalog price before allowing the run to continue.

The first implementation submitted the order using arguments saved during planning. Approval covered a price that no longer existed, but the execution step never checked. The agent had a valid approval flag and stale data, which was enough to call the purchasing tool.

A guarded version behaved differently. It fetched the catalog record again, compared selected fields with the state attached to the approval, and moved the order back to `AWAITING_APPROVAL` when the price no longer matched. No purchase call was made.

That distinction belongs in orchestration code, not in a prompt asking the model to be cautious.

The failure happens between approval and action

The dock order exposed a time-of-check to time-of-use problem, often shortened to TOCTOU: the system checked a condition at one moment, then relied on that result when acting later. This problem predates AI agents, but long-running agent workflows create more opportunities for it because they pause for people, retries, scheduled jobs, and external tools.

In the baseline run, the plan stored the catalog result alongside the proposed tool call. The approval service recorded that a person had accepted the plan. When execution resumed, the orchestrator treated approval as permission to use those saved arguments, even though the vendor catalog was the authority for the current price.

Re-reading the conversation would not have helped. The conversation contained the old value. Replanning from the same cached tool result would also have reproduced the old order, while a general instruction such as “confirm details before purchasing” left the model to decide whether another lookup was necessary.

The safer rule is mechanical: an approval authorizes an action against a defined state, not against a loosely described intention.

Bind the approval to the state that was reviewed

For the dock order, I created an approval record that retained both the source identity and the fields that affected the decision. The record looked like this in simplified form:

```json { "source": { "type": "vendor_catalog", "record_id": "dock SKU", "revision": "revision captured during planning" }, "approved_fields": { "unit_price": "price shown to reviewer", "currency": "currency shown to reviewer", "availability": "status shown to reviewer" }, "critical_hash": "SHA-256 of canonical approved_fields", "decision": "approved" } ```

The critical hash is a fingerprint of consistently serialized data. It makes comparison cheap, but it should not replace the retained fields, because a reviewer needs a readable diff when the fingerprint changes. Canonical serialization also matters: field order, decimal formatting, and null values must produce the same bytes when the underlying state is the same.

Choosing protected fields is a policy decision. In this test, price, currency, and availability could change whether the order should proceed, while a corrected product description did not alter the approval. Hashing the entire catalog response would catch more changes but would also cancel approvals for irrelevant edits, creating enough noise that operators may start approving diffs without reading them.

A database revision number can supplement this snapshot, though it does not explain what changed. For a document workflow, the equivalent may be an immutable file version or content hash. The essential point remains narrow: the approval record must identify the source state the person saw.

An expiration time is useful, but it solves a different problem. A short-lived approval can limit how long authorization remains usable; it cannot detect a price changed seconds after approval.

Put the guard at the execution boundary

The recheck should run after approval and immediately before the irreversible tool call. I placed it in the purchasing tool adapter, the code that validates and translates an agent request before it reaches the external purchasing system, rather than in the agent’s planning loop.

That placement matters. A model can omit a planned verification step, and a resumed workflow may skip planning entirely, but every purchase still has to cross the adapter. The guard therefore applies to normal runs, retries, and manually resumed jobs.

The control path was short:

```python fresh = catalog.read(record_id, bypass_cache=True) fresh_fields = select_critical_fields(fresh)

if digest(fresh_fields) != approval.critical_hash: diff = compare(approval.approved_fields, fresh_fields) workflow.

transition("AWAITING_APPROVAL") approvals.

purchasing.submit( order, expected_revision=fresh.revision, idempotency_key=workflow.id ) ```

The fresh read must come from the authoritative source, not from the model’s context window or the cache used during planning. If the catalog client cannot bypass a cache, its freshness and consistency guarantees become part of the risk decision; labeling a second cached response as a recheck does not make it current.

The diff shown for the dock order included the previously approved price and the current price. The new approval then bound itself to the new snapshot. Reusing the old approval while updating the order arguments would defeat the control.

I kept the comparison deterministic. A language model was not asked whether the change was “material,” because exact fields such as prices and currencies can be compared by ordinary code, without another model call or a judgment that may vary between runs.

Run the mutation after approval, not before it

A useful evaluation has to alter the source during the pause. If the catalog changes before planning, the agent may read the new value and appear safe even though it has no execution-time guard.

I ran the dock workflow until the approval service recorded its decision, then changed the underlying catalog fixture and resumed the same workflow instance. The unguarded path reached the submit function with the saved price. The guarded path performed another catalog read, generated a field-level diff, and stopped before submission.

The surrounding tests matter as much as that central mutation. An unchanged record should pass without another human decision. A change to an unprotected description should follow the policy chosen for irrelevant edits. A price change should block, while a failed or unauthorized catalog read should fail closed, meaning the system refuses to purchase when it cannot establish the precondition.

I also tested the retry path conceptually at the tool boundary: once a purchase has succeeded, a network timeout must not cause the orchestrator to create a second order. The idempotency key, a stable identifier that lets the receiving system recognize repeated requests, addresses duplication; it does not replace the state comparison.

Keep the evidence in the run log. For the dock order, that meant recording the approval identifier, approved hash, fresh hash, changed fields, source revision, and the fact that submission was skipped. Avoid dumping an entire catalog or document into logs when the protected values and identifiers provide enough evidence, especially if the source contains personal or confidential data.

Close the smaller race after the re-read

A precondition check narrows the unsafe window but does not eliminate it. The catalog can change after the fresh read and before the purchasing system commits the order.

The best fix is a conditional write, which tells the destination to execute only if a version or quoted value still matches. In the dock harness, the submit call carried the expected catalog revision. A production purchasing API might instead accept a quote identifier, a maximum authorized total, or a prepare-and-commit flow that returns final terms before the commit.

If the destination accepts only an unconditional “buy” request, the agent cannot guarantee that the checked price is the charged price. A local lock does not protect against changes inside an external vendor system, and another model check adds no protection. For a consequential purchase, that limitation should keep the final submission manual.

This is also why the guard belongs close to the side effect. Putting it several agent steps earlier leaves room for tool calls, queues, and approval delays to reopen the same race.

The cost is one read, plus human delay when it matters

The normal path adds an authoritative source read and a deterministic comparison. It does not require another model invocation, although the source system’s latency and per-call fees still apply. The changed path costs more because work stops until someone approves the new state.

That delay is intentional. Teams can reduce unnecessary interruptions by protecting only decision-relevant fields and by presenting a compact diff, but automatic tolerance rules need their own explicit authorization. A policy allowing movement within a defined ceiling should be recorded as part of the approval, not inferred later by the agent.

For low-consequence, reversible actions, this machinery may not be worth the integration work. For an external purchase, record update, payment, or publication that cannot be cleanly undone, an approval flag without a bound snapshot is incomplete.

Questions people ask

What changes should cancel an AI agent’s approval?

Protect fields that could change the reviewer’s decision or the effect of the action. In the dock order, those were price, currency, and availability. Avoid hashing every response field by default, because harmless metadata edits can create repeated approval requests and train people to ignore the diff.

Is re-reading the source enough to prevent a stale action?

No. Another change can occur between the re-read and the write. Use a conditional write, quote identifier, expected revision, or final confirmation step at the destination when available. Without destination support, the recheck reduces the window but cannot guarantee that execution uses the reviewed state.

Should the language model decide whether a change matters?

Use deterministic comparisons for structured values such as prices, account identifiers, dates, and status fields. A model may help summarize a document diff for a reviewer, but it should not silently waive a failed precondition. The orchestration policy should decide which fields require renewed approval.

What should the agent do if it cannot re-read the source?

Fail closed for consequential actions. Record the lookup error, keep the approval evidence, and move the workflow to a blocked state rather than using the cached value. In the dock workflow, that means leaving the order in `AWAITING_APPROVAL` or a separate error state and never calling the purchase function.

ShareFacebook
ai agentsworkflow automationtool use and function callingai agentsapproval workflowsprecondition checksworkflow safety

One story a day

The story of the day, in your inbox

One real story about AI each morning — no hype, no alarm, just company for the road.

Read next

A laptop showing a citation ledger with one claim marked partially supported beside its quoted source passage.

Agentic AI & Orchestration

A Second Pass Can Catch AI Citations That Do Not Fit

A research agent can check whether a cited passage supports its claim, but only after claims are split into testable units. The extra pass catches mismatches, not bad sources or missing evidence.

Mara Quintero · 7 min read

Account settings page with an address modal partly covered by a cookie banner in a desktop browser.

Agentic AI & Orchestration

Visual AI Agents Still Lose the Checkout Button

A moved control is the easy case. Modal windows, sticky banners, and responsive layouts show why visual browser agents need bounded tasks, state checks, and a selector-based fallback.

Mara Quintero · 8 min read