Inside the Agent Loop: One Bad Retry, Two Refunds
How an AI suggestion becomes a real-world action—and how permission checks, approval gates, and recovery logic keep a helpful agent from making an expensive mistake.
A shopper opens a retailer’s chat window at 8:47 on a Tuesday night. She has a wedding in three days and a dress in her cart. Her question sounds almost too small to warrant a system diagram: Can this arrive by Friday, and is there a less expensive version in blue?
An agentic-commerce assistant might make the exchange feel effortless. It could search the catalogue, inspect real inventory, check delivery promises for her postal code, compare alternatives, and come back with a sensible answer. If she likes one option, it might even prepare the order.
From the outside, this can look like a machine that has simply decided to help. But where, exactly, does the help happen? When does a sentence become a search? When does that search become a charge on someone’s card?
The useful answer is less mystical than the product demo suggests. An AI agent is not a model that has escaped into the world. It is a carefully managed conversation between a model and ordinary software. The model suggests what to do next. The software decides what it is permitted to do, carries out the action, records what happened, and decides whether the work is finished.
That conversation is the agent loop. Once you can see it, the mystery falls away. The real engineering work comes into view.
What happens after the customer presses Enter?
Imagine the retailer’s assistant is called Mira. A customer writes: “Find a blue dress under $180 that can arrive by Friday.” Before Mira answers, the system builds a working packet for the model. It includes the request and the relevant conversation. It may also include customer details, approved tools, discount rules, and the response deadline.
This is called context assembly, though “packing the briefcase” is nearly as accurate. The model cannot know everything in the company. It receives a selected, temporary view of the task.
Why not give it the entire customer record, the entire catalogue, and every tool the company owns? Because more is not always better. A swollen prompt costs more, takes longer, and gives stale or irrelevant information more opportunities to distract the model. It can also turn an old customer comment or a block of imported product copy into an accidental instruction. Good systems separate their permanent rules from untrusted material—customer messages, web pages, retrieval results, and tool output—and include only what is needed now.
Then the model looks at the briefcase and makes a proposal. Perhaps it asks search_catalog for a color, price range, and delivery destination. That proposal is not an action. It resembles a staff member saying: Could someone check this?
This distinction is the center of the whole design. The model does not reach into the retailer’s inventory database. It does not dispatch a package. It emits a structured request; the surrounding application parses it, verifies it, runs approved code, and returns the result. Tool-calling protocols from OpenAI and Anthropic use this same request–execute–observe pattern.
The catalogue tool reports three dresses. A delivery tool says that only one can reach the customer by Friday. The runtime adds that result to the next briefcase, and the model sees a world that is now more specific than it was seconds ago. It can explain the trade-off, look for a cheaper alternative, or offer the available dress. That is the loop:
The repetition is not a flaw. It is how the agent earns new information.
If the model sounds confident, why can’t it be trusted to act?
Because fluent language and permission are different things.
Consider a marketing agent preparing a win-back campaign. It has noticed that customers who bought running shoes six months ago have not returned. The model may propose: “Create an audience of these customers and send a 20-percent-off email.” That may be a smart idea. It still leaves several questions that a clever sentence cannot settle. Is the proposed audience allowed to receive marketing messages? Has each person opted in? Does the promotion violate a price policy? Is the discount within the campaign manager’s authority? Has the same campaign already been sent?
These are not questions for the model to improvise its way through. They belong to deterministic policy code. That code checks the user, consent, spending limits, and authority. The model proposes; the runtime authorizes.
That is why a tool registry is more than a list of convenient functions. Each tool needs a name, input schema, owner, permission level, time limit, retry behavior, and approval rule. A harmless get_campaign_metrics tool may run automatically. A send_campaign tool should be far narrower. It may require an approved audience, a named sender, a preview, and human confirmation. A refund_order tool might require still stricter checks.
Schemas are useful because they force an action request into a known shape. They can establish that an amount is a number and that an order ID is present. But a correctly shaped request can still be a terrible or unauthorized idea. “Refund order 84392 for $500” is valid JSON; it is not necessarily permitted. Validation answers is this well formed? Authorization answers may this person do this now? Approval answers does a responsible human need to see it?
Those layers are the difference between a helpful assistant and an expensive accident. Security guidance makes the point plainly. Tools need least-privilege access and validated inputs. High-risk actions need human review.
When is the work actually done?
The question becomes surprisingly slippery once an agent can act.
Suppose the marketing agent has drafted a campaign and successfully called the email platform. The model produces a polished summary: “Your campaign is scheduled.” Is the job complete? Only if the scheduling tool confirms it. If the platform timed out after receiving the request, the campaign may be scheduled—or it may not. A nice final sentence cannot resolve that ambiguity.
Systems often confuse three different kinds of stopping. A provider may stop because the response ended naturally. It may also stop to request a tool, refuse, or signal an output-token limit. None proves the customer’s task is complete. A token limit means truncation, not success.
At the application level, the completion rule is stricter. A final answer must exist and use the expected format. No tool calls or approvals can be pending. The real-world success condition must also pass. For commerce, that means asking: is the order actually confirmed? For marketing, is the audience final, consent clean, and the campaign in the intended state?
It helps to give every ending a name. A run might be completed, paused_for_approval, needs_user_input, budget_exceeded, blocked, failed, or cancelled. These are not just labels for an operations dashboard. They keep an agent from disappearing behind the vague phrase “it didn’t work.” A representative can see whether an order change needs approval. An engineer can distinguish a policy denial from an outage. The customer gets an honest next step.
What keeps a useful loop from becoming a very fast bad habit?
Picture Mira looking for the blue dress. The inventory service says no result. The model tries a slightly different query. It gets the same no result. It tries again. With enough freedom, a model can persist politely and expensively.
The naïve answer is a maximum number of turns: stop after, say, eight trips around the loop. Every production agent needs such a fuse. But the more revealing question is whether anything is changing. Has the inventory search become more specific? Has the customer supplied new information? Has the number of viable products increased? Or is the system spending tokens, tool calls, and time without moving the task forward?
Good runtimes watch for repeated calls, recurring action-error cycles, and a lack of meaningful progress. They also cap model turns, tool calls, cost, output tokens, timeouts, deadlines, and retries. Each limit catches a different failure. It may expose a stuck integration, runaway budget, truncated response, or model caught in a circle.
Retries need their own judgment. A temporary network problem might deserve a bounded retry with increasing delays and a little randomness. This is the standard backoff-and-jitter approach. An “insufficient inventory” response should not be retried unchanged. Nor should a failed attempt to send a campaign simply be repeated. If a request may have succeeded before a timeout, the system should check its status before acting again. It uses an idempotency key so the downstream system can recognize a duplicate. Otherwise one recovery attempt can become two emails, refunds, or orders.
The loop should not ask the model to be its own judge of whether it is looping. The model is inside the same context that produced the repetition. The controller needs the external evidence: the history, the budget, and the state change.
What does an agent remember when the lights go out?
A demo can keep everything in a short-lived array. Real work has interruptions. A customer may take an hour to approve a substitution. An email platform may be slow. A deployment may restart a service halfway through a refund request.
So the runtime needs durable state: run and tool-call IDs, conversation items, results, approvals, budgets, deadlines, and idempotency keys. It should checkpoint before and after every external operation. After a crash, “we never began” differs greatly from “we may have sent it.” Both differ from “the supplier confirmed it.”
This matters in agentic commerce because actions span systems with different notions of truth. A shopping agent might hold a cart, reserve inventory, authorize payment, and send a confirmation in four separate systems. The agent’s memory is not sentimentality. It is the ledger that makes safe recovery possible.
The same principle applies to approvals. If a campaign manager approves an email to 48,000 customers, that approval should be tied to the exact campaign version, audience, sender, and action. If the model later changes the discount from 15 percent to 25 percent, it should not inherit the old yes. Approval is a pause in a specific run, not a blanket blessing for whatever comes next.
So where does the “agent” live?
Not in one place. It is the collaboration of three parts.
- The model reads the situation and proposes the next move or a final answer.
- The tools read from or change the outside world.
- The runtime loop selects context, enforces policy, runs tools, records observations, protects budgets, preserves state, and decides when to stop.
Frameworks can make this feel seamless, and often they are worth using. But the seam is still there. A framework has not abolished approval logic, failure handling, or state; it has placed them behind an interface. The fastest way to understand an agent is to trace one request across that seam.
Return to the shopper at 8:47. A trustworthy assistant does not merely sound certain that the dress will arrive. It checks. It does not silently replace an unavailable item. It asks. It does not charge a card because a model produced an elegant sentence. It follows a rule, records the decision, and waits for the right confirmation.
That may be less romantic than the idea of autonomous intelligence. It is also why the intelligence can be trusted near a checkout button.
Questions worth asking of any agent
Before calling an agent production-ready, ask a few plain questions:
- What information was placed in the model’s context, and what was deliberately kept out?
- Which actions can the model propose, and which may the runtime actually execute?
- What proof, outside the model’s own text, establishes that the task succeeded?
- Which operations pause for human approval?
- What stops repeated calls, excessive cost, or a hung dependency?
- If the process fails after a side effect, how does it discover what really happened before retrying?
If a team can answer those questions clearly, it has moved beyond the magic-show version of agency. It has built the beginnings of a dependable colleague: one that can search, recommend, draft, and act—while still knowing when to check, when to wait, and when to stop.
Sources
- Function calling | OpenAI API
- How tool use works | Claude Platform Docs
- AI Agent Security Cheat Sheet | OWASP
- Stop reasons and fallback | Claude Platform Docs
- Timeouts, retries, and backoff with jitter | AWS Builders’ Library
- Retry with backoff pattern | AWS Prescriptive Guidance
- Guardrails and human review | OpenAI API
This is Week 5 of a 26-week series on agent systems from first principles: capability maps, skills vs. tools, memory and context, loops, harnesses, and the patterns that separate a demo from production.
Happy learning, happy building.
Tao