How to Prevent AI Agent Loops with Pydantic AI UsageLimits and Temporal
AI agents are designed to iterate.
They reason, call a tool, inspect the result, revise their plan, and continue until they have enough information to complete the task.
That loop is what makes an agent useful.
It is also what can make one expensive, slow, and difficult to operate when there is no clear boundary on how long the loop is allowed to continue.
A production AI agent may repeatedly call the same tool, keep asking the model for another turn, grow its context with every iteration, or spend its entire execution budget before a downstream reviewer ever runs.
The solution is not simply telling the model to “stop when you’re done.”
Production agents need programmatic execution limits around model requests, tool calls, retries, and agent handoffs.
Pydantic AI provides UsageLimits for bounding model and tool usage, while Temporal provides a durable execution layer where those limits, failures, and agent transitions can be observed as part of the workflow.
Together, they give engineering teams a practical way to prevent runaway AI agent loops before they become production incidents.
TL;DR: How to Stop Runaway AI Agent Loops
To prevent AI agent loops in production:
- measure how many model turns healthy executions actually require;
- set an explicit request_limit for each agent run;
- use tool_calls_limit to prevent excessive successful tool execution;
- give different agents different execution budgets;
- keep deterministic helpers outside the model’s tool catalog;
- distinguish structural loops from transient failures that should be retried;
- use Temporal Event History to identify repeated model and tool activity;
- fail the current run instead of allowing uncontrolled execution to continue.
The key principle is simple:
The model can decide what to do next, but the execution architecture should decide how much work it is allowed to do.
Why AI Agents Get Stuck in Loops
An AI agent loop is not always an obvious infinite while statement.
Most production loops are subtler.
The agent continues making technically valid decisions, but those decisions stop moving the workflow toward completion.
Consider this sequence:
Model request
↓
Call version-normalization tool
↓
Receive normalized version
↓
Model request
↓
Call the same normalization tool
↓
Receive the same result
↓
Model request
↓
Call the same tool again
Every individual step succeeds.
The workflow does not.
This makes agent loops particularly dangerous operationally because ordinary failure metrics may remain green while the system is wasting model calls and increasing latency.
Common causes of AI agent loops
Several architecture patterns can create this behavior.
Weak stopping conditions
The model knows what actions are available but does not have a reliable condition for producing final structured output.
Too many tools
A large tool catalog gives the model more possible actions at every turn.
Some may not need to be model-controlled at all.
Repeated tool results
If a tool keeps returning information the model already has, the agent may continue reasoning without gaining useful state.
Retry behavior
Tool validation failures or model retries can keep feeding another request back into the agent.
Unbounded review and revision
Worker-reviewer architectures can accidentally create another loop:
Worker → Reviewer → Worker → Reviewer → ...
without a maximum number of revisions.
Framework defaults
Framework safety limits may prevent an agent from running forever, but a framework maximum should not be mistaken for your application’s desired execution budget.
For production systems, the right question is not:
“How many requests does the framework allow?”
It is:
“How many requests should this specific agent need to complete this specific job?”
Use Pydantic AI UsageLimits to Bound Agent Execution
Pydantic AI provides UsageLimits to constrain usage across an individual agent run.
Current controls include limits for model requests, successful tool calls, tokens, per-request input size, and cost. Pydantic specifically documents request_limit as useful for stopping infinite or excessive tool-calling loops.
A basic request limit looks like this:
from pydantic_ai import Agent, UsageLimitExceeded, UsageLimits
agent = Agent("your-model")
try:
result = await agent.run(
prompt,
usage_limits=UsageLimits(
request_limit=15,
),
)
except UsageLimitExceeded:
# Handle the bounded failure intentionally
...
The important part is not the number 15.
The important part is that the number is intentional.
Pydantic AI currently defaults request_limit to 50. That is a framework safeguard, not necessarily a sensible product-level budget for your agent.
If healthy executions normally complete in six or seven model turns, allowing fifty before the system intervenes may mean paying for dozens of unnecessary requests before discovering that the agent is stuck.
Set AI Agent Request Limits from Healthy Runs
There is no universal request_limit that works for every AI agent.
A research agent may legitimately require many turns.
A classifier may need one.
A reviewer may only need two or three.
The best starting point is your own execution history.
Step 1: Measure successful executions
For a representative set of healthy runs, record:
- number of model requests;
- number of tool calls;
- execution duration;
- retries;
- input and output token usage;
- number of worker-reviewer cycles.
Do not start with pathological runs.
First establish what normal looks like.
Step 2: Look at the distribution
Suppose healthy worker executions typically use:
Median: 5 requests
P75: 6 requests
P95: 9 requests
Worst valid: 11 requests
A request_limit of 50 would provide very little protection against a runaway execution.
A lower limit with enough headroom for legitimate variation gives the orchestrator a meaningful boundary.
Step 3: Set limits by agent role
Do not necessarily use one global value.
For example:
WORKER_LIMITS = UsageLimits(
request_limit=15,
tool_calls_limit=20,
)
REVIEWER_LIMITS = UsageLimits(
request_limit=5,
tool_calls_limit=0,
)
The worker is allowed to explore.
The reviewer is not.
That distinction is especially important in multi-agent systems because each agent has a different responsibility.
Use Tool-Call Limits to Stop Agent Thrashing
A request limit controls how many times an agent can go back to the model.
That does not fully solve excessive tool usage.
Pydantic AI also provides tool_calls_limit, which caps the number of successful tool invocations within a run. The limit is checked before tool execution; if parallel tool calls would push the run beyond the configured maximum, those calls are not executed.
For example:
limits = UsageLimits(
request_limit=15,
tool_calls_limit=20,
)
result = await agent.run(
prompt,
usage_limits=limits,
)
Why use both?
Because they protect against different problems.
| Limit | Protects against |
| request_limit | Excessive model turns and runaway reasoning |
| tool_calls_limit | Excessive successful tool execution |
| Token limits | Growing prompt/output consumption |
| cost_limit | Unexpected model spend |
| Per-request input limit | Oversized individual context windows |
Pydantic AI now also supports a cost_limit, although its documentation recommends combining it with controls such as request_limit rather than treating it as a hard billing guarantee.
For many agent systems, request and tool-call limits are the more important architectural controls because they address the behavior causing the waste.
Why Temporal Matters When an Agent Exceeds Its Limit
Usage limits answer:
How much work can this agent do?
Temporal answers another question:
What should happen when that boundary is reached?
Pydantic AI supports Temporal as a durable execution backend. In the current integration, TemporalDurability routes model requests, I/O tool calls, and MCP communication through Temporal Activities while coordination logic executes inside the Workflow.
That creates a useful separation.
Temporal Workflow
│
├── Worker agent
│ ├── model request
│ ├── tool call
│ ├── model request
│ └── ...
│
├── Reviewer
│
├── Optional revision
│
└── Complete
The AI agent is still allowed to reason dynamically.
But execution policy lives outside that reasoning.
If the agent reaches its usage limit, the system can stop the run before scheduling another expensive step and handle that condition deliberately.
That is safer than allowing the model to own its own stopping behavior.
Moving AI agents from prototype to production?
Agent loops are only one production failure mode. Retries, tool side effects, state recovery, worker failures, observability, and versioning can create equally difficult problems once real traffic arrives.
Use Xgrid’s Temporal Production Deployment Checklist to review the architecture, reliability, observability, scaling, retry, and operational controls that should be validated before production workloads grow.
Do Not Treat Every Agent Failure as Retryable
One of the easiest ways to turn a bounded failure into an unbounded system is to retry it automatically.
Suppose an external API returns a temporary 503.
Retrying makes sense.
Now suppose the agent reaches its model-request limit because it has called the same tool repeatedly and failed to produce an answer.
Restarting the exact same agent run may simply generate the same expensive sequence again.
These are different classes of failure.
Transient failure
Examples:
- temporary network timeout;
- provider rate limiting;
- unavailable downstream API;
- short-lived infrastructure problem.
These may be appropriate for retry.
Structural failure
Examples:
- request budget exceeded;
- revision limit reached;
- repeated deterministic tool call;
- invalid execution path;
- agent cannot reach structured output.
Retrying without changing anything is unlikely to help.
This distinction matters particularly with Temporal because Activities support configurable retry behavior.
A good production architecture should deliberately classify failures rather than assuming that all exceptions should receive another attempt.
Reduce AI Agent Loops by Fixing Tool Design
Usage limits protect the system when an agent behaves badly.
Good tool design reduces the likelihood of bad behavior occurring in the first place.
One particularly important question is:
Should this function be an AI agent tool at all?
Consider a function that:
- strips a prefix from a string;
- reformats a date;
- normalizes a version;
- performs a deterministic calculation;
- validates an already structured value.
These operations do not usually require model reasoning.
If they are exposed as tools, however, the model must now decide whether and when to invoke them.
That creates another possible branch in the agent loop.
A useful design rule is:
Keep deterministic transformation in code. Expose tools when the agent actually needs to interact with external state, retrieve information, create side effects, or make a decision that benefits from an auditable boundary.
Good agent-tool candidates
Examples include:
- searching a knowledge source;
- querying a database;
- retrieving current external information;
- creating a ticket;
- sending a message;
- changing infrastructure;
- requesting human approval.
Poor agent-tool candidates
Often:
- trimming strings;
- normalizing values;
- simple arithmetic;
- deterministic formatting;
- basic schema conversion;
- predictable validation.
A smaller tool catalog reduces the number of choices presented to the model and makes pathological tool patterns easier to identify.
Detect AI Agent Loops with Temporal Event History
Limits prevent a loop from continuing indefinitely.
They do not explain why it happened.
For that, teams need execution-level observability.
When model requests and tool calls execute through Temporal Activities, the Workflow’s Event History can expose the order and duration of the steps that occurred.
That can turn:
“The agent was slow.”
into:
“The worker made 28 model requests, invoked the same tool 19 times, never reached the reviewer, and exceeded its request budget.”
That is a much more useful debugging statement.
Signals to inspect in a suspected agent loop
Number of model requests
Compare the execution with successful runs.
A significant increase is one of the clearest loop indicators.
Repeated tools
Look for one tool appearing disproportionately often.
Identical arguments
The same (tool, arguments) pair occurring repeatedly may indicate that the agent is not gaining new information.
Reviewer execution
In a multi-agent workflow, verify whether downstream stages actually started.
If the worker consumed the full budget first, the nominal multi-agent architecture never truly executed.
Activity duration
Determine whether wall-clock time was spent in:
- model requests;
- external tools;
- Temporal task queues;
- database/API activity;
- retry delays.
Temporal observability is particularly valuable here because a healthy Temporal service does not necessarily mean the business workflow is healthy. Xgrid’s production observability guidance similarly recommends combining workflow-level signals with Event History and domain-specific execution context rather than relying only on platform health.
Prevent Multi-Agent Loops with Separate Budgets
Multi-agent systems make execution limits even more important.
Consider this architecture:
Orchestrator
↓
Worker
↓
Reviewer
↓
Worker revision
↓
Reviewer
Without explicit boundaries, there are at least two possible loops.
Loop 1: Inside the worker
model → tool → model → tool → model...
Loop 2: Between agents
worker → reviewer → worker → reviewer...
Solving only one leaves the other open.
A production design should therefore define budgets at multiple levels.
Per-run worker budget
How many model and tool calls may one worker execution use?
Reviewer budget
How much reasoning should the reviewer be allowed?
Revision budget
How many times may the reviewer return work to the worker?
Overall workflow budget
At what point should the orchestrator stop attempting improvement and return a bounded failure or degraded result?
Pydantic AI’s documentation also notes that usage can be accumulated across delegated multi-agent runs and that UsageLimits can help avoid unexpected cost and runaway tool loops.
The orchestration layer should own these policies.
Otherwise, each agent may individually behave within its own rules while the system as a whole still loops.
A Production Pattern for Pydantic AI and Temporal
For teams using Pydantic AI with Temporal, a practical architecture looks something like this:
Temporal Workflow
│
├── Load durable state
│
├── Worker agent
│ ├── explicit request limit
│ ├── explicit tool-call limit
│ └── structured output
│
├── Reviewer
│ ├── smaller request limit
│ └── no tools unless necessary
│
├── Revision?
│ ├── yes → bounded additional worker run
│ └── no → continue
│
└── Complete
The model still owns reasoning.
Pydantic AI owns the agent runtime and usage enforcement.
Temporal owns durable orchestration and execution recovery.
Your application owns policy.
That last distinction is important.
No framework can know:
- how much one recommendation is worth;
- how many model turns are acceptable;
- whether a reviewer is mandatory;
- which tools deserve another attempt;
- when degraded output is preferable to another expensive loop.
Those are product and architecture decisions.
They should be encoded intentionally.
AI Agent Loop Prevention Checklist
Before shipping an autonomous or multi-agent workflow, check the following.
Agent execution
- Do you know the normal number of model requests for successful runs?
- Is request_limit explicitly configured?
- Is the limit different for workers, reviewers, and specialized agents?
- Does each revision path have a maximum number of iterations?
Tool usage
- Is tool_calls_limit configured where appropriate?
- Are deterministic helper functions kept out of the agent tool surface?
- Can you detect repeated tool calls with identical arguments?
- Are side-effecting tools designed to tolerate retries safely?
Failure handling
- Are usage-limit failures treated differently from transient infrastructure failures?
- Could a Temporal retry restart an agent that is structurally stuck?
- Is there a clear terminal failure state when a budget is exceeded?
Observability
- Can you count model requests for a single workflow?
- Can you inspect tool-call order?
- Can you see whether downstream agents ran?
- Can you compare pathological Event History with a healthy run?
Cost control
- Can you attribute model usage to an individual workflow?
- Do you know how much an unsuccessful run consumes?
- Do you alert on abnormal model-turn or tool-call counts?
- Are long-tail executions monitored separately from averages?
If several answers are no, prompt engineering is unlikely to be enough.
The execution architecture needs stronger boundaries.
Usage Limits Are Guardrails, Not the Root-Cause Fix
There is an important distinction between stopping an agent loop and fixing why the agent loops.
A request limit may stop a worker after 15 turns instead of 50.
That is valuable.
But if healthy executions only need six turns, the next question should still be:
Why did this run need fifteen?
The answer may be:
- a bad tool boundary;
- ambiguous instructions;
- repeated external results;
- growing context;
- poorly designed reviewer feedback;
- an unexpected model behavior;
- a missing completion condition.
Usage limits create a safe boundary while engineers investigate those issues.
Temporal then provides an execution history that can help reconstruct what happened before the boundary was reached.
That combination is more useful than either mechanism alone:
Limits contain the failure.
History explains the failure.
Architecture prevents it from recurring.
Building AI Agents That Fail Predictably
A production-grade AI agent does not need to succeed every time.
It needs to fail in a way the surrounding system can understand.
“Agent exceeded the worker request budget” is actionable.
“Agent ran for four minutes and eventually timed out” is much less so.
Predictable failure boundaries help engineering teams:
- control model spend;
- preserve downstream quality checks;
- protect external tools;
- reduce latency outliers;
- debug unexpected behavior;
- and make autonomous systems safer to operate.
This is one of the reasons Temporal is a strong fit for production AI agents.
Durable execution is not about giving the model more autonomy.
It is about putting reliable infrastructure around that autonomy.
If your team is already using Temporal for agentic workflows and is seeing repeated tool calls, runaway model turns, difficult-to-debug executions, or reviewer loops, Xgrid can review the workflow with your engineering team and identify where agent boundaries, retry behavior, tooling, and production observability need to be tightened.
Request a Temporal Workflow Review.
Frequently Asked Questions About AI Agent Loops
What is an AI agent loop?
An AI agent loop occurs when an agent continues making model requests or executing actions without making meaningful progress toward completion. It may repeatedly call the same tool, revise the same plan, retry invalid outputs, or continue reasoning until an external limit or timeout stops it.
How do I prevent an AI agent from looping?
Use multiple layers of control: explicit stopping conditions, model-request limits, tool-call limits, bounded retries, restricted revision cycles, and a carefully designed tool catalog. Production systems should enforce these controls in code rather than relying only on prompt instructions.
What is Pydantic AI request_limit?
request_limit is part of Pydantic AI’s UsageLimits. It caps the number of requests that can be made to the model during an agent run. Pydantic AI checks the limit before scheduling another model request, making it useful for preventing runaway model-turn loops.
What is the default Pydantic AI request limit?
Pydantic AI currently defines a default request_limit of 50. Production applications should evaluate whether that default matches their own healthy execution patterns rather than treating it as an application-specific SLA.
How does Temporal help prevent AI agent loops?
Temporal does not decide when an AI agent has reasoned enough. Instead, it provides the durable orchestration layer around the agent. Model requests and external tool calls can execute as Activities, while the Workflow controls execution flow, retries, agent transitions, and failure handling. Event History also makes abnormal execution patterns easier to inspect.
Can Pydantic AI and Temporal be used together?
Yes. Pydantic AI provides native durable-execution support for Temporal. For current implementations, Pydantic recommends attaching the TemporalDurability capability to an agent and executing the run inside a Temporal Workflow. Model requests and I/O-based tools can then be routed through Temporal Activities.

