LangGraph ReAct Agent Template

repository·main·Indexed 21 days ago

https://github.com/langchain-ai/react-agent

A starter template for building custom Reasoning and Action (ReAct) agents using LangGraph. It implements a reasoning-action loop that integrates with tool calling and is optimized for visualization and development within LangGraph Studio. The template supports multiple LLM providers, including Anthropic and OpenAI, and provides a pre-compiled graph object for direct application integration.

Tokens
3.5K
Snippets
13
Records
16
Agent score
74%

What's inside react-agent

  1. Development and Debugging in LangGraph Studio

    main

    When developing with this template in LangGraph Studio:

    • Hot Reloading: Local code changes are automatically applied.
    • State Manipulation: You can edit past states and rerun the application from those specific points to debug individual nodes.
    • Thread Management: Follow-up requests are appended to the current thread. To start fresh, use the + button in the top right to create a new thread.
    • Advanced Debugging: Use interrupts (e.g., before tool calls) or modify the system message in src/react_agent/context.py to test different agent personas.
  2. Customize the ReAct Agent

    main

    You can extend the agent's capabilities by modifying the following files:

    • Add new tools: Define new Python functions in src/react_agent/tools.py to expand what the agent can do.
    • Select a different model: Use the provider/model-name syntax in the LangGraph Studio runtime context to change the model (e.g., openai/gpt-4-turbo-preview).
    • Customize the prompt: Update the system prompt in src/react_agent/prompts.py.
    • Modify reasoning logic: Adjust the agent's graph structure, loop, or decision-making steps in src/react_agent/graph.py.
  3. Configure LLM Providers (Anthropic and OpenAI)

    main

    The template supports multiple LLM providers. You can switch providers by adding the appropriate API key to your .env file and specifying the model via runtime context in LangGraph Studio using the provider/model-name format (e.g., openai/gpt-4-turbo-preview).

    Anthropic Setup: Add ANTHROPIC_API_KEY=your-api-key to your .env file.

    OpenAI Setup: Add OPENAI_API_KEY=your-api-key to your .env file.

    ANTHROPIC_API_KEY=your-api-key
    OPENAI_API_KEY=your-api-key
  4. Get Started with the LangGraph ReAct Agent Template

    main

    This template provides a ReAct agent implementation using LangGraph, optimized for use with LangGraph Studio. The agent follows a reasoning-action loop: it takes a query, reasons about it, executes a tool, observes the result, and repeats until a final answer is reached.

    To set up the project:

    1. Ensure LangGraph Studio is installed.
    2. Create a .env file from the example:
      cp .env.example .env
    3. Configure your API keys in the .env file (e.g., TAVILY_API_KEY for search tools, ANTHROPIC_API_KEY or OPENAI_API_KEY for the LLM).
    4. Open the project folder in LangGraph Studio.
    cp .env.example .env
  5. Customize the ReAct Agent model and tools

    main

    The agent's behavior is driven by the call_model node. To change the LLM being used or the set of available tools, you must modify how the model is initialized within this function. The model is loaded via load_chat_model(runtime.context.model) and tools are attached using .bind_tools(TOOLS).

    Note that the system_prompt is retrieved from runtime.context.system_prompt and can be customized to change the agent's persona or instructions.

    # Example of how the model and tools are bound inside call_model
    model = load_chat_model(runtime.context.model).bind_tools(TOOLS)
    
    system_message = runtime.context.system_prompt.format(
        system_time=datetime.now(tz=UTC).isoformat()
    )
  6. Understand the ReAct Agent graph structure

    main

    The ReAct agent is implemented as a StateGraph that cycles between two main nodes: call_model and tools.

    1. Entrypoint: The graph starts at call_model.
    2. Routing: After call_model executes, the route_model_output function determines the next step:
      • If the model's response contains tool_calls, the graph routes to the tools node.
      • If there are no tool_calls, the graph routes to __end__.
    3. Tool Execution: The tools node (a ToolNode instance) executes the requested actions and then routes back to call_model to allow the model to process the tool results.
    4. Termination: If the agent reaches its maximum step limit (state.is_last_step) but still attempts to call a tool, the call_model node intercepts this and returns a fallback message instead of proceeding to the tools.
  7. Configure Agent parameters via environment variables

    main

    The Context class automatically attempts to populate its fields from environment variables if they are not explicitly provided during instantiation. The environment variable names are the uppercase versions of the field names.

    Supported environment variables:

    • SYSTEM_PROMPT: Sets the agent's system prompt.
    • MODEL: Sets the LLM model identifier.
    • MAX_SEARCH_RESULTS: Sets the maximum number of search results.

    Note: This fallback mechanism only applies to fields that are not explicitly passed as arguments to the Context constructor.

    # Example: Setting configuration via shell before running the agent
    # export MODEL="anthropic/claude-3-5-sonnet-20240620"
    # export MAX_SEARCH_RESULTS=20
    
    from react_agent.context import Context
    context = Context()  # Uses environment variables for defaults
  8. Load a chat model with load_chat_model

    main

    The load_chat_model(fully_specified_name: str) function initializes a LangChain chat model using a shorthand string format. The input string must follow the pattern 'provider/model'. This function uses LangChain's init_chat_model internally to resolve the provider and model name.

    from react_agent.utils import load_chat_model
    
    # Load an OpenAI model
    model = load_chat_model("openai/gpt-4o")
    
    # Load an Anthropic model
    model = load_chat_model("anthropic/claude-3-5-sonnet-20240620")
  9. Use the search tool for web results

    main

    The search function provides a way to perform web searches using the Tavily search engine. It is designed to return comprehensive and accurate results, making it suitable for answering questions about current events.

    This tool retrieves its configuration (specifically max_search_results) from the Context object via the LangGraph runtime.

    Note: This is provided as an example tool. For production environments, you should implement more robust or specialized tools tailored to your specific requirements.

    from react_agent.tools import search
    
    # Example usage within an agent loop
    results = await search("current events in AI")
  10. Extract text from a BaseMessage with get_message_text

    main

    Use get_message_text(msg: BaseMessage) to reliably extract the string content from a LangChain message object. This function handles various message content formats, including plain strings, dictionary-based content (e.g., {'text': '...'}), and complex list-based content structures common in multi-modal models. It ensures a consistent string output regardless of the underlying message structure.

    from langchain_core.messages import HumanMessage
    from react_agent.utils import get_message_text
    
    # Example with string content
    msg_str = HumanMessage(content="Hello")
    print(get_message_text(msg_str))  # Output: "Hello"
    
    # Example with dict content
    msg_dict = HumanMessage(content={"text": "Hello"})
    print(get_message_text(msg_dict))  # Output: "Hello"
  11. Implement route_model_output for conditional routing

    main

    To control the flow of a ReAct agent, you can implement a routing function like route_model_output. This function inspects the last message in the State to decide whether to continue to a tool node or finish the execution.

    It must return a Literal["__end__", "tools"] based on whether state.messages[-1] (which should be an AIMessage) contains tool_calls.

    def route_model_output(state: State) -> Literal["__end__", "tools"]:
        last_message = state.messages[-1]
        if not isinstance(last_message, AIMessage):
            raise ValueError(f"Expected AIMessage in output edges, but got {type(last_message).__name__}")
        
        if not last_message.tool_calls:
            return "__end__"
        return "tools"
  12. Configure the ReAct Agent using the Context class

    main

    The Context class is used to define the configurable parameters for the agent, including the system prompt, the LLM model, and search constraints. You can instantiate Context by passing specific arguments or by relying on environment variables for default values.

    Available configuration fields:

    • system_prompt (str): The system prompt that sets the agent's behavior. Defaults to prompts.SYSTEM_PROMPT.
    • model (str): The identifier for the language model in the format provider/model-name (e.g., anthropic/claude-sonnet-4-5-20250929).
    • max_search_results (int): The maximum number of search results to return per query. Defaults to 10.
    from react_agent.context import Context
    
    # Explicit configuration
    context = Context(
        model="openai/gpt-4o",
        max_search_results=5,
        system_prompt="You are a helpful assistant."
    )