While the core of an agent is its Large Language Model, the strategy it uses to reason and solve a problem can differ significantly. LangChain provides several agent types, each embodying a different approach to the reasoning process. These different approaches are not merely academic; they have practical implications for an agent's performance, reliability, and suitability for a given task. The component that powers these reasoning strategies is the AgentExecutor, which acts as the runtime for the agent, managing the interaction between the LLM, the tools, and the user input.
Before examining the different agent types, it is important to understand the AgentExecutor. This is the mechanism that facilitates the agent's operation. It takes an agent and a set of tools as input and runs a loop until a stopping condition is met. This loop is often referred to as the "reasoning loop."
The typical flow of this loop is as follows:
AgentExecutor passes the user input and any previous steps to the agent.Thought and a proposed Action.AgentExecutor parses this response. If an Action is specified, it identifies the tool to use and the input for that tool.Observation, is sent back to the agent.Thought -> Action -> Observation repeats until the agent determines it has the final answer and provides it.This iterative process allows the agent to build context, recover from errors, and break down complex problems into smaller, manageable steps.
The AgentExecutor manages the cycle where the LLM reasons (Thought), chooses a tool (Action), and receives new information (Observation) to continue its reasoning process.
The ReAct framework, which stands for "Reason and Act," is one of the most common and effective general-purpose strategies for agents. The main idea is that the LLM explicitly verbalizes its reasoning process (Thought) before deciding on an Action. This chain-of-thought process makes the agent's behavior more interpretable and often leads to more reliable tool use.
A ReAct agent's prompt template guides the LLM to generate text in a specific format:
Question: The user's query goes here.
Thought: The model's reasoning about what it needs to do next.
Action: The tool to use and the input for that tool.
Observation: The result from executing the tool.
... (this Thought/Action/Observation cycle repeats)
Thought: I now have enough information to answer the user's question.
Final Answer: The final response to the user.
This structure forces the LLM to plan its steps, execute them, and then reflect on the outcome before proceeding. It is a powerful pattern for tasks that require multiple tool calls or gathering information from several sources to formulate an answer.
You can initialize a ReAct-based agent using the create_react_agent constructor, which assembles the necessary prompt and logic.
from langchain.agents import create_react_agent, AgentExecutor
from langchain_openai import ChatOpenAI
from langchain import hub
# Load the ReAct prompt template
prompt = hub.pull("hwchase17/react")
# Initialize the LLM
llm = ChatOpenAI(model="gpt-4o", temperature=0)
# Create the agent
# Tools would be defined and passed in here
# tools = [...]
agent = create_react_agent(llm, tools, prompt)
# Create the AgentExecutor
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
The Self-Ask with Search agent type is designed for question-answering tasks where a complex question needs to be broken down into simpler, factual sub-questions. It iteratively "asks itself" these simpler questions and uses a Search tool to find the answers. Once all the intermediate answers are gathered, it synthesizes them into a final response.
The prompt for this agent encourages a different reasoning pattern:
Question: Who was the maternal grandfather of the 14th Dalai Lama?
Are follow up questions needed here: Yes.
Follow up: Who was the 14th Dalai Lama's mother?
Intermediate answer: The 14th Dalai Lama's mother was Diki Tsering.
Follow up: Who was Diki Tsering's father?
Intermediate answer: Diki Tsering's father was Choekyong Tsering.
So the final answer is: Choekyong Tsering.
This approach is particularly effective for questions that involve multiple hops of information retrieval. By explicitly stating intermediate questions and answers, the agent's reasoning path is transparent and easier to verify. As its name suggests, this agent type is tightly coupled with a search tool.
Standard agents are typically stateless; they treat each query independently. Conversational agents are designed to overcome this limitation by incorporating memory. This allows them to remember previous interactions in a conversation and use that context to inform their responses.
These agents often use a ReAct-style logic but are built with prompts that are specifically designed to handle chat history. The prompt template includes a placeholder for conversation history, which is managed by a memory object, as discussed in Chapter 4.
Setting up a conversational agent involves creating a memory object and passing it to the AgentExecutor.
from langchain.memory import ConversationBufferWindowMemory
from langchain.agents import create_react_agent, AgentExecutor
from langchain import hub
# Define a memory object
memory = ConversationBufferWindowMemory(
k=2, # Remember the last 2 interactions
memory_key="chat_history",
return_messages=True
)
# Load a prompt that supports chat history
prompt = hub.pull("hwchase17/react-chat")
# Create a conversational agent
agent = create_react_agent(llm, tools, prompt)
# The AgentExecutor now includes the memory object
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
memory=memory,
verbose=True,
handle_parsing_errors=True
)
agent_executor.invoke({"input": "Hi, my name is Bob."})
agent_executor.invoke({"input": "What's my name?"})
The agent can now correctly answer the second question by accessing the conversation history stored in memory.
The choice of agent type depends on your application's requirements:
When configuring the AgentExecutor, you have access to several parameters that help control its behavior and make it more reliable. Two important ones are:
max_iterations: This prevents agents from getting stuck in long or infinite loops by setting a hard limit on the number of Thought -> Action -> Observation cycles.handle_parsing_errors: LLMs can sometimes produce output that the agent can't parse into a valid Action. Setting this parameter to True or providing a custom function allows the executor to gracefully handle such errors, for example, by sending the error message back to the LLM for self-correction.By understanding these different reasoning strategies and the AgentExecutor that drives them, you can build more sophisticated and specialized agents tailored to the unique challenges of your application.
Cleaner syntax. Built-in debugging. Production-ready from day one.
Built for the AI systems behind ApX Machine Learning
Was this section helpful?
max_iterations and handle_parsing_errors.© 2026 ApX Machine LearningEngineered with