The Agent Chose the Right Tool at the Wrong Time
The Agent Chose the Right Tool at the Wrong Time Consider this fictional order-management trace: 10:02:11 Customer asks to change the delivery address 10:02:12 Agent reads order: PAID, version 17 10:02:13 Agent s
The Agent Chose the Right Tool at the Wrong Time
Consider this fictional order-management trace:
10:02:11 Customer asks to change the delivery address
10:02:12 Agent reads order: PAID, version 17
10:02:13 Agent selects update_delivery_address
10:02:15 Warehouse starts packing: PACKING, version 18
10:02:17 Support manager approves the change
10:02:18 Agent updates the address
10:02:20 Shipping label still contains the old address
The model understood the request.
It selected the correct customer, order, and tool. The support manager even approved the action.
The problem appeared in the five seconds between selection and execution. By the time the tool ran, the order had entered a different business state.
This is a time-of-check to time-of-use problem inside an AI workflow.
A Correct Tool Call Can Become Stale
Agent evaluations often test tool selection like this:
User request: Change the delivery address
Expected tool: update_delivery_address
Actual tool: update_delivery_address
Result: PASS
That test proves the model can map an instruction to a function. It says nothing about whether the function remains safe to run later.
Real workflows introduce delays:
- A person must approve the action.
- Another service updates the record.
- A background job changes its status.
- A webhook arrives while the agent is paused.
- The model retries after a timeout.
- A queue resumes the run on another worker.
The selected tool may still be semantically correct while its original assumptions are no longer true.
Give Every Proposed Action a Shelf Life
A tool call that changes business data should carry more than a function name and arguments.
It should also contain the conditions under which the action was proposed:
from dataclasses import dataclass
from datetime import datetime
@dataclass(frozen=True)
class ActionProposal:
tool: str
entity_id: str
expected_version: int
allowed_states: tuple[str, ...]
expires_at: datetime
For the address-change example, the proposal could say:
proposal = ActionProposal(
tool="update_delivery_address",
entity_id="order_4821",
expected_version=17,
allowed_states=("PAID", "QUEUED"),
expires_at=approval_deadline,
)
The agent can recommend the action. The application records the state that made the recommendation valid.
Execution then becomes a separate decision.
Recheck State Inside the Tool Boundary
Do not rely on the model to inspect the order again and decide whether its earlier plan is still safe.
The tool executor should enforce the rule:
from datetime import UTC, datetime
def execute_address_change(proposal, new_address):
order = orders.get_for_update(proposal.entity_id)
if datetime.now(UTC) > proposal.expires_at:
return {"status": "REPLAN", "reason": "proposal_expired"}
if order.version != proposal.expected_version:
return {"status": "REPLAN", "reason": "order_changed"}
if order.status not in proposal.allowed_states:
return {"status": "ESCALATE", "reason": "shipping_started"}
orders.update_address_if_version(
order_id=order.id,
expected_version=proposal.expected_version,
address=new_address,
)
return {"status": "COMPLETED"}
get_for_update() and update_address_if_version() are conceptual repository methods. In a real system, they could use a database transaction, row lock, or compare-and-swap operation.
The important part is where the checks happen: immediately before the write, inside the trusted execution layer.
Approval Does Not Last Forever
Current agent frameworks support pausing a run until a person approves a sensitive tool call. OpenAIβs human-in-the-loop documentation describes serializing a paused run and resuming it after the decision.
That solves one problem: the agent cannot perform the action before approval.
It does not prove that the world remained unchanged while approval was pending.
An approval should therefore apply to a specific proposal, entity version, parameter set, and time window. If any of those change, the previous approval should expire.
A manager approving a $50 refund should not accidentally approve a recalculated $500 refund. Approval for order version 17 should not authorize an operation against version 19.
Test the Delay, Not Only the Prompt
A useful test suite needs to change state between planning and execution.
Test cases should include:
Agent proposes action β entity changes β action is rejected
Agent proposes action β approval expires β workflow replans
Agent proposes action β duplicate callback arrives β one write occurs
Agent proposes action β permission changes β action is denied
Agent proposes action β parameters change β approval is requested again
These tests evaluate the system surrounding the model. They are often more valuable than adding another set of prompt examples.
OWASP describes excessive autonomy as part of its Excessive Agency risk. Its guidance recommends independent authorization and approval for high-impact operations.
Temporal checks add another boundary: authorization must still be valid at the moment of execution.
Log the Decision Boundary
When this failure reaches production, a simple βtool succeededβ log will hide the problem.
Record operational facts such as:
- When the action was proposed
- When approval was granted
- When execution started
- Which entity version was read
- Which version existed at execution
- Which precondition rejected or allowed the write
- Whether the call was new, resumed, or retried
This creates an audit trail without storing private chain-of-thought. Engineers can reconstruct what the system observed and why the executor allowed the action.
The Engineering Question I Would Ask
When evaluating someone for an agent project, I would provide the opening trace and ask:
Where should this workflow recheck state, and what should happen when the state has changed?
A strong answer should cover versioning, transactions, expiring approvals, idempotency, retries, cancellation, and escalation. Framework knowledge matters, but production judgment is revealed at these boundaries.
For teams planning to hire AI engineers, this type of scenario is more informative than asking candidates to build another tool-calling demo. It reflects how Spaculus Software approaches workflow automation: models can propose actions, while the application decides whether those actions are still valid.
The agent chose the correct tool.
The system failed because it treated a correct decision as permanent.
Which state change could make a tool call unsafe in your current workflow?
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.