惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - 时空穿越者

java并发:深入解析 ThreadPoolExecutor.addWorker() 流水线技术解析:处理器重排序的硬件基础 java并发:synchronized 揭秘 java并发:管道流(Piped Streams)的应用场景 java并发:再次认识一下Java中的锁 —— 类级别的锁是否存在? Spring异步机制:@Async Spring BeanDefinition Spring Resource Spring之ApplicationContext Spring之BeanFactory:解析getBean()方法 Spring之IoC容器 Spring的整体架构 Spring Data JPA:解析CriteriaQuery Spring Data JPA:解析CriteriaBuilder Spring Data JPA:解析JpaSpecificationExecutor & Specification Spring Data JPA:解析SimpleJpaRepository java并发:线程池之Executors(ScheduledExecutorService篇) - 时空穿越者 java并发:线程池之饱和策略 java并发:线程池之ThreadPoolExecutor
LangGraph:add_conditional_edges详解
时空穿越者 · 2025-11-30 · via 博客园 - 时空穿越者

在 LangGraph 中,add_conditional_edges 是构建动态工作流的关键,用于创建基于条件判断的分支路径;它允许工作流根据当前状态动态决定下一步的执行路径,这种模式使 LangGraph 能够处理复杂的、状态驱动的对话流程,特别是在需要工具调用和多次交互的场景中。

示例

    # State Management
    class State(TypedDict):
        messages: Annotated[List[AnyMessage], add_messages]
​
    # Nodes
    def chat_node(state: State) -> State:
        state["messages"] = chat_llm.invoke({"messages": state["messages"]})
        return state
​
    # Building the graph
    graph_builder = StateGraph(State)
    graph_builder.add_node("chat_node", chat_node)
    graph_builder.add_node("tool_node", ToolNode(tools=tools))
    graph_builder.add_edge(START, "chat_node")
    graph_builder.add_conditional_edges("chat_node", tools_condition, {"tools": "tool_node", "__end__": END})
    graph_builder.add_edge("tool_node", "chat_node")
    graph = graph_builder.compile(checkpointer=MemorySaver())
    return graph

解读:

上述示例的执行流程如下:

image

细节描述

执行工具节点

class ToolNode:
    def __init__(self, tools):
        self.tools = tools
    
    def __call__(self, state: State) -> State:
        # 执行工具调用
        tool_results = []
        for tool_call in state["messages"][-1].tool_calls:
            tool = self.tools[tool_call["name"]]
            result = tool.invoke(tool_call["args"])
            tool_results.append(result)
        
        return {"messages": tool_results}

状态更新:将工具执行结果作为新消息添加

工具节点执行后,通过 graph_builder.add_edge("tool_node", "chat_node") 返回聊天节点继续生成对工具结果的响应

重点关注

add_conditional_edges,这个方法包含三个核心参数

image

A、源节点:条件分支的起点
B、条件函数:决定分支路径的函数
C、分支映射:将条件函数返回值映射到目标节点的字典

条件函数

条件函数是一个自定义函数,它接收当前状态作为输入,返回一个字符串值,表示下一步应该执行的路径。

在上面示例中,tools_condition 函数可能类似这样:

def tools_condition(state: State) -> str:
    """判断是否需要调用工具"""
    # 获取最后一条消息
    last_message = state["messages"][-1]
    
    # 检查是否是工具调用请求
    if hasattr(last_message, "tool_calls") and last_message.tool_calls:
        return "tools"  # 需要调用工具
    else:
        return "__end__"  # 结束对话

tools_condition(LangGraph源码)

image

image

def tools_condition(
    state: list[AnyMessage] | dict[str, Any] | BaseModel,
    messages_key: str = "messages",
) -> Literal["tools", "__end__"]:
    """Conditional routing function for tool-calling workflows.

    This utility function implements the standard conditional logic for ReAct-style
    agents: if the last `AIMessage` contains tool calls, route to the tool execution
    node; otherwise, end the workflow. This pattern is fundamental to most tool-calling
    agent architectures.

    The function handles multiple state formats commonly used in LangGraph applications,
    making it flexible for different graph designs while maintaining consistent behavior.

    Args:
        state: The current graph state to examine for tool calls. Supported formats:
            - Dictionary containing a messages key (for `StateGraph`)
            - `BaseModel` instance with a messages attribute
        messages_key: The key or attribute name containing the message list in the state.
            This allows customization for graphs using different state schemas.

    Returns:
        Either `'tools'` if tool calls are present in the last `AIMessage`, or `'__end__'`
            to terminate the workflow. These are the standard routing destinations for
            tool-calling conditional edges.

    Raises:
        ValueError: If no messages can be found in the provided state format.

    Example:
        Basic usage in a ReAct agent:

        ```python
        from langgraph.graph import StateGraph
        from langchain.tools import ToolNode
        from langchain.tools.tool_node import tools_condition
        from typing_extensions import TypedDict


        class State(TypedDict):
            messages: list


        graph = StateGraph(State)
        graph.add_node("llm", call_model)
        graph.add_node("tools", ToolNode([my_tool]))
        graph.add_conditional_edges(
            "llm",
            tools_condition,  # Routes to "tools" or "__end__"
            {"tools": "tools", "__end__": "__end__"},
        )
        ```

        Custom messages key:

        ```python
        def custom_condition(state):
            return tools_condition(state, messages_key="chat_history")
        ```

    !!! note
        This function is designed to work seamlessly with `ToolNode` and standard
        LangGraph patterns. It expects the last message to be an `AIMessage` when
        tool calls are present, which is the standard output format for tool-calling
        language models.
    """
    if isinstance(state, list):
        ai_message = state[-1]
    elif (isinstance(state, dict) and (messages := state.get(messages_key, []))) or (
        messages := getattr(state, messages_key, [])
    ):
        ai_message = messages[-1]
    else:
        msg = f"No messages found in input state to tool_edge: {state}"
        raise ValueError(msg)
    if hasattr(ai_message, "tool_calls") and len(ai_message.tool_calls) > 0:
        return "tools"
    return "__end__"

分支映射

分支映射是一个字典,将条件函数的返回值映射到具体的节点或特殊端点:

{
    "tools": "tool_node",  # 当条件返回 "tools" 时,跳转到 tool_node
    "__end__": END         # 当条件返回 "__end__" 时,结束工作流
}

特殊端点:

  • START:工作流起点
  • END:工作流终点

条件分支的高级应用

多分支条件

可以创建包含多个可能路径的条件分支

def advanced_condition(state: State) -> str:
    last_message = state["messages"][-1]
    
    if "help" in last_message.content:
        return "help_flow"
    elif "purchase" in last_message.content:
        return "checkout_flow"
    elif "cancel" in last_message.content:
        return "cancellation_flow"
    else:
        return "__end__"

graph_builder.add_conditional_edges(
    "chat_node",
    advanced_condition,
    {
        "help_flow": "help_node",
        "checkout_flow": "checkout_node",
        "cancellation_flow": "cancellation_node",
        "__end__": END
    }
)

嵌套条件分支

# 第一层条件分支
graph_builder.add_conditional_edges(
    "initial_node",
    determine_flow_type,
    {"support": "support_flow", "sales": "sales_flow"}
)

# 支持流中的子分支
graph_builder.add_conditional_edges(
    "support_flow",
    support_condition,
    {"technical": "tech_support_node", "billing": "billing_support_node"}
)

# 销售流中的子分支
graph_builder.add_conditional_edges(
    "sales_flow",
    sales_condition,
    {"new": "new_customer_node", "existing": "existing_customer_node"}
)

最佳实践

保持条件函数纯净

只读取状态,不修改状态
避免副作用

明确的返回值

使用描述性的字符串作为返回值
确保返回值在分支映射中有对应项

错误处理

def safe_condition(state: State) -> str:
    try:
        # 业务逻辑
    except Exception as e:
        # 记录错误
        state["errors"].append(str(e))
        return "error_handling"

状态设计

确保状态包含条件判断所需的所有信息
使用清晰的字段命名

扩展阅读

使用Graph API | LangChain 中文文档

image