大数跨境

使用 LangGraph 构建 AI 智能体(2026 版):分步指南

使用 LangGraph 构建 AI 智能体(2026 版):分步指南 AI科技在线
2026-03-20
5
导读:在过去的两年里,LangGraph 已经成为在 AI 领域构建几乎所有智能体项目的核心。


图片

在过去的两年里,LangGraph 已经成为我在 AI 领域构建几乎所有项目的核心。无论是聊天机器人、MCP 助手、语音机器人,还是内部自动化智能体——只要涉及推理、工具或多步骤工作流程,我可能都是用 LangGraph 构建的。它是我客户项目、个人实验,甚至日常生产系统中反复使用的技术栈。

LangGraph 不断进化,生态系统日趋成熟,我构建智能体的方式也发生了显著变化。因此,我觉得是时候写一篇更新指南了——一篇反映 LangGraph 现在工作方式的文章,而不是一年多前的工作方式。

在深入探讨新的模式和更简洁的 2025 API 之前,让我们先回顾一下 LangGraph 存在的初衷。

什么是 LangGraph?

LangGraph 是建立在 LangChain 之上的一个库,专注于 LLM 应用程序的显式控制流。LangGraph 不是将应用程序构建为线性流水线,而是将其建模为一个图,执行可以在其中分支、循环和回溯到之前的步骤。

传统的 LangChain 工作流通常是有向无环图(DAG):它们向前移动并终止。这对于许多用例已经足够,但一旦你想要能够迭代、重新评估中间结果或动态决定下一步做什么的系统,它就开始变得局限。许多真实的智能体需要循环、重试,或根据结果调整行为,而不是遵循固定的序列。

LangGraph 通过允许图中的循环来解决这个问题。节点可以被重新访问,决策可以被重复做出,控制流被显式处理,而不是嵌入在提示词中。这使得构建能够规划、行动、观察结果并持续运行直到满足停止条件的智能体成为可能。

图片

LangGraph:节点、状态和边。

从概念上讲,LangGraph 围绕一小部分核心抽象构建。智能体被定义为一个图,其中所有步骤共享和更新一个共同的状态。

理解状态节点就足以理解 LangGraph 的工作原理。

状态 —— 智能体的记忆

状态是流经图的数据结构。每个节点接收当前状态并可以返回对它的更新。

你可以把状态想象成智能体的累积上下文:消息、决策、工具输出、中间结果,以及任何需要在步骤之间持久化的其他信息。因为状态是显式向前携带的,每个节点都可以访问迄今为止发生的所有内容,而不依赖于隐式的提示历史。

节点 —— 专注的行为单元

节点是图的可执行单元。每个节点代表一个单一的、定义良好的操作,例如:

  • • 调用 LLM
  • • 调用工具或 API
  • • 转换或验证数据
  • • 做出路由决策

在实践中,当节点保持小而专注时,LangGraph 效果最好。只做一件事的节点更容易测试、推理和修改,随着智能体的演进而独立变化。

边 —— 控制流

边定义执行如何从一个节点移动到下一个节点。它们编码了智能体的控制流,可以是:

  • • 顺序的(总是移动到下一个节点)
  • • 条件性的(根据状态选择下一个节点)
  • • 循环的(返回到前一个节点)

通过显式定义边,LangGraph 使控制流在图本身中可见,而不是将其隐藏在提示逻辑中。这使得更容易理解智能体何时循环、何时分叉以及何时终止。

有了这些核心概念,我们就可以从理论转向具体示例。在下一节中,我们将逐步构建一个基于 Strava 的训练智能体,使用状态、节点和边来建模一个能够根据实际训练数据自动适应的工作流程。

分步指南

从你想要自动化的流程开始

想象一下,你想要构建一个作为你的个人 Strava 驱动训练操作员的 AI 智能体。你有一个明确的目标(例如,即将到来的比赛),一个训练约束(例如,每周 3 次训练),并且你希望你的计划能够根据你实际所做的自动适应。

该智能体应该:

  • • 连接到你的 Strava 账户并读取你最近的活动(跑步、越野跑……)
  • • 理解你的目标(比赛距离/日期,目标配速/完赛目标,海拔剖面)
  • • 生成简洁的一周计划,尊重进展上限和减量训练。
  • • 比较计划与完成的工作以发现错过/额外/高强度的训练和过载风险。
  • • 调整即将到来的一周当出现风险标志时,解释什么发生了变化以及为什么。
  • • 通过电子邮件发送计划当 SMTP 设置时,或在日志/终端中预览(如果未设置)。

要在 LangGraph 中实现一个智能体,你通常会遵循相同的五个步骤。

第 1 步:将你的工作流程映射为离散步骤

我们首先将想要自动化的过程分解为清晰的、离散的步骤。每个步骤成为一个节点:一个具有单一、定义良好职责的小函数。一旦确定了这些步骤,我们就可以连接它们来描述智能体的整体流程。

下图显示了这些节点如何适应 Strava 训练智能体工作流程。


图片

第 2 步:确定每个步骤需要做什么

现在我们有了工作流程,让我们确定图中的每个节点负责什么,以及它需要什么才能正确完成其工作。

对于每个步骤,我们将决定:

  • • 它是什么类型的操作
  • • 它需要什么上下文(静态 vs 动态)
  • • 它应该产生什么作为输出

因为这个智能体完全自动运行并且只发送每周电子邮件,我们不包含任何用户输入或人在回路中的步骤。

图片

节点类型(LangGraph 教程)

数据步骤

每当我们需要从外部系统检索信息时,就会使用数据步骤。

同步 Strava 活动

让我们从引入原始训练数据开始。

  • • 此步骤做什么: 获取最近约 90 天的 Strava 活动。
  • • 它需要的上下文: 通过访问令牌的 Strava 身份验证以及客户端 ID/密钥。
  • • 期望的结果: 包含我们稍后将使用的指标(日期、持续时间、距离、配速、海拔、活动类型)的最近活动列表。

LLM 步骤

当智能体需要分析数据、权衡利弊或生成人类可读的输出时,我们会使用 LLM 步骤。

总结近期训练

接下来,让我们将原始活动日志转化为有意义的信号。

  • • 此步骤做什么: 将活动聚合为更高级别的训练指标,例如每周训练量、强度训练次数、长时间跑持续时间和一致性。
  • • 它需要的上下文: 来自 Strava 的近期活动,基本定义(什么算作强度训练、长跑、每周窗口)
  • • 期望的结果: 可用于推理和决策的近期训练的结构化摘要。

评估进展与目标

现在我们评估进展情况。

  • • 此步骤做什么: 将近期训练信号与用户的目标和约束进行比较,以确定整体状态。
  • • 它需要的上下文: 训练摘要,目标定义(比赛日期、距离、海拔、目标努力程度),约束(例如每周 3 次训练),风险启发式(负荷峰值、强度累积)。
  • • 期望的结果: 关于训练状态(步入正轨/落后/过载)的结构化评估、置信度分数、风险标志、推荐策略(保持、调整、减量)。

生成下周计划

现在我们生成实际计划。

  • • 此步骤做什么: 生成一周的训练安排(以公里计),尊重训练次数和进展上限,基于你的目标和近期训练。
  • • 它需要的上下文: 目标(比赛/日期/距离/海拔)、每周训练次数,以及近期训练摘要(训练量、强度信号)。
  • • 期望的结果: 即将到来一周的结构化计划(包含日期、描述、持续时间、强度的训练),以及捕获的原始生成计划用于下游比较/调整。

调整计划并添加警告

如果检测到风险,我们需要清楚地显示它们并相应地调整训练方案。

  • • 此步骤做什么: 必要时修改计划,并在检测到过载或不一致时生成简洁的警告或注意事项。
  • • 它需要的上下文: 风险标志、训练计划草稿。
  • • 期望的结果: 最终计划以及用户应该注意的简短警告列表。

撰写每周电子邮件

最后,让我们把一切都变成可读的内容。

  • • 此步骤做什么: 生成清晰的每周电子邮件,包括训练计划、简要理由以及任何警告或风险。
  • • 它需要的上下文: 最终训练计划、关键摘要信号、警告(如果有)
  • • 期望的结果: 准备发送的每周电子邮件(主题 + 正文)。

操作步骤

当智能体需要与外部世界交互时,我们会使用操作步骤。

发送电子邮件

让我们通过交付结果来闭合循环。

  • • 此步骤做什么: 向用户发送每周训练电子邮件。
  • • 它需要的上下文: 收件人电子邮件地址、电子邮件主题和正文
  • • 期望的结果: 电子邮件成功发送并记录在案。

现在我们已将步骤分类为 LLM数据操作步骤,我们知道了图中每个节点负责什么工作。

下一个问题同样重要:这些节点如何共享信息?

为了回答这个问题,我们需要设计智能体的状态——允许每个步骤建立在先前工作基础上的共享内存。

第 3 步:设计你的状态

既然我们知道了每个步骤做什么,我们需要决定这些步骤如何共享信息。状态是智能体的共享内存:它是节点存储它们检索、计算或决定的内容的地方,以便下游步骤可以建立在它之上。

在决定什么属于状态时,我们遵循两个简单的规则。如果一条信息需要在多个步骤之间持久化,它应该存储在状态中。如果相同的信息可以从现有数据中重新推导出来,我们就避免存储它,而是在需要时计算它。

对于我们的 Strava 训练智能体,我们需要跟踪:

  • • 原始 Strava 活动: 这些无法在以后重建,并且被多个步骤重复使用。
  • • 训练摘要: 聚合的信号,如每周训练量、强度训练次数和长时间跑持续时间。
  • • 目标和约束: 静态输入,如比赛日期、距离和每周训练次数。
  • • 评估结果: 智能体对进展、置信度和风险标志的评估,这些会驱动下游决策。
  • • 生成的训练计划: 将发送给用户的下周计划。
  • • 执行元数据: 用于调试和恢复的时间戳和标识符。

让我们定义我们的状态:


   
   
   
    
   
   
   from typing import TypedDict, Literal, List, Dict

class
 TrainingEvaluation(TypedDict):
    status: Literal["on_track", "behind", "overloaded"]
    confidence: float
    risk_flags: List[str]
    recommendation: Literal["keep", "adjust", "deload"]

class
 TrainingSession(TypedDict):
    day: str
    description: str
    duration_min: int
    intensity: Literal["easy", "moderate", "hard"]

class
 StravaTrainingAgentState(TypedDict):
    # Raw Strava data

    activities: List[Dict] | None
    # Aggregated training signals

    training_summary: Dict | None
    # Goal and constraints

    goal: Dict
    sessions_per_week: int
    # Evaluation output

    evaluation: TrainingEvaluation | None
    # Generated plan

    next_week_plan: List[TrainingSession] | None
    # Generated communication

    weekly_email: str | None
    # Execution metadata

    run_id: str
    last_sync_timestamp: str

请注意,状态只包含原始或结构化的数据。每个节点从这个共享状态读取,做一个特定的工作,并以结构化形式写回其结果。

第 4 步:构建你的节点

有了工作流程和状态,我们可以开始将每个步骤转化为代码。在 LangGraph 中,一个节点只不过是一个 Python 函数:它将当前状态作为输入,并返回它想要更新的字段。这种简单性是刻意的——它让焦点保持在数据如何流经系统,而不是框架特定的细节。

所有节点的完整实现可在 GitHub 仓库中找到。在这篇文章中,我们将重点放在最重要的一个:生成下周计划

为了使示例易于理解,我们在 ChatOpenAI 周围使用了一个最小的包装器。这个包装器只是集中了 LLM 调用,使节点逻辑保持干净。


   
   
   
    
   
   
   from dataclasses import dataclass
from
 langchain_openai import ChatOpenAI
from
 langchain_core.messages import SystemMessage, HumanMessage

@dataclass

class
 LLMService:
    model: str = "gpt-4o-mini"
    temperature: float = 0.1

    def
 __post_init__(self) -> None:
        self
.client = ChatOpenAI(model=self.model, temperature=self.temperature)

    def
 structured_completion(self, system: str, user: str) -> str:
        return
 self.client.invoke(
            [SystemMessage(content=system), HumanMessage(content=user)]
        ).content

generate_next_week_plan 节点是智能体实际"智能"所在的位置。图中的所有早期内容都准备输入——同步 Strava、总结训练、评估进展。所有后期内容都完善或传达结果。这个节点的责任很简单:给定当前状态,生成一个尊重所选策略和约束的一周训练计划。

这个节点完全是状态驱动的。它读取运动员的目标、近期训练的简短摘要、当前建议(keepadjust 或 deload)以及每周训练次数。不需要额外的上下文。

系统提示将模型锚定为跑步教练并编码护栏:只返回结构化的 JSON,尊重请求的训练次数,除非减量训练否则限制进展在 +10%,并保持描述简洁。用户提示从状态中注入实际上下文。


   
   
   
    
   
   
   def generate_next_week_plan(state: StravaTrainingAgentState) -> dict:
    """LangGraph node: generate next week's training plan."""

    llm: LLMService = _get_service("llm")
    goal = state.get("goal", {})
    summary = state.get("training_summary", {})
    sessions = state.get("sessions_per_week", 3)
    recommendation = (state.get("evaluation") or {}).get("recommendation", "adjust")

    system_prompt = (
        "You are a running coach. Return ONLY valid JSON: "

        "a list of sessions with fields: day (Mon-Sun), description, "

        "duration_min, intensity (easy|moderate|hard). "

        "Respect sessions_per_week exactly. Cap progression at +10% unless deloading (20–30% down)."

    )

    user_prompt = (
        f"Goal: {json.dumps(goal)}\n"

        f"Recent summary: {json.dumps(summary)}\n"

        f"Recommendation: {recommendation}\n"

        f"Sessions per week: {sessions}"

    )

    plan = llm.structured_completion(system_prompt, user_prompt)
    return
 {"next_week_plan": plan}

第 5 步:将它们连接在一起

实现了所有节点后,最后一步是将它们连接成一个可工作的 LangGraph 工作流程。这是智能体的控制流变得显式的地方:我们定义下一个运行哪个节点、图在哪里分支以及何时停止。

我们首先用状态模式创建一个 StateGraph 并注册每个节点:


   
   
   
    
   
   
   # Initiat graph
graph = StateGraph(StravaTrainingAgentState)

# Add nodes

graph.add_node("sync_strava_activities", sync_strava_activities)
graph.add_node("summarize_recent_training", summarize_recent_training)
graph.add_node("evaluate_progress_vs_goal", evaluate_progress_vs_goal)
graph.add_node("generate_next_week_plan", generate_next_week_plan)
graph.add_node("adjust_plan_add_warnings", adjust_plan_add_warnings)
graph.add_node("compose_weekly_email", compose_weekly_email)
graph.add_node("send_email", send_email)

接下来,我们添加定义执行如何流经图的边。大多数边是简单且顺序的:一个节点总是跟随另一个。

关键部分是 generate_next_week_plan 之后的条件边。此时智能体已经生成了一个计划,但我们并不总是想以相同的方式对待它。如果评估说我们步入正轨(keep),我们可以立即发布。如果建议是 adjust 或 deload,我们通过一个可以软化计划并附加警告的额外节点进行路由。

在 LangGraph 中,add_conditional_edges 接受:

  1. 1. 我们分支自的节点,
  2. 2. 返回一个键的路由函数,
  3. 3. 从该键到下一个节点的映射。

这里路由函数只是从状态中读取建议:


   
   
   
    
   
   
   # Add edges
graph.add_edge(START, "sync_strava_activities")
graph.add_edge("sync_strava_activities", "summarize_recent_training")
graph.add_edge("summarize_recent_training", "evaluate_progress_vs_goal")
graph.add_edge("evaluate_progress_vs_goal", "generate_next_week_plan")

graph.add_conditional_edges(
    "generate_next_week_plan"
,
    lambda
 state: state.get("evaluation", {}).get("recommendation", "adjust"),
    {
        "keep"
: "compose_weekly_email",
        "adjust"
: "adjust_plan_add_warnings",
        "deload"
: "adjust_plan_add_warnings",
    },
)

graph.add_edge("adjust_plan_add_warnings", "compose_weekly_email")
graph.add_edge("compose_weekly_email", "send_email")
graph.add_edge("send_email", END)

# Compile graph

app = graph.compile()

最后,我们连接剩余的节点并编译图。

第 6 步:测试智能体

要在本地测试完整的智能体,首先克隆 GitHub 仓库并按照 README 中的设置说明进行操作。创建(或激活)虚拟环境,安装依赖项,并在 .env 文件中配置所需的 Strava 和 OpenAI 凭据后,你可以用单个命令运行智能体:


   
   
   
    
   
   
   python strava_training_agent.py

每次运行时,智能体都会获取你最近的 Strava 活动,总结你的训练,为下周生成计划,并撰写每周电子邮件。

配置 SMTP 是可选的。如果未设置与电子邮件相关的环境变量,智能体将简单打印并记录电子邮件预览,而不是发送它。这使得在不预先设置电子邮件基础设施的情况下轻松端到端测试整个工作流程变得容易。

自动运行

一旦智能体在本地工作,下一个问题是如何自动运行它。因为这个工作流程只需要每周执行一次,所以不需要始终在线的基础设施。

对于个人项目和教程,GitHub Actions 通常是最简单的选项。这个仓库包含一个 weekly-agent.yml 工作流程,它使用 cron 触发器调度智能体,并运行你在本地使用的相同脚本。Strava 和 OpenAI 凭据(以及可选的 SMTP 凭据)存储为加密的 GitHub Secrets,GitHub 负责执行和日志记录。设置工作量小、可靠,其他人也很容易复制。

最终想法

本教程的目标不是构建尽可能复杂的训练系统,而是展示 LangGraph 如何帮助构建显式、可测试且易于推理的智能体工作流程。

通过将问题建模为图——具有共享状态、小而专注的节点和明确定义的控制流——你最终会得到一个行为可见且可预测的智能体,即使它适应不断变化的输入。同样的模式很好地超越了这个 Strava 示例:客户支持智能体、数据分析助手、内部工具,或任何需要推理、行动和循环的系统。

还有一些明显的方向可以改进智能体本身。在本教程中,我们故意保持提示简单以专注于架构。在提示设计上投入更多时间——通过添加更丰富的教练背景、更清晰的进展规则、恢复启发式或运动特定知识——已经可以在不改变图的情况下显著带来更好的训练计划。一旦工作流程到位,提示通常是杠杆最高的改进。

从那里,你可以用用户反馈循环扩展智能体,跨训练模块的更长期记忆,额外的数据来源如睡眠或心率变异性,或更严格的安全检查,当风险信号累积时停止进展。

关键要点是这些改进是渐进的。如果你能够将问题分解为节点,仔细定义状态,并有意识地连接图,你就已经有了一个坚实的基础,可以使用 LangGraph 构建健壮、自适应的智能体。

参考https://ai.gopubby.com/building-ai-agents-with-langgraph-2026-edition-a-step-by-step-guide-494d36e801f9

来源:机器之魂


【声明】内容源于网络
0
0
AI科技在线
1234
内容 1272
粉丝 0
AI科技在线 1234
总阅读7.9k
粉丝0
内容1.3k