How to Fix 'agent infinite loop in production' in LlamaIndex (TypeScript)

By Cyprian AaronsUpdated 2026-04-21
agent-infinite-loop-in-productionllamaindextypescript

When you see agent infinite loop in production in a LlamaIndex TypeScript app, it usually means the agent keeps calling tools or re-entering the same reasoning path without ever reaching a final answer. In practice, this shows up when your tool outputs don’t let the agent make progress, or when the agent is allowed to call itself forever.

This is common in production because real data is messy. A tool returns an empty result, a parser fails, or the agent gets a response that looks valid but doesn’t satisfy its stop condition.

The Most Common Cause

The #1 cause is a tool loop: the agent calls a tool, gets output that still looks like a task for the same agent, then calls another tool with the same intent. In LlamaIndex TS, this often happens with OpenAIAgent or ReActAgent when your tools return ambiguous text instead of structured completion signals.

Here’s the broken pattern:

import { OpenAIAgent } from "llamaindex";

const agent = new OpenAIAgent({
  tools: [
    {
      name: "lookupCustomer",
      description: "Find customer by email",
      call: async ({ email }) => {
        // BAD: returns text that encourages another lookup
        return `Customer not found for ${email}. Try searching again.`;
      },
    },
  ],
});

const response = await agent.chat("Find john@acme.com and summarize his policy status");
console.log(response.toString());

And here’s the fixed version:

import { OpenAIAgent } from "llamaindex";

const agent = new OpenAIAgent({
  tools: [
    {
      name: "lookupCustomer",
      description: "Find customer by email",
      call: async ({ email }) => {
        const customer = await db.customers.findByEmail(email);

        if (!customer) {
          // GOOD: explicit terminal state
          return JSON.stringify({
            found: false,
            reason: "customer_not_found",
            email,
          });
        }

        return JSON.stringify({
          found: true,
          customerId: customer.id,
          policyCount: customer.policyCount,
        });
      },
    },
  ],
});

const response = await agent.chat("Find john@acme.com and summarize his policy status");
console.log(response.toString());

The difference is simple:

BrokenFixed
Returns natural language that suggests retryingReturns structured terminal output
No clear stop conditionExplicit found: false / found: true
Agent keeps reasoning about the same missing entityAgent can conclude and answer

If you’re using ReActAgent, the same issue appears as repeated tool calls with no final answer, often visible in logs as repeated Thought -> Action -> Observation cycles.

Other Possible Causes

1) Tool output is too large or noisy

If your tool returns huge documents, the model may keep re-reading and re-asking instead of finishing.

// BAD
return JSON.stringify({ rows }); // thousands of rows

// GOOD
return JSON.stringify({
  rowCount: rows.length,
  topResults: rows.slice(0, 5),
  truncated: rows.length > 5,
});

Keep tool responses small and deterministic.

2) The agent has overlapping tools with similar names

Two tools that both sound like “search” can cause repeated selection and no progress.

// BAD
tools: [
  { name: "search", description: "Search records", call: searchA },
  { name: "searchData", description: "Search records", call: searchB },
]

// GOOD
tools: [
  { name: "customerLookupByEmail", description: "Lookup one customer by email", call: searchA },
  { name: "policySearchById", description: "Lookup one policy by ID", call: searchB },
]

Make tool names precise and non-overlapping.

3) Missing max iterations / step limit

If your agent config doesn’t cap reasoning steps, a bad prompt or bad tool output can spin forever.

const agent = new OpenAIAgent({
  tools,
  maxIterations: 5,
});

If your version exposes a similar setting on ReActAgent, set it there too. Production agents need hard limits.

4) Your prompt asks for impossible completeness

A prompt like “keep searching until you are certain” can push the model into endless verification.

// BAD
const prompt = "Keep checking until you're fully certain there are no other policies.";

// GOOD
const prompt =
  "Use at most one lookup tool call per identifier. If no record is found, return not_found and stop.";

The model needs an exit rule. Write it into the prompt.

How to Debug It

  1. Turn on verbose tracing

    • Log every tool call input/output.
    • Look for repeated identical arguments.
    • In LlamaIndex TS, inspect whether you’re seeing repeated Action/Observation cycles with no final response.
  2. Check for identical repeated tool inputs

    • If the agent keeps calling lookupCustomer({ email }) with the same value, your output is not giving it a terminal state.
    • Fix by returning structured results like { found:false }.
  3. Reduce to one tool

    • Remove all but one tool.
    • If the loop disappears, you likely have overlapping tools or ambiguous routing.
    • Add them back one at a time.
  4. Force a hard stop

    • Set maxIterations to something small like 3 or 5.
    • If you now get an error such as Agent reached maximum iterations without producing a final answer, you’ve confirmed a reasoning loop instead of an infrastructure issue.

Prevention

  • Return structured outputs from tools:
    • Use JSON objects with explicit states like found, not_found, truncated, error.
  • Keep prompts operational:
    • Tell the agent when to stop and what counts as completion.
  • Add iteration caps everywhere:
    • Don’t ship an uncapped production agent.
  • Write tests for loop behavior:
    • Mock empty results, partial matches, and malformed outputs.
    • Assert that the agent stops after one or two turns instead of retrying forever.

If you want a quick rule of thumb, use this:

  • Bad: “Try again until you figure it out.”
  • Good: “Call once, return structured result, stop on not_found.”

That’s usually enough to eliminate most agent infinite loop in production cases in LlamaIndex TypeScript.


Keep learning

By Cyprian Aarons, AI Consultant at Topiax.

Want the complete 8-step roadmap?

Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.

Get the Starter Kit

Related Guides