### Install dependencies for LLM-as-a-Judge example Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/README.md Install necessary libraries for the LLM-as-a-Judge example, including langgraph-reflection, langchain, and openevals. ```bash pip install langgraph-reflection langchain openevals ``` -------------------------------- ### Install dependencies for Code Validation example Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/README.md Install necessary libraries for the Code Validation example, including langgraph-reflection, langchain, openevals, and pyright. ```bash pip install langgraph-reflection langchain openevals pyright ``` -------------------------------- ### Create Basic Reflection Graph Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/api-reference/create_reflection_graph.md This example demonstrates how to create a basic reflection graph using a simple main agent and a judge agent. It shows the setup for both agents and the final compilation and invocation of the reflection graph. ```python from langgraph_reflection import create_reflection_graph from langgraph.graph import StateGraph, MessagesState, START, END from langchain.chat_models import init_chat_model # Create a simple main agent def call_model(state): model = init_chat_model(model="gpt-4") return {"messages": model.invoke(state["messages"])} assistant_graph = ( StateGraph(MessagesState) .add_node(call_model) .add_edge(START, "call_model") .add_edge("call_model", END) .compile() ) # Create a judge/reflection agent def judge(state, config): # Evaluate the last message if evaluate_response(state["messages"][-1]): return None # No critique else: return {"messages": [{"role": "user", "content": "Please improve..."}]} judge_graph = ( StateGraph(MessagesState) .add_node(judge) .add_edge(START, "judge") .add_edge("judge", END) .compile() ) # Create and compile the reflection graph reflection_graph = create_reflection_graph(assistant_graph, judge_graph) compiled_app = reflection_graph.compile() # Use it result = compiled_app.invoke({"messages": [{"role": "user", "content": "Your query"}]}) ``` -------------------------------- ### Install langgraph-reflection from Source Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/package-info.md Clone the repository and install the package in editable mode. ```bash git clone https://github.com/langchain-ai/langgraph-reflection.git cd langgraph-reflection pip install -e . ``` -------------------------------- ### Install langgraph-reflection Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/README.md Install the langgraph-reflection package using pip. ```bash pip install langgraph-reflection ``` -------------------------------- ### Direct Creation Example Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/api-reference/MessagesWithSteps.md Demonstrates how to directly create and use an instance of the MessagesWithSteps state. ```APIDOC ## Example: Direct Creation (Advanced) ### Description This example shows how to instantiate `MessagesWithSteps` and access its fields directly. ### Code ```python from langgraph_reflection import MessagesWithSteps from langchain_core.messages import HumanMessage, AIMessage from langgraph.managed import RemainingSteps # Create a state instance state = MessagesWithSteps( messages=[ HumanMessage(content="Can you explain quantum computing?"), AIMessage(content="Quantum computing harnesses quantum mechanics..."), HumanMessage(content="Can you be more concise?"), ], remaining_steps=RemainingSteps(3) ) # Access fields print(len(state["messages"])) # 3 print(state["remaining_steps"]) # RemainingSteps(3) ``` ``` -------------------------------- ### LangGraph Reflection Implementation Checklist Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/INDEX.md A step-by-step checklist for integrating langgraph-reflection into your project, covering installation, imports, graph building, and invocation. ```markdown - [ ] Install: `pip install langgraph-reflection` - [ ] Import: `from langgraph_reflection import create_reflection_graph` - [ ] Build main agent graph (StateGraph → compile) - [ ] Build reflection agent graph (StateGraph → compile) - [ ] Returns `None` for approval - [ ] Returns `{"messages": [HumanMessage(...)]}` for feedback - [ ] Call `create_reflection_graph(main, reflection)` - [ ] Call `.compile()` on result - [ ] Invoke with `{"messages": [...]}` - [ ] Access final state from result ``` -------------------------------- ### Example Usage of Reflection App Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/usage-examples.md Invokes the compiled reflection graph with an initial state and prints the final response and evaluation metrics. ```python # Example usage if __name__ == "__main__": question = "What are the benefits of renewable energy?" initial_state = { "messages": [{"role": "user", "content": question}], "evaluation_results": None, "evaluation_rounds": 0 } result = reflection_app.invoke(initial_state) print("Final Response:", result["messages"][-1].content) print("Evaluation Results:", result.get("evaluation_results")) print("Evaluation Rounds:", result.get("evaluation_rounds")) ``` -------------------------------- ### Build LangGraph Reflection Package Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/package-info.md Use these commands to build the package. Ensure you have the 'build' package installed. This process generates distribution files in the 'dist/' directory. ```bash pip install build python -m build ``` -------------------------------- ### Run LangGraph Reflection Tests Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/package-info.md Clone the repository, install dependencies, and run tests using pytest. Ensure you have the development dependencies installed. ```bash git clone https://github.com/langchain-ai/langgraph-reflection.git cd langgraph-reflection pip install -e ".[dev]" pytest ``` -------------------------------- ### Code Validation Example Usage Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/README.md Demonstrates using the reflection agent for Python code validation with Pyright. The agent generates code, validates it, and iterates based on Pyright's feedback until the code passes static analysis. ```python assistant_graph = ... # Function that validates code using Pyright def try_running(state: dict) -> dict | None: """Attempt to run and analyze the extracted Python code.""" # Extract code from the conversation code = extract_python_code(state['messages']) # Run Pyright analysis evaluator = create_pyright_evaluator() result = evaluator(outputs=code) if not result['score']: # If errors found, return critique for the main agent return { "messages": [{ "role": "user", "content": f"I ran pyright and found this: {result['comment']}\n\n" "Try to fix it..." }] } # No errors found - return None to indicate success return None # Create graphs with reflection judge_graph = StateGraph(MessagesState).add_node(try_running).... # Create reflection system that combines code generation and validation reflection_app = create_reflection_graph(assistant_graph, judge_graph) result = reflection_app.invoke({"messages": example_query}) ``` -------------------------------- ### LLM-as-a-Judge Example Usage Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/README.md Demonstrates setting up and using the reflection graph with an LLM-as-a-Judge for response evaluation. The judge approves responses or provides critiques for the main agent to address. ```python # Define the main assistant graph assistant_graph = ... # Define the judge function that evaluates responses def judge_response(state, config): """Evaluate the assistant's response using a separate judge model.""" evaluator = create_llm_as_judge( prompt=critique_prompt, model="openai:o3-mini", feedback_key="pass", ) eval_result = evaluator(outputs=state["messages"][-1].content, inputs=None) if eval_result["score"]: print("✅ Response approved by judge") return else: # Otherwise, return the judge's critique as a new user message print("⚠️ Judge requested improvements") return {"messages": [{"role": "user", "content": eval_result["comment"]}]} # Create graphs with reflection judge_graph = StateGraph(MessagesState).add_node(judge_response).... # Create reflection graph that combines assistant and judge reflection_app = create_reflection_graph(assistant_graph, judge_graph) result = reflection_app.invoke({"messages": example_query}) ``` -------------------------------- ### Type Checking with mypy and pyright Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/INDEX.md Commands to run type checking on the project using mypy and pyright. Ensure these tools are installed and configured for your environment. ```bash mypy src/langgraph_reflection/ pyright src/langgraph_reflection/ ``` -------------------------------- ### Using MessagesWithSteps in Reflection Graph Nodes Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/api-reference/MessagesWithSteps.md Illustrates how nodes within a reflection graph receive and can interact with the MessagesWithSteps state. This example shows accessing message count and remaining steps within a node function. ```python from langgraph_reflection import create_reflection_graph, MessagesWithSteps from langgraph.graph import StateGraph, MessagesState, START, END def my_node(state: MessagesWithSteps): # Nodes in the reflection graph receive MessagesWithSteps num_messages = len(state["messages"]) steps_left = state["remaining_steps"] if steps_left < 2: print("Approaching step limit") return {"messages": state["messages"] + [{"role": "assistant", "content": "..."}]} ``` -------------------------------- ### Audit Dependencies with pip-audit Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/package-info.md Use pip-audit to check for vulnerable dependencies in your project. Ensure pip-audit is installed first. ```bash pip install pip-audit pip-audit ``` -------------------------------- ### Create Reflection Graph with Custom State Schema Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/api-reference/create_reflection_graph.md This example shows how to create a reflection graph when using a custom state schema that extends the default `MessagesState`. The custom schema must include a `messages` field and can include additional fields like `context` and `extra_field`. ```python from typing import TypedDict class CustomState(MessagesState): context: str extra_field: int reflection_graph = create_reflection_graph( assistant_graph, judge_graph, state_schema=CustomState ) compiled_app = reflection_graph.compile() result = compiled_app.invoke({ "messages": [{"role": "user", "content": "Query"}], "context": "additional context", "extra_field": 42 }) ``` -------------------------------- ### Configure Step Limits with Reflection Graph Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/usage-examples.md Use `RunnableConfig` to set `max_steps` for controlling iteration depth. This example demonstrates invoking the compiled reflection graph with both default and custom step limits. ```python from langgraph_reflection import create_reflection_graph from langgraph.graph import StateGraph, MessagesState, START, END from langchain.chat_models import init_chat_model from langchain_core.messages import HumanMessage def agent_node(state): model = init_chat_model(model="gpt-4") return {"messages": model.invoke(state["messages"])} def reflection_node(state, config): # Always request revision to stress-test step limits return {"messages": [HumanMessage(content="Revise.")]} main = ( StateGraph(MessagesState) .add_node("gen", agent_node) .add_edge(START, "gen") .add_edge("gen", END) .compile() ) judge = ( StateGraph(MessagesState) .add_node("judge", reflection_node) .add_edge(START, "judge") .add_edge("judge", END) .compile() ) # Create reflection graph reflection_graph = create_reflection_graph(main, judge) compiled_app = reflection_graph.compile() # Run with custom step limit if __name__ == "__main__": query = "Write a poem about the moon" # Use invoke with config to set step limit from langgraph.types import RunnableConfig # Default step limit (usually 25) result1 = compiled_app.invoke({"messages": [{"role": "user", "content": query}]}) print(f"Default steps: {len(result1['messages'])} messages") # With custom step limit (6 = 3 reflection loops max) config = RunnableConfig(configurable={"max_steps": 6}) result2 = compiled_app.invoke( {"messages": [{"role": "user", "content": query}]}, config=config ) print(f"6-step limit: {len(result2['messages'])} messages") ``` -------------------------------- ### Decision Tree: Choosing a Reflection Pattern Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/INDEX.md This decision tree outlines different reflection patterns based on what drives the evaluation process, guiding you to the appropriate implementation. ```markdown What drives the evaluation? ├─ Another LLM: → Example 1 (Judge) ├─ Static analysis: → Example 2 (Code Validation) ├─ Multi-dimension: → Example 3 (Multi-Evaluation) ├─ Content-based: → Example 4 (Conditional) └─ Other: → Example 6 (Custom) ``` -------------------------------- ### Direct Creation of MessagesWithSteps Instance Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/api-reference/MessagesWithSteps.md Demonstrates how to manually create an instance of MessagesWithSteps, initializing it with message history and a specific number of remaining steps. Useful for testing or advanced use cases. ```python from langgraph_reflection import MessagesWithSteps from langchain_core.messages import HumanMessage, AIMessage from langgraph.managed import RemainingSteps # Create a state instance state = MessagesWithSteps( messages=[ HumanMessage(content="Can you explain quantum computing?"), AIMessage(content="Quantum computing harnesses quantum mechanics..."), HumanMessage(content="Can you be more concise?"), ], remaining_steps=RemainingSteps(3) ) # Access fields print(len(state["messages"])) # 3 print(state["remaining_steps"]) # RemainingSteps(3) ``` -------------------------------- ### Create and Compile a Reflection Graph Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/00-START-HERE.md This snippet demonstrates the core usage of the `create_reflection_graph` function. It shows how to initialize main and critique agents, wire them into a reflection graph, compile the graph, and invoke it with an initial message. ```python from langgraph_reflection import create_reflection_graph # Create two LangGraph agents main_agent = build_your_agent() # Generates responses critique_agent = build_your_critique() # Evaluates responses # Wire them together reflection_graph = create_reflection_graph(main_agent, critique_agent) app = reflection_graph.compile() # Run it result = app.invoke({"messages": [{"role": "user", "content": "Your query"}]}) ``` -------------------------------- ### TOML Build Configuration Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/package-info.md This TOML snippet indicates the build system configuration, implying setuptools with PEP 517/518 compliance. No direct action is needed as it's implied by the pyproject.toml structure. ```toml # Implied by pyproject.toml structure # Uses setuptools with PEP 517/518 compliance ``` -------------------------------- ### Simple LLM-as-Judge Reflection Graph Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/README.md Demonstrates building a reflection graph where an LLM acts as a judge to evaluate and potentially correct the output of a main agent. Requires initialization of chat models and an LLM-as-judge evaluator. ```python from langgraph_reflection import create_reflection_graph from langgraph.graph import StateGraph, MessagesState, START, END # Main agent: generates response def generate(state): model = init_chat_model() return {"messages": model.invoke(state["messages"]) } main = StateGraph(MessagesState) .add_node(generate) .add_edge(START, "generate") .add_edge("generate", END) .compile() # Critique agent: evaluates and provides feedback def judge(state): evaluator = create_llm_as_judge(...) result = evaluator(outputs=state["messages"][-1].content, inputs=None) if result["score"]: return None # Approved, no feedback return {"messages": [{"role": "user", "content": result["comment"]} ]} # Critique critique = StateGraph(MessagesState) .add_node(judge) .add_edge(START, "judge") .add_edge("judge", END) .compile() # Build and run reflection graph reflection_app = create_reflection_graph(main, critique).compile() result = reflection_app.invoke({"messages": [{"role": "user", "content": "Your query"}]}) ``` -------------------------------- ### Define Custom Reflection Node Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/types.md Example of a custom node function that accepts and utilizes the `MessagesWithSteps` state type for type-safe access to messages and remaining steps. ```python from langgraph_reflection import create_reflection_graph, MessagesWithSteps from langgraph.graph import StateGraph, MessagesState, START, END, CompiledStateGraph from langchain_core.messages import HumanMessage, AIMessage def my_reflection_node(state: MessagesWithSteps) -> dict: """A node that receives the extended state type.""" # Type-safe access to both messages and remaining_steps last_msg: BaseMessage = state["messages"][-1] steps_left: RemainingSteps = state["remaining_steps"] if isinstance(last_msg, HumanMessage): return {"messages": [AIMessage(content="Revised response")]} return None ``` -------------------------------- ### Project Structure Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/package-info.md Illustrates the directory layout of the langgraph-reflection project, highlighting key files like README.md, pyproject.toml, and the source directory. ```tree langgraph-reflection/ ├── README.md # Project overview ├── pyproject.toml # Package metadata and dependencies ├── langgraph-reflection.png # Architecture diagram ├── src/ │ └── langgraph_reflection/ │ └── __init__.py # Complete implementation (50 lines) └── examples/ ├── llm_as_a_judge.py # Example: Judge-based reflection └── coding.py # Example: Code validation reflection ``` -------------------------------- ### Code Validation Reflection Graph with Static Analysis Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/README.md Illustrates creating a reflection graph for code generation and validation. The critique agent uses Pyright for static analysis to ensure code correctness. Assumes helper functions for code extraction and Pyright evaluation. ```python # Main agent: generates code def code_gen(state): model = init_chat_model() return {"messages": model.invoke(state["messages"]) } # Critique agent: validates code with Pyright def validate(state): code = extract_python_code(state["messages"]) result = create_pyright_evaluator()(outputs=code) if result["score"]: return None # Valid, no errors return {"messages": [{"role": "user", "content": f"Fix errors: {result['comment']}"}]} # Wire and run main = build_code_gen_graph() # StateGraph critique = build_validator_graph() # StateGraph reflection_app = create_reflection_graph(main, critique).compile() ``` -------------------------------- ### Create and Compile Reflection Graph Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/usage-examples.md Combines the assistant and judge graphs into a reflection app using a custom state schema. ```python # Step 4: Create reflection graph with custom state reflection_app = create_reflection_graph( assistant_graph, judge_graph, state_schema=EvaluationState ).compile() ``` -------------------------------- ### Troubleshooting: Infinite Loop Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/INDEX.md If your reflection process never stops, verify that the reflection agent correctly returns `None` or messages for approval/feedback. ```markdown **Check**: - Reflection agent returns `None` or no messages for approval - Reflection agent returns `HumanMessage` for feedback - [See Pitfall 1](./usage-examples.md#pitfall-1-infinite-loop-reflection-always-critiques) ``` -------------------------------- ### Create Main Agent Graph Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/usage-examples.md A simple graph that generates an answer based on the input messages. ```python # Step 2: Main agent def generate_answer(state): """Generate an answer to the user's question.""" model = init_chat_model(model="gpt-4") response = model.invoke(state["messages"]) return {"messages": response, "evaluation_rounds": state.get("evaluation_rounds", 0)} assistant_graph = ( StateGraph(EvaluationState) .add_node("generate", generate_answer) .add_edge(START, "generate") .add_edge("generate", END) .compile() ) ``` -------------------------------- ### Code Validation with Static Analysis using Pyright Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/usage-examples.md This snippet sets up a LangGraph reflection application. It includes functions for code generation, Python code extraction, and validation using Pyright. The reflection graph orchestrates these steps to ensure generated code is valid. ```python from langgraph_reflection import create_reflection_graph from langgraph.graph import StateGraph, MessagesState, START, END from langchain.chat_models import init_chat_model from langchain_core.messages import HumanMessage import subprocess import re # Step 1: Main agent generates code def code_generator(state): """Generate Python code to solve the user's task.""" model = init_chat_model(model="claude-3-sonnet-latest") system_prompt = """You are a Python code generator. When asked to write code, return only a valid Python code block without explanations.""" messages = [{"role": "system", "content": system_prompt}, *state["messages"]] response = model.invoke(messages) return {"messages": response} assistant_graph = ( StateGraph(MessagesState) .add_node("generate", code_generator) .add_edge(START, "generate") .add_edge("generate", END) .compile() ) # Step 2: Extract Python code from messages def extract_python_code(messages): """Extract Python code block from messages.""" for msg in reversed(messages): content = msg.content if hasattr(msg, 'content') else msg.get('content', '') # Look for code blocks match = re.search(r'```python\n(.*?)```', content, re.DOTALL) if match: return match.group(1) return None # Step 3: Reflection agent validates code with Pyright def validate_code(state, config): """Run Pyright static analysis on the generated code.""" code = extract_python_code(state["messages"]) if not code: return {"messages": [HumanMessage(content="Please provide Python code in a ```python block.")]} # Write code to temp file with open("/tmp/generated_code.py", "w") as f: f.write(code) # Run Pyright try: result = subprocess.run( ["pyright", "/tmp/generated_code.py", "--outputjson"], capture_output=True, text=True, timeout=10 ) errors = result.stdout except Exception as e: errors = str(e) # Parse results if "error" not in errors.lower() and result.returncode == 0: # Code is valid return None else: # Found errors, return feedback return { "messages": [ HumanMessage( content=f"Pyright found issues:\n{errors}\n\nPlease fix the code." ) ] } judge_graph = ( StateGraph(MessagesState) .add_node("validate", validate_code) .add_edge(START, "validate") .add_edge("validate", END) .compile() ) # Step 4: Create reflection graph reflection_app = create_reflection_graph(assistant_graph, judge_graph).compile() # Example usage if __name__ == "__main__": task = "Write a function that calculates the Fibonacci sequence up to n." result = reflection_app.invoke({"messages": [{"role": "user", "content": task}]}) final_code = extract_python_code(result["messages"]) print("Final validated code:\n", final_code) ``` -------------------------------- ### Import Core Reflection Functions Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/INDEX.md Imports the necessary functions for creating and controlling reflection graphs. ```python from langgraph_reflection import create_reflection_graph, end_or_reflect ``` -------------------------------- ### Import Main Module Components Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/package-info.md Import the primary functions and classes from the top-level package. ```python from langgraph_reflection import ( create_reflection_graph, end_or_reflect, MessagesWithSteps ) ``` -------------------------------- ### create_reflection_graph Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/00-START-HERE.md Main function to build a reflection graph. It takes a main agent and a critique agent and wires them together to create a graph that can be compiled and run. ```APIDOC ## create_reflection_graph ### Description Builds a reflection graph by wiring together a main agent and a critique agent. ### Signature `create_reflection_graph(graph, reflection, state_schema=None, config_schema=None) -> StateGraph` ### Parameters - **graph**: The main agent or graph. - **reflection**: The critique agent or graph. - **state_schema** (Optional): The schema for the state. - **config_schema** (Optional): The schema for the configuration. ### Returns A `StateGraph` object representing the reflection graph. ``` -------------------------------- ### Module Map Overview Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/INDEX.md This section outlines the core components of the langgraph-reflection library, including the `create_reflection_graph` function for orchestrating reflection loops, the `end_or_reflect` function for conditional routing, and the `MessagesWithSteps` class for state management. ```text langgraph_reflection/ │ ├── create_reflection_graph(graph, reflection, state_schema, config_schema) → StateGraph │ │ │ ├─ Input: Two CompiledStateGraph instances │ ├─ Output: Uncompiled StateGraph (call .compile() on result) │ └─ Returns: Orchestrated reflection loop │ ├── end_or_reflect(state: MessagesWithSteps) → Literal[END, "graph"] │ │ │ ├─ Routing function for conditional edges │ ├─ Decision: Continue loop or exit? │ └─ Internal use (called by graph routing) │ └── MessagesWithSteps (class) │ ├─ Extends: MessagesState ├─ Field: messages: list[BaseMessage] ├─ Field: remaining_steps: RemainingSteps └─ Used as: State schema in reflection graphs ``` -------------------------------- ### State Evolution in Reflection Loop Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/architecture.md Details how the 'messages' list in the state evolves across iterations, showing the addition of AI and Human messages based on agent actions and the potential for loop termination. ```text Iteration 1: messages = [HumanMessage("User query")] → Main agent executes → messages = [HumanMessage("User query"), AIMessage("Response")] → Reflection agent executes → messages = [..., AIMessage(...), HumanMessage("Feedback")] Iteration 2: messages = [HumanMessage, AIMessage, HumanMessage("Feedback")] → Main agent executes (receives full context) → messages = [..., HumanMessage, AIMessage("Revised response")] → Reflection agent executes → messages = [..., HumanMessage, AIMessage, HumanMessage(...)] Or approval: → messages = [..., HumanMessage, AIMessage] (no new HumanMessage) → end_or_reflect returns END → Graph terminates ``` -------------------------------- ### Troubleshooting: Graph Won't Compile Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/INDEX.md Check these common issues when your graph fails to compile, ensuring both agent graphs are compiled and agents use compatible schemas. ```markdown **Check**: - Both agent graphs are **compiled** (call `.compile()`) - Agents accept `MessagesState` or compatible schema - [See Error Handling](./architecture.md#error-handling) ``` -------------------------------- ### create_reflection_graph Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/INDEX.md Builds a reflection loop by combining a main graph with a reflection graph. It takes compiled graphs and optional state/config schemas as input and returns an uncompiled StateGraph. ```APIDOC ## create_reflection_graph ### Description Builds a reflection loop by combining a main graph with a reflection graph. It takes compiled graphs and optional state/config schemas as input and returns an uncompiled StateGraph. ### Function Signature `create_reflection_graph(graph, reflection, state_schema=None, config_schema=None) -> StateGraph` ### Parameters - **graph**: Compiled main graph. - **reflection**: Compiled reflection graph. - **state_schema** (optional): Schema for the graph state. - **config_schema** (optional): Schema for the graph configuration. ### Returns - **StateGraph**: An uncompiled StateGraph representing the reflection loop. ### Raises - `ValueError`: If the provided state schema is invalid. ``` -------------------------------- ### pyproject.toml Package Metadata Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/package-info.md Configuration file defining package metadata, Python version requirements, and dependencies. ```toml [project] name = "langgraph-reflection" version = "0.0.1" description = "LangGraph agent that runs a reflection step" readme = "README.md" requires-python = ">=3.11" dependencies = [ "langgraph", "mypy>=1.8.0", "langchain>=0.1.0" ] authors = [{name = "Harrison Chase"}] [tool.setuptools.packages.find] where = ["src"] [dependency-groups] dev = [ "langgraph-reflection", ] ``` -------------------------------- ### Routing Decision Scenarios Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/api-reference/end_or_reflect.md Demonstrates various scenarios for the end_or_reflect function, including approval, critique, step limit, and empty messages, showing the expected routing outcome. ```python from langgraph_reflection import end_or_reflect from langchain_core.messages import HumanMessage, AIMessage from langgraph.managed import RemainingSteps # Scenario 1: AI message (approval) - exits state = MessagesWithSteps( messages=[ {"role": "user", "content": "Write code"}, AIMessage(content="Here is the code") ], remaining_steps=RemainingSteps(5) ) result = end_or_reflect(state) assert result == "END" # Approval, exit # Scenario 2: Human message (critique) - loops state = MessagesWithSteps( messages=[ {"role": "user", "content": "Write code"}, AIMessage(content="Here is the code"), HumanMessage(content="Fix the bug on line 5") ], remaining_steps=RemainingSteps(5) ) result = end_or_reflect(state) assert result == "graph" # Critique, retry # Scenario 3: Step limit reached - exits state = MessagesWithSteps( messages=[ {"role": "user", "content": "Query"}, HumanMessage(content="More feedback") ], remaining_steps=RemainingSteps(1) ) result = end_or_reflect(state) assert result == "END" # Not enough steps, exit # Scenario 4: No messages - exits state = MessagesWithSteps( messages=[], remaining_steps=RemainingSteps(5) ) result = end_or_reflect(state) assert result == "END" # Nothing to reflect on ``` -------------------------------- ### create_reflection_graph Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/README.md Constructs an uncompiled reflection graph. This is the primary entry point for creating a reflection-enabled graph. ```APIDOC ## Function: create_reflection_graph ### Description Constructs an uncompiled reflection graph. This is the primary entry point. ### Signature `create_reflection_graph(graph, reflection, state_schema=None, config_schema=None) -> StateGraph` ### Parameters - **graph** (CompiledStateGraph) - The main agent graph. - **reflection** (CompiledStateGraph) - The reflection agent graph. - **state_schema** (optional) - Custom state schema. - **config_schema** (optional) - Custom config schema. ### Returns - Uncompiled `StateGraph` ready for `.compile()` ### Example ```python from langgraph_reflection import create_reflection_graph reflection_graph = create_reflection_graph( graph=main_agent, # CompiledStateGraph reflection=critique_agent, # CompiledStateGraph state_schema=None, # optional custom state config_schema=None # optional config schema ) compiled = reflection_graph.compile() result = compiled.invoke({"messages": [...]}) ``` ``` -------------------------------- ### Troubleshooting: Messages Not Accumulating Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/INDEX.md Ensure messages are correctly accumulated by checking that agents return a dictionary with a "messages" key and that messages are appended. ```markdown **Check**: - Agents return dict with `"messages"` key - Messages are appended, not replaced - [See Pitfall 2](./usage-examples.md#pitfall-2-forgetting-to-return-dict) ``` -------------------------------- ### LangGraph Reflection Imports Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/architecture.md Imports necessary types and classes from typing and LangGraph for building stateful graphs and managing agent steps. ```python from typing import Optional, Type, Any, Literal, get_type_hints from langgraph.graph import END, START, StateGraph, MessagesState from langgraph.graph.state import CompiledStateGraph from langgraph.managed import RemainingSteps from langchain_core.messages import HumanMessage ``` -------------------------------- ### LangGraph Parallel Reflection Agents Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/architecture.md Sets up multiple reflection agents to run in parallel. It defines a `StateGraph` that adds nodes for each reflection agent and a merge node for combining their outputs. ```python # Run multiple reflection agents in parallel parallel_reflection = ( StateGraph(MessagesState) .add_node(reflection1, reflection_agent_1) .add_node(reflection2, reflection_agent_2) .add_node(merge, merge_feedback_nodes) ... ``` -------------------------------- ### Reflection Graph High-Level Flow Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/architecture.md Illustrates the cyclical process involving user input, a main agent, a reflection agent, and a conditional router that determines whether to continue the loop or terminate. ```text ┌─────────────────────────────────────────────────────────┐ │ Reflection Loop │ ├─────────────────────────────────────────────────────────┤ │ │ │ User Input: {"messages": [HumanMessage("Query")]} │ │ ↓ │ │ ┌──────────────────────┐ │ │ │ Main Agent Node │ │ │ │ ("graph") │ │ │ │ │ │ │ │ Generates response │ │ │ │ → Adds AIMessage │ │ │ └──────────┬───────────┘ │ │ ↓ │ │ ┌──────────────────────┐ │ │ │ Reflection Node │ │ │ │ ("reflection") │ │ │ │ │ │ │ │ Evaluates output │ │ │ │ → Returns feedback │ │ │ │ or nothing │ │ │ └──────────┬───────────┘ │ │ ↓ │ │ ┌──────────────────────────┐ [Conditional Router] │ │ │ end_or_reflect() │ ───────────────── │ │ │ │ │ │ │ Decision: │ Checks: │ │ │ - Step limit? │ 1. remaining_steps < 2? │ │ │ - No messages? │ 2. Empty messages? │ │ │ - Last msg Human? │ 3. Last msg Human? │ │ └──────────┬───────────────┘ │ │ ↓ │ │ ┌─────┴──────┐ │ │ │ │ │ │ END "graph" ──→ Loop back to Main Agent │ │ │ │ │ └─ Exit & return final state │ │ │ └─────────────────────────────────────────────────────────┘ ``` -------------------------------- ### Troubleshooting: Custom State Fields Missing Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/INDEX.md If custom state fields are missing, confirm that the result of `create_reflection_graph` is compiled and that the `state_schema` parameter is used correctly. ```markdown **Check**: - Call `.compile()` on result of `create_reflection_graph` - Use `state_schema` parameter for custom schema - [See CustomState Example](./usage-examples.md#example-3-multi-dimensional-evaluation) ``` -------------------------------- ### Implementing Robust Agent Function Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/architecture.md Shows how to implement an agent function that includes a try-except block to gracefully handle exceptions during model invocation, returning an error message as a HumanMessage if an issue occurs. ```python def robust_agent(state): try: result = model.invoke(state["messages"]) except Exception as e: result = HumanMessage(content=f"Error: {e}") return {"messages": result} ``` -------------------------------- ### Unit Test Graph Creation Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/architecture.md Tests the creation and compilation of the reflection graph using `create_reflection_graph`. Invokes the compiled graph and asserts the structure of the result. ```python def test_graph_creation(): main = build_test_agent() reflection = build_test_reflection() app = create_reflection_graph(main, reflection).compile() result = app.invoke({"messages": [{"role": "user", "content": "test"}]}) assert "messages" in result assert len(result["messages"]) > 0 ``` -------------------------------- ### Usage in Reflection Graph Nodes Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/api-reference/MessagesWithSteps.md Illustrates how nodes within a reflection graph receive and utilize the MessagesWithSteps state. ```APIDOC ## Example: In Reflection Graph Nodes ### Description This example shows how nodes within a reflection graph are typed with `MessagesWithSteps` and can access its fields. ### Code ```python from langgraph_reflection import create_reflection_graph, MessagesWithSteps from langgraph.graph import StateGraph, MessagesState, START, END def my_node(state: MessagesWithSteps): # Nodes in the reflection graph receive MessagesWithSteps num_messages = len(state["messages"]) steps_left = state["remaining_steps"] if steps_left < 2: print("Approaching step limit") return {"messages": state["messages"] + [{"role": "assistant", "content": "..."}]} # This state is used internally when you create a reflection graph main_agent = ( StateGraph(MessagesState) .add_node(my_node) .add_edge(START, "my_node") .add_edge("my_node", END) .compile() ) ``` ``` -------------------------------- ### Runtime Error Handling Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/architecture.md Demonstrates catching general exceptions that may occur during the invocation of a reflection graph, which could originate from the main agent, reflection agent, or underlying model calls. ```python try: result = reflection_app.invoke({"messages": [...]}) except Exception as e: # Could be raised by main agent, reflection agent, or model calls pass ``` -------------------------------- ### Type Hinting in Nodes Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/api-reference/MessagesWithSteps.md Explains how to use `MessagesWithSteps` for type hinting in reflection graph nodes. ```APIDOC ## Type Hints ### Description When defining nodes that will run inside a reflection graph, you can type-hint with `MessagesWithSteps` to ensure IDE autocomplete and type checking know about the `remaining_steps` field. ### Code ```python def reflection_node(state: MessagesWithSteps) -> dict: # Type checker knows about state["remaining_steps"] if state["remaining_steps"] < 2: # Handle step limit pass return {} ``` ``` -------------------------------- ### Create Reflection Graph Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/README.md Use `create_reflection_graph` to construct an uncompiled reflection graph. This function takes two compiled LangGraph graphs (one for the main agent and one for reflection) and optional state/config schemas. The output is an uncompiled `StateGraph` ready for compilation. ```python from langgraph_reflection import create_reflection_graph reflection_graph = create_reflection_graph( graph=main_agent, # CompiledStateGraph reflection=critique_agent, # CompiledStateGraph state_schema=None, # optional custom state config_schema=None # optional config schema ) compiled = reflection_graph.compile() result = compiled.invoke({"messages": [...]}) ``` -------------------------------- ### LLM-as-Judge Simple Reflection Graph Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/usage-examples.md Demonstrates a basic reflection system where an LLM judges another LLM's response. The `judge_response` function returns `None` for approval or feedback for revision. The loop continues until the judge approves or a step limit is reached. ```python from langgraph_reflection import create_reflection_graph from langgraph.graph import StateGraph, MessagesState, START, END from langchain.chat_models import init_chat_model from langchain_core.messages import HumanMessage, AIMessage # Step 1: Main agent that generates responses def generate_response(state): """Call an LLM to generate a response to the user query.""" model = init_chat_model(model="gpt-4") response = model.invoke(state["messages"]) return {"messages": response} # Step 2: Build the main agent graph assistant_graph = ( StateGraph(MessagesState) .add_node("generate", generate_response) .add_edge(START, "generate") .add_edge("generate", END) .compile() ) # Step 3: Reflection agent that judges the response def judge_response(state, config): """Judge the main agent's response and provide feedback if needed.""" judge_model = init_chat_model(model="gpt-4-turbo") # Create a prompt that asks the judge to evaluate judge_prompt = """You are an expert evaluator. Look at the assistant's latest response. Is it: 1. Accurate and factually correct? 2. Complete and fully addressing the user's question? 3. Clear and well-structured? 4. Helpful and actionable? If the response is excellent on all criteria, return: {"approved": true} Otherwise, provide specific feedback on what to improve.""" # Extract the assistant's response messages_for_judge = [ {"role": "system", "content": judge_prompt}, *state["messages"] ] judge_result = judge_model.invoke(messages_for_judge) # Parse the judge's decision if "approved" in judge_result.content.lower(): # Judge approved, exit the loop return None else: # Judge found issues, return feedback feedback = judge_result.content return {"messages": [HumanMessage(content=f"The judge found issues:\n{feedback}\n\nPlease revise.")]} # Step 4: Build the judge/reflection graph judge_graph = ( StateGraph(MessagesState) .add_node("judge", judge_response) .add_edge(START, "judge") .add_edge("judge", END) .compile() ) # Step 5: Create the reflection graph combining both reflection_app = create_reflection_graph(assistant_graph, judge_graph).compile() # Step 6: Run it! if __name__ == "__main__": query = "Explain quantum entanglement in simple terms" result = reflection_app.invoke({"messages": [{"role": "user", "content": query}]}) print("Final response:", result["messages"][-1].content) ``` -------------------------------- ### Import MessagesWithSteps State Schema Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/INDEX.md Imports the custom state schema used for tracking messages and remaining steps in reflection loops. ```python from langgraph_reflection import MessagesWithSteps ``` -------------------------------- ### Build Reflection Graph with Custom Schema Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/types.md Function to construct a reflection graph using `create_reflection_graph`, allowing for an optional custom state schema. ```python from langgraph_reflection import create_reflection_graph, MessagesWithSteps from langgraph.graph import StateGraph, MessagesState, START, END, CompiledStateGraph from langchain_core.messages import HumanMessage, AIMessage def build_reflection_graph( main_agent: CompiledStateGraph, reflection_agent: CompiledStateGraph, custom_schema: type = None ) -> StateGraph: """Build a reflection graph with optional custom state.""" return create_reflection_graph(main_agent, reflection_agent, state_schema=custom_schema) ``` -------------------------------- ### Create Reflection Graph in Python Source: https://github.com/langchain-ai/langgraph-reflection/blob/main/_autodocs/architecture.md Defines a function to construct a reflection graph. It validates the state schema, dynamically adds a 'remaining_steps' field, and sets up the graph's nodes and edges for sequential and conditional execution. Use this to build a graph that incorporates a reflection step. ```python def create_reflection_graph( graph: CompiledStateGraph, reflection: CompiledStateGraph, state_schema: Optional[Type[Any]] = None, config_schema: Optional[Type[Any]] = None, ) -> StateGraph: _state_schema = state_schema or graph.builder.schema if "remaining_steps" in _state_schema.__annotations__: raise ValueError( "Has key 'remaining_steps' in state_schema, this shadows a built in key" ) if "messages" not in _state_schema.__annotations__: raise ValueError("Missing required key 'messages' in state_schema") class StateSchema(_state_schema): remaining_steps: RemainingSteps rgraph = StateGraph(StateSchema, config_schema=config_schema) rgraph.add_node("graph", graph) rgraph.add_node("reflection", reflection) rgraph.add_edge(START, "graph") rgraph.add_edge("graph", "reflection") rgraph.add_conditional_edges("reflection", end_or_reflect) return rgraph ```