Recommended resources
The freely available resources this lesson will direct you to.
Hello! Welcome to the next lesson in our journey to build capable AI agents.
In our last session, we built a multi-step tool chain, enabling our agent to tackle complex queries by sequencing tool calls. We focused on the "happy path," where every tool works perfectly, and every LLM output is exactly as expected. But as any experienced software engineer knows, the real world is rarely that clean.
Today, we'll address the "unhappy path." What happens when a tool fails because an external API is down? What if the LLM hallucinates non-existent arguments for a function call? Our goal is to make our agent resilient to these inevitable issues.
This lesson directly addresses the learning outcome: Implement error handling and validation for tool call results. You'll find that many of the principles here are direct applications of robust software engineering practices you already use, adapted for the unique challenges of working with probabilistic LLMs.
Why Error Handling is Crucial for Agents
LLM-based agents are inherently non-deterministic. Unlike a traditional program that produces the same output for the same input, an LLM's response can vary. This non-determinism, combined with reliance on external tools and APIs, creates multiple potential points of failure.
Let's start by watching a short video that frames this problem. While it discusses non-determinism broadly, it correctly identifies that the real concerns are response quality and debugging—both of which are addressed by robust error handling and validation.
Evaluating and Debugging Non-Deterministic AI Agents
The video 'Evaluating and Debugging Non-Deterministic AI Agents' from Google Cloud Tech sets the stage for our discussion. It clarifies that the challenge isn't non-determinism itself, but managing its consequences.
Watch the segment from 01:16 to 02:12. Pay attention to how the speakers reframe the problem from 'fixing non-determinism' to 'ensuring reasonable responses' and 'making debugging easier'.
Categorizing Failure Modes
To handle errors effectively, we first need to understand where they come from. In an agentic system, failures can occur at multiple levels.
The article below provides an excellent breakdown of common error sources.
Error Handling Strategies in Tool Execution
The article 'Error Handling Strategies in Tool Execution' from ApX Machine Learning offers a clear categorization of why tools might fail. Understanding these categories helps in designing targeted solutions.
Read the introductory part and the section titled 'Why Tools Falter: Common Sources of Errors'. As you read, think about which of these you've encountered when dealing with standard API integrations in your own work.
As the article outlines, errors generally fall into these buckets:
- Input Issues: The LLM provides malformed arguments to a tool (e.g., a string instead of an integer, an invalid format). This is a very common failure mode due to the creative nature of LLMs.
- Execution & External Service Issues: The tool itself fails during execution. This could be due to a network timeout, a 404 error from an API, failed authentication, or a rate limit being exceeded.
- Internal Logic/Resource Errors: Classic software bugs within your tool's code or an inability to access a local resource (like a file not found).
Now, let's explore the strategies to handle these, starting with the most proactive approach: validation.
Proactive Defense: Validating LLM Outputs with Pydantic
Many errors can be caught before a tool even executes by validating the inputs the LLM provides. Forcing the LLM's output to conform to a strict schema is one of the most powerful techniques for building reliable agents. In the Python ecosystem, Pydantic is the go-to library for this.
The following image provides a high-level overview of how Pydantic acts as a validation layer between the often-messy output of an LLM and your structured application code.

Now, let's see this in action. The instructor library, paired with Pydantic, provides a powerful and elegant way to not only validate LLM outputs but also to automatically guide the LLM to correct its mistakes.
Pydantic: How to Validate LLM Responses? 🚀 Quality Response. VERY EASY!!!!
This video, 'Pydantic: How to Validate LLM Responses?', demonstrates a practical and highly effective approach. It shows how to define a Pydantic model for your desired output and use instructor to enforce it, even triggering a re-prompt if the LLM's first attempt is invalid.
Watch from the beginning to 04:22. The key steps are: Defining a Pydantic BaseModel that represents the desired data structure and types. Using instructor.patch() to augment the OpenAI client. Adding the response_model parameter to the chat completion call. Notice how this simple setup ensures you always get back a correctly-typed Pydantic object, handling the messy conversion and validation for you.
This approach of defining a schema with Pydantic and using a library like instructor is a best practice for handling input issues. It prevents your tools from ever being called with malformed data.
Reactive Defense: Robust In-Tool Error Handling
Validation is great, but it can't prevent all errors. A perfectly valid API call can still fail due to network issues or server-side problems. This is where reactive error handling—writing your tool code defensively—comes in.
The core principle is to catch exceptions within your tool and return a descriptive error message to the LLM agent. Crashing the agent is unhelpful. Providing it with information about the failure allows it to potentially retry, try an alternative tool, or inform the user.
This next article provides a comprehensive guide with a clear pseudocode example that should be very familiar from a general software engineering perspective.
Error Handling Strategies in Tool Execution
Let's return to the 'Error Handling Strategies in Tool Execution' article. This time, we'll focus on the core strategies for managing errors that happen during a tool's execution.
Read the sections 'Core Strategies for Managing Tool Errors', 'Proactive Input Validation', and 'Handling External Service Issues'. Pay close attention to: The structure of a good error message for an LLM (Error Type, Descriptive Message). The Python-esque pseudocode, which demonstrates wrapping tool logic in try...except blocks for different failure types. Standard strategies for external services like 'Retries with Exponential Backoff' and 'Timeouts'.
To summarize the key takeaways for your tool's implementation:
- Wrap critical code in
try...exceptblocks. Catch specific exceptions likeNetworkTimeoutor generic ones. - Return structured error messages. Instead of just
{"error": "Something went wrong"}, return something the LLM can parse, like:{"success": False, "error": {"type": "APIFailure", "message": "The weather service returned a 503 Service Unavailable error. You could try again in a few minutes."}}. - Implement retries for transient errors. For network glitches or temporary service overloads, a simple retry loop with exponential backoff can make your agent much more resilient. The
tenacitylibrary in Python is excellent for this. - Log detailed technical errors for yourself. While the LLM gets a user-friendly error, your logs should contain the full stack trace for debugging.
A Holistic Approach to Reliability
Effective error handling isn't about a single technique; it's a layered strategy that combines proactive validation, reactive error handling, and good software engineering discipline.
The video from Google Cloud Tech connects these ideas back to fundamental development practices.
Evaluating and Debugging Non-Deterministic AI Agents
Let's revisit the Google Cloud Tech video to see how these specific techniques fit into a broader strategy for building reliable, debuggable agents.
Watch from 02:12 to 06:46. This segment discusses: Evaluating each step: Adding validation checks after each tool call to catch errors before they propagate. Applying basic software engineering: Catching errors and using fallbacks, just as you would with any external API. Comprehensive logging: The importance of logging tool calls, parameters, and results to make debugging non-deterministic systems possible.
Finally, as a developer, you know that reliability is also a function of good testing. Building agents requires a shift in testing mindset, away from purely deterministic unit tests and towards testing for behavioral properties, including how the agent handles failure.

Conclusion
In this lesson, you've learned how to move beyond the "happy path" and build resilient, robust AI agents that can handle real-world failures.
Key Takeaways:
- Categorize Errors: Agent failures can stem from invalid LLM inputs, tool execution errors, or external service problems.
- Validate Proactively: Use schema validation libraries like Pydantic to enforce structure on LLM outputs, catching malformed data before it causes problems.
- Handle Reactively: Write defensive tool code using
try...exceptblocks to catch runtime errors. - Inform the Agent: When a tool fails, it should return a structured, descriptive error message to the LLM, not crash. This allows the agent to reason about the failure and decide on a next step (e.g., retry or inform the user).
- Embrace Engineering Principles: Building reliable agents relies on familiar software engineering practices like logging, retries with exponential backoff, timeouts, and comprehensive testing for failure modes.
You are now equipped to build agents that are not only capable but also dependable.
In the next module, we'll shift our focus slightly. Having built a strong conceptual and practical foundation for how LLMs work and how agents reason, we will begin exploring how to interact with them programmatically through APIs and master the art of prompt engineering.