Agent Patterns and Production Tool Use
Deliberate Academy Editorial Team
Reviewed for accuracy and professional relevance
You're 4 lessons in — don't lose your progress.
Sign up free to save where you are and earn a verified certificate when you pass.
- Implement the ReAct pattern for multi-step LLM reasoning and identify the three most common failure modes in production agent loops
- Write tool/function definitions that minimise hallucinated calls and maximise model compliance with tool use constraints
- Evaluate LangGraph vs. raw tool use for a described agent use case and justify the architectural decision
- Design human-in-the-loop checkpoints and agent observability instrumentation for a production agent system
An agent is an LLM system that takes actions to accomplish a goal. Instead of receiving a prompt and returning a response, the agent receives a goal, decides what actions to take, executes those actions via tools, observes the results, and iterates until the goal is complete or a stopping condition is reached.
Agents are genuinely powerful for certain problem classes — tasks that require multi-step planning, dynamic data retrieval, or sequences of actions that cannot be predetermined. They are also the most complex LLM integration pattern to build reliably. Most agent systems fail not because the underlying LLM is incapable, but because the agent loop design, tool definitions, context management, and failure handling are insufficient for the complexity of real production environments.
This lesson covers how to build agents that work reliably, not just in demos.
The ReAct Pattern
ReAct (Reasoning and Acting) is the foundational pattern for most production agent implementations. The pattern works as follows: given a goal, the LLM produces a Thought (reasoning about what to do next), an Action (which tool to call and with what inputs), and then observes the Action's output (the Observation). This Thought-Action-Observation cycle repeats until the LLM produces a final answer.
The ReAct pattern is effective because it makes the model's reasoning explicit and observable. The Thought steps are not just artifacts — they are where the model decides what to do next and can catch its own errors ("I retrieved a document about the wrong company, I should search again with a more specific query"). This self-correction capability is what makes ReAct more reliable than simpler action-selection patterns.
Implementing ReAct. Modern LLM APIs expose ReAct through tool/function calling: you define tools, call the API, and if the model returns a tool call, execute the tool and add the result to the conversation history. Repeat until the model returns a final text response instead of a tool call. The tool call is the Action; the result you add back is the Observation; the model's implicit reasoning before the tool call is the Thought.
Context accumulation. Each Thought-Action-Observation cycle adds tokens to the context: the tool call request, the tool output, and the model's next reasoning step. For long tasks with many tool calls, context can grow quickly. Set a maximum iteration count (typically 10-20 steps) as an absolute safety limit, and monitor context token count to trigger summarisation or stopping before the context window is exhausted.
Tool Definition Best Practices
The quality of tool definitions directly determines whether the model calls tools correctly. A poorly defined tool leads to hallucinated arguments, incorrect tool selection, and agent loops that fail silently.
Tool name and description. The tool name should be a clear, unambiguous verb phrase: search_customer_database, get_order_status, send_email. Avoid abbreviations and generic names like search or query that do not specify what is being searched or queried. The description should explain what the tool does, what inputs it expects, and what it returns — in one to three sentences written for the model, not for human developers.
Parameter definition. Every parameter should have a type, a description that explains exactly what value is expected, and an enum constraint where the allowed values are finite and known. Avoid optional parameters unless they are genuinely optional — models tend to omit optional parameters even when they should provide them. For parameters with specific format requirements (ISO date strings, specific ID formats), state the format explicitly in the description.
Return value documentation. Describe what the tool returns in the tool description. If the tool returns a structured object, describe the fields. If the tool can return an error, describe the error format. The model's ability to reason about tool outputs depends on knowing what to expect.
tools = [
{
"name": "get_order_details",
"description": "Retrieve the full details of a specific order by order ID. Returns order status, line items, shipping address, and estimated delivery date. Returns an error object if the order ID does not exist.",
"input_schema": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "The order ID in format ORD-XXXXXXXX (e.g., ORD-12345678)"
}
},
"required": ["order_id"]
}
}
]
Tool outputs are injected into the LLM context as the Observation step. If your tools return large payloads — full database records, long documents, unfiltered API responses — the context fills quickly and the model's performance degrades as relevant information is buried in noise. Tool implementations should return the minimum information the model needs to reason about the next step. Filter, summarise, or paginate large tool outputs before returning them to the agent loop.
Agent Failure Modes
Production agent systems fail in specific, predictable patterns. Understanding these failure modes before building is more valuable than debugging them after deployment.
Hallucinated tool calls. The model calls a tool with arguments that are syntactically valid but semantically incorrect — a made-up customer ID, a date outside a valid range, a parameter value that does not match the expected format. This happens when the model infers parameter values from context rather than extracting them from provided data. Mitigations: validate all tool arguments before execution, return explicit errors (not exceptions) when arguments are invalid so the model can self-correct, and design tools to be safe when called with incorrect arguments (read-only tools that return errors are safer than write tools that execute on bad inputs).
Infinite loops. The agent repeatedly calls the same tool with the same arguments, or enters a cycle between two tools, never progressing toward the goal. This happens when tool outputs do not give the model enough information to determine that progress is not being made. Mitigations: implement a maximum step count, detect repeated tool calls (same tool, same arguments) and inject a message indicating the tool has already been called with those arguments.
Context exhaustion. The agent loop accumulates tool call history, reasoning steps, and observations until the context window is exhausted. The provider either truncates silently or returns an error. Mitigations: monitor token count at each step, implement context summarisation when a token budget threshold is reached, set explicit maximum context budget per agent run.
Goal drift. The model pursues a subtask so thoroughly that it loses sight of the original goal. This is most common in long agent runs with many intermediate steps. Mitigations: include the original goal in the system prompt and at regular intervals in the agent loop message, use a supervisory check step every N iterations that evaluates whether the current trajectory is on-track.
LangGraph vs. Raw Tool Use
LangGraph is a framework for building stateful multi-actor agent systems as directed graphs. Each node in the graph is a processing step (an LLM call, a tool execution, a human approval step), and edges define the control flow between steps. LangGraph handles state persistence, parallel execution of independent subgraphs, conditional routing based on intermediate results, and checkpointing for human-in-the-loop workflows.
When to use LangGraph. LangGraph is appropriate for agent systems with complex, non-linear control flow: parallel execution of multiple agents, conditional branching based on intermediate results, human approval checkpoints, multi-agent coordination where a supervisor routes to specialised subagents. The graph structure makes the system's control flow explicit, debuggable, and modifiable without rewriting the core agent loop.
When to use raw tool use. For simple linear agent loops — a single LLM with a defined tool set, a maximum step count, and straightforward tool execution — raw tool use with a hand-written loop is simpler to implement, easier to debug, and requires no framework dependency. The overhead of LangGraph is justified by complexity, not by the fact that you are building an agent. A five-tool agent that runs in a simple ReAct loop does not need LangGraph.
The middle ground. Many teams start with raw tool use, discover they need some of LangGraph's capabilities (usually human-in-the-loop checkpointing or parallel subgraph execution), and migrate later. This is a reasonable path. Avoid premature adoption of framework complexity.
Human-in-the-Loop Checkpoints
Agents that take consequential actions — sending emails, writing to databases, making API calls that have side effects, spending money — require human approval checkpoints before those actions are executed. This is not an optional safety feature; it is a design requirement for any agent that operates in the real world with real consequences.
Checkpoint placement. Human approval checkpoints should be placed before any irreversible action. Reading data, performing calculations, and drafting content can proceed autonomously. Writing data, sending messages, executing financial transactions, and deleting records require approval. Design the agent so that the approval decision is presented with enough context for the human to make an informed decision: what action is about to be taken, why the agent decided to take it, and what the expected outcome is.
Asynchronous approval. For workflows where the agent may need to wait minutes or hours for human approval, the agent state must be persisted so the workflow can resume after approval without re-executing preceding steps. LangGraph's checkpointing is designed for this pattern. For raw implementations, persist the full agent state to a database at each checkpoint.
Approval granularity. Avoid presenting humans with every micro-decision the agent makes — approval fatigue leads to rubber-stamping. Reserve human approval for high-stakes, irreversible, or novel decisions. For well-understood, low-risk actions, define a pre-approved action policy and let the agent proceed autonomously within it.
Agent Observability
Agent systems are more difficult to observe than single-turn LLM calls because the interesting events are distributed across multiple steps, multiple LLM calls, and multiple tool executions, all connected by conversational context that is not visible in standard request logs.
What to trace. For each agent run, record: the initial goal, every LLM call with its full prompt and response, every tool call with its arguments and return value, the step count and total token count, the final outcome (success, failure, max steps reached, human rejection), and the total elapsed time and cost.
Session replay. The most valuable debugging capability for agents is session replay: the ability to look at a specific agent run and see the exact sequence of thoughts, actions, and observations that led to the final outcome. LangSmith (from LangChain), Langfuse, and Braintrust all support this for LangGraph and instrumented raw agent loops. Without session replay, debugging an agent that failed partway through a 15-step task is extremely difficult.
Detecting failure modes in traces. Design your observability to surface the known failure modes: step count distribution (are runs regularly hitting the maximum?), repeated tool call detection (are loops occurring?), context token usage per step (is context growing unexpectedly quickly?), tool error rates by tool name (which tools fail most frequently and why?).
Eliminating infinite loops in a customer support agent
Context
A B2C e-commerce company deployed a customer support agent that could look up orders, check inventory, and initiate refunds. The agent used a ReAct loop with five tools and a maximum of 25 steps. After launch, they noticed that approximately 8% of agent runs hit the 25-step maximum and terminated without resolving the customer query. Support team review showed these runs typically involved order status lookups for orders that were in a 'pending' state, which provided ambiguous information to the agent.
Action
Examining traces in LangSmith, the engineering team found a common pattern: the agent would call get_order_status, receive 'status: pending', call get_order_status again with the same order ID (same tool, same argument, same result), and continue this loop for up to 20 steps before hitting the maximum. The agent had no signal that repeating the same call would produce a different result. The team added a repeated tool call detector that injected a message after three identical calls ('This tool has already been called with these arguments. The result will not change. Proceed with the information available.') and added explicit handling in the get_order_status tool for 'pending' status that included an estimated resolution time.
Outcome
Runs hitting the maximum step count dropped from 8% to 0.4% within a week. Customer queries about pending orders began receiving accurate estimates rather than agent timeouts. The team added automatic detection of the top-3 loop patterns to their weekly agent quality review, discovering a second loop pattern involving inventory lookup that was resolved with a similar fix.
A production agent handles customer queries by looking up account data, checking policy documents, and drafting responses. The agent occasionally takes inappropriate actions — drafting refund emails for customers who are not eligible for refunds under the policy retrieved. The team is debugging why the agent ignores policy constraints found in retrieved documents. Which investigation approach is most likely to identify the root cause?
Select one answer.
Why does this lesson advise against marking a tool parameter optional unless it genuinely is?
Select one answer.
Exercise
Your Task
Design the agent architecture for the following scenario: a procurement AI agent assists buyers in processing purchase requisitions. Given a requisition, the agent must: check the supplier's compliance status in the supplier database, verify the requested item is in the approved product catalog, check that the requisition amount is within the buyer's approval limit, retrieve the current budget balance for the relevant cost centre, and either approve the requisition automatically (if all checks pass) or flag it for human review with a specific reason. Specify: (1) the tool definitions for each check, including the exact schema and return format, (2) which actions require human-in-the-loop checkpoints and why, (3) the maximum step count and your reasoning for it, (4) what to log in traces to make failures debuggable, and (5) one failure mode specific to this use case and how you would detect it.
Your reflection
Did you complete this exercise? What did you find? (Saved locally in your browser)
- The ReAct pattern (Thought-Action-Observation) is the foundation of production agent implementations. Modern LLM tool calling APIs implement this pattern natively: tool call requests are Actions and tool results added back to the conversation are Observations.
- Tool definition quality determines whether the model calls tools correctly. Every parameter needs a clear description with format requirements, and tool outputs should be filtered to minimum necessary information before returning to the agent loop.
- The three most impactful production failure modes are: hallucinated tool call arguments (validate all arguments before execution), infinite loops (detect repeated identical calls), and context exhaustion (monitor token count per step and set hard maximum step counts).
- LangGraph is appropriate for complex non-linear agent control flow (parallel execution, conditional branching, human approval checkpoints). Raw tool use with a hand-written loop is sufficient for simple linear ReAct agents and is easier to debug and maintain.
- Agent observability requires tracing every LLM call and tool call in a session, recording the full context at each step, and supporting session replay — the ability to examine the exact sequence of thoughts, actions, and observations for any specific agent run.