3.6 KiB
3.6 KiB
Edge
Control flow that defines transitions between nodes.
Overview
Edges determine "what to do next". Nodes perform processing, and edges dictate the next action.
Types of Edges
1. Normal Edges (Fixed Transitions)
Always transition to a specific node:
from langgraph.graph import START, END
# From START to node_a
builder.add_edge(START, "node_a")
# From node_a to node_b
builder.add_edge("node_a", "node_b")
# From node_b to end
builder.add_edge("node_b", END)
2. Conditional Edges (Dynamic Transitions)
Determine the destination based on state:
from typing import Literal
def should_continue(state: State) -> Literal["continue", "end"]:
if state["iteration"] < state["max_iterations"]:
return "continue"
return "end"
# Add conditional edge
builder.add_conditional_edges(
"agent",
should_continue,
{
"continue": "tools", # Go to tools if continue
"end": END # End if end
}
)
3. Entry Points
Define the starting point of the graph:
# Simple entry
builder.add_edge(START, "first_node")
# Conditional entry
builder.add_conditional_edges(
START,
route_start,
{
"path_a": "node_a",
"path_b": "node_b"
}
)
Parallel Execution
Nodes with multiple outgoing edges will have all destination nodes execute in parallel in the next step:
# From node_a to multiple nodes
builder.add_edge("node_a", "node_b")
builder.add_edge("node_a", "node_c")
# node_b and node_c execute in parallel
To aggregate results from parallel execution, use a Reducer:
from operator import add
class State(TypedDict):
results: Annotated[list, add] # Aggregate results from multiple nodes
Edge Control with Command
Specify the next destination from within a node:
from langgraph.types import Command
def smart_node(state: State) -> Command:
result = analyze(state["data"])
if result["confidence"] > 0.8:
return Command(
update={"result": result},
goto="finalize"
)
else:
return Command(
update={"result": result, "needs_review": True},
goto="human_review"
)
Conditional Branching Implementation Patterns
Pattern 1: Tool Call Loop
def should_continue(state: State) -> Literal["continue", "end"]:
messages = state["messages"]
last_message = messages[-1]
# Continue if there are tool calls
if last_message.tool_calls:
return "continue"
return "end"
builder.add_conditional_edges(
"agent",
should_continue,
{
"continue": "tools",
"end": END
}
)
Pattern 2: Routing
def route_query(state: State) -> Literal["search", "calculate", "general"]:
query = state["query"]
if "calculate" in query or "+" in query:
return "calculate"
elif "search" in query:
return "search"
return "general"
builder.add_conditional_edges(
"router",
route_query,
{
"search": "search_node",
"calculate": "calculator_node",
"general": "general_node"
}
)
Important Principles
- Explicit Control Flow: Transitions should be transparent and traceable
- Type Safety: Explicitly specify destinations with Literal
- Leverage Parallel Execution: Execute independent tasks in parallel
Related Pages
- 01_core_concepts_node.md - Node implementation
- 02_graph_architecture_routing.md - Routing patterns
- 05_advanced_features_map_reduce.md - Parallel processing patterns