ReAct Architecture: Making AI Think Before It Acts
This article introduces the ReAct (Reason + Act) agent pattern, explains its reasoning‑action‑observation loop, shows how to build a basic single‑call agent and a full ReAct agent with LangGraph, compares their performance on a multi‑step query, and provides a quantitative evaluation highlighting ReAct’s advantages and trade‑offs.
Introduction
When an AI agent receives a complex question such as “Who is the current CEO of the company that produced Dune and what is the budget of its latest film?”, a single‑search approach often returns incoherent or incomplete answers because it treats the whole problem as one search.
What Is ReAct?
ReAct (Reason + Act) is an agent design pattern that interleaves reasoning and tool usage. At each step the model thinks about what to do next, acts by invoking a tool (e.g., a web search), then observes the tool’s result and repeats the cycle until the task is solved.
This loop mirrors how humans solve complex problems.
ReAct Workflow
Receive Goal : The agent gets a complex task.
Reason : It generates a self‑talk plan, e.g., “First find the production company, then its CEO, then the budget.”
Act : Calls a tool such as web_search("X").
Observe : Receives the tool’s output.
Loop : Incorporates the observation into the context and returns to step 2.
Finish : Stops when enough information is gathered.
When to Use ReAct
Multi‑hop question answering.
Web navigation and research that requires iterative refinement.
Interactive workflows where the environment changes and steps cannot be predetermined (e.g., troubleshooting, code debugging).
Pros and Cons
Advantages : Dynamic planning, ability to handle complex multi‑step tasks.
Disadvantages : Higher latency and cost due to multiple LLM calls; risk of infinite loops if prompts are unclear, requiring explicit exit conditions.
Setup
Install the required libraries:
# !pip install -q -U langchain-nebius langchain langgraph rich python-dotenv tavily-pythonCreate a .env file with your API keys:
NEBIUS_API_KEY="your_nebius_api_key"
LANGCHAIN_API_KEY="your_langsmith_api_key"
TAVILY_API_KEY="your_tavily_api_key"Basic Single‑Call Agent
A linear LangGraph with an agent node that can call a tool only once. The agent receives the user query, performs one web_search, and then must produce a final answer.
class AgentState(TypedDict):
messages: Annotated[list[AnyMessage], add_messages]
search_tool = TavilySearchResults(max_results=2, name="web_search")
llm = ChatNebius(model="meta-llama/Meta-Llama-3.1-8B-Instruct", temperature=0)
llm_with_tools = llm.bind_tools([search_tool])
def basic_agent_node(state: AgentState):
console.print("--- 基础智能体:思考中... ---")
system_prompt = "你是一个有用的助手。你可以使用网络搜索工具。请基于工具结果回答用户问题。你必须在一次工具调用后给出最终答案。"
messages = [("system", system_prompt)] + state["messages"]
response = llm_with_tools.invoke(messages)
return {"messages": [response]}
# Build and compile the graph (omitted for brevity)Testing this agent on the multi‑step query typically yields a wrong or incomplete answer, illustrating the need for iterative reasoning.
Building the ReAct Agent
The ReAct graph adds a loop from the tools node back to the agent node, enabling repeated reasoning cycles.
def react_agent_node(state: AgentState):
console.print("--- REACT 智能体:思考中... ---")
response = llm_with_tools.invoke(state["messages"])
return {"messages": [response]}
def react_router(state: AgentState):
last_message = state["messages"][-1]
if last_message.tool_calls:
console.print("--- 路由:决定调用工具。 ---")
return "tools"
console.print("--- 路由:决定结束。 ---")
return "__end__"
react_graph_builder = StateGraph(AgentState)
react_graph_builder.add_node("agent", react_agent_node)
react_graph_builder.add_node("tools", ToolNode([search_tool]))
react_graph_builder.set_entry_point("agent")
react_graph_builder.add_conditional_edges("agent", react_router, {"tools": "tools", "__end__": "__end__"})
react_graph_builder.add_edge("tools", "agent")
react_agent_app = react_graph_builder.compile()
print("包含推理循环的 ReAct 智能体编译成功。")Comparison Test
Running the same multi‑step query with the ReAct agent produces a clear reasoning trace:
Thought 1 : Identify the production company.
Action 1 : web_search for “Dune production company”.
Observation 1 : Result points to “Legendary Pictures”.
Thought 2 : Find the current CEO of Legendary.
Action 2 : web_search for “Legendary Pictures CEO”.
Observation 2 : Retrieves “Josh Green”.
Thought 3 : Get the budget of Legendary’s latest film.
Action 3 : web_search for “Legendary Pictures recent movie budget”.
Observation 3 : Returns the budget data.
Integration : The agent assembles a complete, accurate answer.
The iterative “think → act → observe” loop demonstrates ReAct’s superiority on complex, multi‑step tasks.
Quantitative Evaluation
A structured evaluation model scores both agents on task completion and reasoning quality (1‑10). The basic agent receives low scores for both criteria, while the ReAct agent scores near‑perfect, confirming its advantage.
class TaskEvaluation(BaseModel):
"""评估智能体完成任务能力的评分模式。"""
task_completion_score: int = Field(description="1-10分,智能体是否成功完成了用户请求的所有部分。")
reasoning_quality_score: int = Field(description="1-10分,智能体展现的逻辑流程与推理质量。")
justification: str = Field(description="分数的简要理由。")
judge_llm = llm.with_structured_output(TaskEvaluation)
def evaluate_agent_output(query: str, agent_output: dict):
trace = "
".join([f"{m.type}: {m.content}" for m in agent_output['messages']])
prompt = f"""你是一位专门评估 AI 智能体的裁判。请为以下智能体在给定任务上的表现打分,1-10分。10分表示任务完成完美,1分表示完全失败。
**用户任务:**
{query}
**完整智能体对话追踪:**
{trace}
"""
return judge_llm.invoke(prompt)
basic_agent_evaluation = evaluate_agent_output(multi_step_query, basic_agent_output)
react_agent_evaluation = evaluate_agent_output(multi_step_query, final_react_output)
print(basic_agent_evaluation.model_dump())
print(react_agent_evaluation.model_dump())Key Takeaways
Core principle: ReAct’s reason → act → observe loop enables dynamic planning for multi‑step problems. Implementation tip: In LangGraph, create a back‑edge from tools to agent to form the loop. Pitfall warning: Guard against infinite loops by adding stop conditions in prompts or code.
Conclusion
Although ReAct incurs higher latency and cost, its ability to handle deep analysis and multi‑hop reasoning makes it valuable for real‑world scenarios such as complex customer‑service tickets, root‑cause analysis in operations, and multi‑source verification in finance.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Data STUDIO
Click to receive the "Python Study Handbook"; reply "benefit" in the chat to get it. Data STUDIO focuses on original data science articles, centered on Python, covering machine learning, data analysis, visualization, MySQL and other practical knowledge and project case studies.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
