Troubleshooting AI Agents: Why They Break and How to Fix Them
I still remember the first time I left an AI agent running overnight. It was a simple Python script using the early GPT-4 API, designed to scrape tech news and summarize it into a newsletter. I thought I was being clever. I woke up the next morning not to a perfectly formatted newsletter, but to a depleted OpenAI credit balance—about $120 gone in eight hours—and a log file filled with 4,000 repetitions of the agent trying to click a "Accept Cookies" button that didn't exist in the DOM. That was my expensive introduction to the reality of agentic workflows: they are incredibly powerful, but they are also chaotic, non-deterministic toddlers that will burn your house down if you don't watch them.
If you're reading this, you've probably hit that wall where your agent works perfectly for three runs and then completely implodes on the fourth. Maybe it's caught in a reasoning loop, or perhaps it's hallucinating arguments for function calls. Debugging this stuff is fundamentally different from traditional software engineering. In standard code, if `a + b = c`, it always equals `c`. With LLM agents, `a + b` might equal `c` today, but tomorrow it might equal a poem about daffodils or a JSON formatting error.
The "While True" Loop of Death
So, let's talk about the most common issue I see when auditing client codebases: the infinite loop. This usually happens when the agent's reasoning capabilities fail to register that a task is complete, or when an error message from a tool feeds back into the prompt, causing the agent to retry the exact same failing action endlessly.
I worked on a customer support bot recently that was supposed to look up an order status. The API returned a 404 because the order ID was wrong. The agent, being "helpful," decided to retry. And retry. And retry. It didn't have a stopping condition for that specific error type.
You can't rely on the LLM to say "I give up." You have to force it. I now hard-code a `max_iterations` limit on every single agent loop I build. For most tasks, if an agent hasn't solved the problem in 10 steps, it's not going to solve it in 100. In LangChain (specifically looking at versions 0.1.0 and later), you can set early stopping criteria. But honestly, I prefer handling this at the control flow level. If the tool output is identical three times in a row, kill the process and raise a flag. It sounds primitive, but it saves your API budget.
Tool Use and Argument Hallucinations
This drove me crazy until I started using Pydantic for everything. Here is the scenario: You give your agent a tool called `search_database(query, date_range)`. The agent decides to call it, but instead of passing a date range string like "2023-01-01", it passes a relative term like "last week" or, worse, completely invents a parameter like `sort_by="relevance"` which your Python function doesn't accept.
The LLM doesn't know your code. It only knows the schema you provide. If that schema is vague, the model will fill in the gaps with its training data, which often includes parameters from other popular APIs that have nothing to do with yours. I've learned that you need to be aggressively specific in your tool descriptions. Don't just say "Get data." Say "Get data. The date_range argument MUST be in YYYY-MM-DD format. No other format is accepted."
Even then, it fails. My go-to fix now is using a validation layer—something like the `instructor` library or just raw Pydantic validators—before the function actually executes. If the agent hallucinates a bad argument, I catch the validation error, and—this is the important part—I feed that error message back to the agent as an observation. "Error: sort_by is not a valid argument." The agent usually looks at that, goes "Oops," and corrects itself in the next step. If you just crash the program, the agent learns nothing.
Observability: Stop Using Print Statements
When I started, I debugged by printing the prompt and completion to the console. That works for a single call. It does not work when you have an agent executing a chain of thought with five distinct steps, three tool calls, and a RAG lookup. You end up with a wall of text that is impossible to parse.
You need a tracing tool. I've been using LangSmith extensively lately, though Arize Phoenix is also solid if you want something open-source and local. Seeing the exact "Chain of Thought" (CoT) is the only way to understand why the agent did something stupid.
For example, I was debugging a coding agent that kept deleting the wrong files. When I looked at the trace, I saw that in the "Thought" step, it correctly identified the file to keep, but in the "Action" step, it swapped the filenames because the context window was getting truncated. I wouldn't have caught that with `print(response)`. The trace showed me exactly where the context limit cut off the instruction. If you aren't using a tracing tool, you are flying blind.
The JSON Formatting Struggle
If you've worked with agents, you've seen the dreaded `json.decoder.JSONDecodeError`. You ask the model for JSON, and it gives you JSON wrapped in markdown backticks, or it adds a trailing comma that breaks the parser.
I used to write complex regex patterns to clean up the output. That's a losing battle. The better approach is to use models that support "JSON mode" natively (like GPT-4o or Claude 3.5 Sonnet), but even those aren't bulletproof.
The real lesson here is resilience. When the parsing fails, don't crash. Send a system message back to the model: "Your last response was not valid JSON. Please correct it." I'd say this fixes the issue about 90% of the time. For the other 10%, I use a library called `json_repair` which is surprisingly good at fixing those trailing commas and missing brackets that LLMs love to leave behind.
Context Window Management and "Lost in the Middle"
Here is a thing people forget: just because a model has a 128k context window doesn't mean it pays attention to all of it. There's a phenomenon researchers call "Lost in the Middle." If you stuff 50 documents into the context for your agent to read, it will likely remember the first few and the last few, but hallucinate details about the ones in the middle.
I ran into this building a legal analysis agent. We were dumping entire case files into the prompt. The agent started making up laws. The fix wasn't a better model; it was better architecture. We switched to a RAG (Retrieval-Augmented Generation) approach where the agent queries a vector database for specific chunks of text rather than reading the whole document at once.
It feels counter-intuitive to give the agent less information, but by forcing it to retrieve only what is relevant, you reduce noise. A confused agent is a hallucinating agent. Keep the context clean. I try to keep the system prompt under 1,000 tokens and dynamically load the rest.
Two Hard Lessons I Learned the Hard Way
1. Never deploy without a budget cap.
I mentioned the $120 mistake earlier. That was cheap compared to what could have happened. Now, I use a proxy middleware (Helicone is great for this) that sits between my code and OpenAI/Anthropic. I set a hard daily limit of $10 for development environments. If the agent goes rogue and enters a loop, the proxy cuts it off. Do not trust your code to stop the loop; the network layer must be your safety net.
2. Latency kills user trust.
I built a super-smart agent that used GPT-4 for every single step. It was brilliant. It was also incredibly slow. It took 45 seconds to answer a simple question because it was "thinking" too much. Users hated it. I learned that you don't need the smartest model for every step. I now use a "router" architecture. I use a smaller, faster model (like GPT-4o-mini or Haiku) for the initial routing decision, and only call the heavy hitters for complex reasoning tasks. It cut latency by 60% and costs by 80%.
FAQ: Troubleshooting Common Agent Issues
Why does my agent keep repeating the same action?
This is usually a "context saturation" issue. The agent's context window is full of the same error message repeating, so the model thinks repeating the action is the correct pattern to follow. You need to truncate the conversation history. If the agent loops more than 3 times, clear the last few messages or summarize the history to "reset" its train of thought.
How do I stop the agent from hallucinating URLs?
Agents love to invent URLs that look real but return 404s. The only fix is to give the agent a tool to search for URLs (like a Google Search API or Tavily) rather than asking it to recall them. LLMs are prediction engines, not databases. If you ask for a link to a specific article, it will predict what that link should look like, not what it actually is.
Is it better to use one big agent or multiple small ones?
Multi-agent systems are generally more stable. Instead of one "God Agent" that tries to do research, coding, and writing, break it down. Have a "Researcher" agent that just finds data and passes it to a "Writer" agent. This is often called the Supervisor pattern. It makes debugging easier because if the output is bad, you know exactly which sub-agent failed.
Why does the agent ignore my system instructions?
This often happens because the system prompt is too long or conflicting. LLMs suffer from "recency bias." They pay more attention to the user's last message than the system prompt at the start. A trick I use is to append a condensed version of the most critical rules to the very end of the prompt, right before the agent generates a response. It reminds the model of the constraints right at the moment of inference.
My Take on the Future of Debugging Agents
Look, debugging AI agents right now feels a lot like web development did in the late 90s. The tools are rough, the standards are changing every week, and half the time you're just guessing why things broke. But it is getting better.
I think we're moving away from prompt engineering and toward "flow engineering." The prompt matters less than the architecture—the loops, the checks, the validation layers. If you're struggling, stop trying to talk the model into being smarter. Instead, build a better cage for it. Restrict its actions, validate its outputs, and treat it like an intern who tries hard but needs constant supervision. That's the only way to build agents that actually work in production.
.png)