深入学 LangChain 官方文档(一):总览、安装与快速开始
本篇对应的官方文档
- LangChain overview:支撑 Agent harness 的定位,以及 LangChain 与 LangGraph、Deep Agents、LangSmith 的职责边界。
- Install LangChain:支撑 Python 版本、核心包和独立 provider package 的安装分层。
- LangChain Agents:支撑模型---工具循环、harness 职责和
create_agent的最小组成。- Model Studio OpenAI-compatible access:支撑千问模型通过 OpenAI-compatible API 接入的产品边界。
- Model Studio Base URL:支撑 API key、区域、计费计划与访问地址必须匹配的接入判断。
本篇讲解范围
本篇集中讲清 LangChain 在模型外承担的 harness 职责、安装分层和最小
create_agent闭环;Structured Output、持久化会话、完整 harness 配置与生产观测留给后续文章。
刚开始接触 LangChain 时,很容易把它理解成"另一套大模型调用 SDK"。如果目标只是把一句问题交给模型,再取回一句回答,这种理解甚至不会立刻造成麻烦:供应商 SDK 已经能够完成请求,额外增加框架反而显得绕。
真正的差异会在应用需要"行动"时出现。用户问"北京今天需不需要带伞",模型本身并不知道实时天气。应用必须准备天气工具,让模型判断何时调用,执行查询,把结果送回模型,再拿到最终建议。这里已经不再是一次输入对应一次输出,而是一个可能往返多次的运行过程。
LangChain 当前把这层能力概括得很直接:Agent = Model + Harness 。Model 负责理解和生成,harness 则组织系统约束、工具和执行循环。create_agent 是这套高层入口,本篇就从它开始,完成一次能调用天气工具的最小 Agent。
官方对 Agent 的定义还多了一层重要限定:模型会在循环中调用工具,直到给定任务完成。也就是说,Agent 并不是"调用一次模型时多传了一个 tools 参数",而是允许一次运行经历模型判断、工具执行、结果回填和再次判断。快速开始真正要跑通的,正是这几个阶段之间的交接。

Agent harness 接住的是模型外的运行职责:用户请求以状态进入,系统提示限定行为,模型决定直接回答还是请求工具,工具结果再回到模型,直到产生最终响应。它不会让模型凭空获得天气知识,也不会替后端完成权限和数据校验;它做的是把这些对象放进一条可持续推进的执行链。
本篇只解决系列入口的三个问题:LangChain 在模型外增加了什么;最小环境怎样安装;create_agent 的输入、工具和返回结果怎样连成闭环。Messages 的对象结构、工具调用配对和 Agent 循环细节会在后文分别展开,这里先把代码真正跑到"能够读懂下一篇"的位置。
1. 模型会生成文本,应用还要负责行动
先把问题缩到最小。用户问"用一句话介绍北京",模型可以依据已有知识直接生成答案。应用发起一次调用,等待一次返回,这时独立 Model 已经足够。
换成"根据北京今天的降水概率判断是否带伞",任务就多了一个外部事实。模型不能安全地把"今天的天气"当作静态知识回答,应用至少要完成四件事:
- 告诉模型有哪些工具以及工具需要什么参数。
- 识别模型是准备回答,还是请求调用某个工具。
- 执行工具,并把结果交还给模型继续判断。
- 在模型给出最终答案时结束运行,而不是无限循环。
如果手写这些步骤,当然也能做出来。问题在于,工具一多,代码很快会混入消息历史、参数校验、重试、状态保存和停止条件。业务逻辑原本只想回答"是否带伞",最后却要维护一套通用执行器。
这里需要把"模型作决定"和"应用做事情"分开。模型可以根据工具描述生成一次调用请求,例如选择 get_weather 并给出城市参数;真正的函数仍然运行在应用环境里,能访问哪些数据库、是否允许查询某个用户、请求超时后如何处理,都由后端控制。模型提出行动,不等于模型获得了后端权限。
天气结果返回后,模型也不是直接读取 Python 函数的局部变量。harness 会把工具结果作为新的上下文放回当前运行,模型根据这份结果决定继续调用工具还是给出最终回答。于是,一次 Agent 运行至少存在三种不同性质的工作:模型负责语义判断,工具负责确定性执行,harness 负责让两者按状态往返。把三者混成"模型调用",排错时往往只能看到一句含糊的"Agent 没反应"。

三类对象围绕同一份消息状态协作,却不能互相替代。Model 产出语义判断和结构化行动请求;Tool 在受控后端里执行确定性动作;harness 负责调度、回填和停止条件。尤其要守住右侧的权限边界:模型能提出"查询天气",并不因此拥有数据库、密钥或用户数据的直接访问权。
LangChain 的价值不是替模型思考,而是把这套执行器抽成可组合的 harness。开发者仍然决定使用哪个模型、开放哪些工具、系统约束是什么;create_agent 负责让这些对象按照 Agent 运行方式协作。
因此,"要不要使用 LangChain"不该按项目大小判断,而应该按运行形态判断:
| 任务形态 | 更直接的入口 | 原因 |
|---|---|---|
| 单次翻译、摘要、分类 | 独立 Model | 一次输入就能得到业务需要的结果 |
| 模型需要自主选择工具 | LangChain Agent | 需要管理模型与工具之间的往返 |
| 流程由固定业务规则决定 | 普通代码或确定性工作流 | 不必把明确规则交给模型选择 |
| 确定性步骤与 Agent 决策深度交织 | LangGraph | 需要更低层的图、状态和恢复控制 |
还可以用一个更具体的变化来检验边界。用户已经把"北京,小雨,降水概率 70%"完整放进输入时,Model 直接判断即可;应用规定"降水概率大于 60% 就提示带伞"时,普通条件判断更稳定;只有当模型需要先理解用户意图,再从多个工具中选择天气查询,并根据结果组织自然语言建议时,Agent harness 才承担了无法由一次模型调用或一条固定规则替代的职责。

入口选择的关键不在项目大小,而在任务中有没有必须由模型完成的动态决策。输入事实齐全时,独立 Model 足够;规则能够提前穷举时,确定性工作流更稳;只有"理解意图---选择工具---读取结果---继续判断"无法在调用前写死时,Agent 循环才带来不可替代的价值。
因此,引入 Agent 并不会自动让回答更准确。它增加的是行动空间,同时也增加了工具选错、参数错误、外部服务失败和循环终止等新的检查点。项目是否值得使用 LangChain,要看这些动态决策是否真实存在,而不是看"Agent"这个名称是否更像完整产品。
边界明确以后,下一步才是看 LangChain 在整个生态中处于哪一层,否则很容易把名字相近的产品当成互相替代的框架。
2. 四个相邻入口各管一层
官方总览把几个常见入口放在一起介绍,但它们解决的问题不同。
LangChain 提供高层 Agent harness。开发者把 model、tools、prompt 和 middleware 组合起来,用较少代码建立可定制的 Agent。
LangGraph 是更低层的编排框架。LangChain Agent 本身构建在 LangGraph 之上,因此能够利用持久执行、人机协作和状态能力;当应用需要显式控制节点、分支、恢复和状态图时,才有必要直接进入这一层。
Deep Agents 更接近"带齐常用能力的 Agent"。它在 LangChain Agent 之上提供长任务、上下文压缩、虚拟文件系统和子 Agent 等能力。它适合需要现成复杂能力的场景,不代表所有项目都应该从最重的入口开始。
LangSmith 负责 trace、debug 和 evaluate。它观察一次运行经过了哪些模型和工具、耗时在哪里、输出质量如何,但不参与本地 Agent 是否能够完成最小调用。
选择入口时,可以先问"我需要控制哪一层"。只想把模型、工具和系统约束组成一个可扩展 Agent,停在 create_agent;业务要求把确定性节点、条件分支和 Agent 决策编排成显式状态图,再直接使用 LangGraph;任务天然很长,并且确实需要上下文压缩、虚拟文件系统或子 Agent,才评估 Deep Agents;程序已经能运行,但需要检查工具调用、状态变化和延迟,则把 LangSmith 接到观测侧。

LangChain、LangGraph、Deep Agents 与 LangSmith 形成的是分层关系,而不是从弱到强的排行榜:LangChain 提供可定制 harness,LangGraph提供低层图控制,Deep Agents 提供更完整的长任务能力,LangSmith负责观测和评估。当前目标只是完成第一个可运行 Agent,因此只引入 LangChain 和模型供应商适配包。
这样的取舍也给后续学习定了顺序:先理解 Model 和 Messages,再进入 Agent、Tools、State、Memory 与 Middleware;等这些对象的职责清楚以后,再讨论更低层编排或生产化观测,概念不会挤在同一篇快速开始里。
分层还有一个实际好处:相邻产品可以组合,而不是只能四选一。LangChain Agent 本身构建在 LangGraph 之上;LangSmith 又可以观察用这些框架构建的运行。开发者平时使用高层入口,并不妨碍框架在底层获得持久执行等能力;只有当高层抽象遮住了项目必须控制的节点和状态时,才需要下沉。这样判断比按功能数量选择"最强框架"更接近真实工程。
3. 安装时要分清运行时、核心包和供应商适配包
LangChain 的 Python 包当前要求 Python 3.10+。如果只使用核心能力,可以安装 langchain;本文还要通过 OpenAI-compatible 接口连接千问,因此同时安装 langchain-openai:
bash
py -m pip install -U langchain langchain-openai
官方把大量模型与其他集成拆到独立 provider package 中。langchain 提供 Agent、消息和可组合运行接口;langchain-openai 提供 ChatOpenAI,负责把标准模型调用转换成兼容接口请求。API key 和 Base URL 则属于运行配置,不应该写进源码仓库。
在 PowerShell 中,可以先为当前终端设置密钥:
powershell
$env:DASHSCOPE_API_KEY="你的 Model Studio API Key"
Model Studio 的 API key 与 Base URL 存在区域和计费计划边界。本文使用北京公共 DashScope 的 OpenAI-compatible 地址;如果密钥来自其他区域、工作空间专用域名或订阅计划,应使用控制台为该密钥提供的地址,不能只替换模型名就假设请求一定可达。
Model Studio 当前还把访问域名分成共享 DashScope、工作空间专属域名和试用域名。共享域名是现有的集中式入口;工作空间专属域名被推荐用于生产环境,强调吞吐、延迟和流量隔离;试用域名用于临时测试和快速验证,限流更低。本文继续使用北京共享域名,是为了让第一段代码少一个工作空间变量;它不是"所有环境都应该复制"的唯一地址。

核心包、provider package 与认证信息是三类独立依赖:缺少核心包时没有 Agent 入口,缺少 provider package 时无法创建模型对象,密钥或地址错误时请求会在模型生成之前失败。LangSmith tracing 位于旁路观测层,不是这次最小运行的前置条件。
实际排错时也应按这个层次来。ModuleNotFoundError 先检查安装环境和 provider package;401 先检查密钥与地址是否属于同一区域;404 或 model not found 再检查 Base URL 和模型名。盲目增加重试次数不会修复这些配置错误。
包已经安装也不代表当前脚本一定能导入。Windows 上可能同时存在多个 Python 解释器,py -m pip 把安装动作绑定到 py 选中的解释器;如果编辑器或虚拟环境运行的是另一个解释器,仍然会出现"终端显示安装成功,代码却找不到包"。这类问题发生在本地运行时,甚至还没有进入 LangChain,更没有向模型服务发请求。
随后才轮到远端调用目标。能创建 ChatOpenAI 对象,只说明 Python 已经认识这个类,不代表密钥、地址和模型名已经通过服务端校验。把"导入成功""认证成功""模型可用"当成三个独立检查点,遇到错误时就能知道应该检查依赖、凭据还是服务配置,而不是反复重装所有包。
4. 用 create_agent 组装最小天气 Agent
环境准备好以后,代码里只需要四个核心对象:模型、工具、系统约束和 Agent。
天气工具在这里返回固定数据。这样做不是为了模拟真实天气服务,而是先隔离网络、第三方鉴权和接口波动,让注意力集中在 create_agent 如何调度工具。换成真实项目时,工具函数内部再接数据库或天气 API,同时保留参数校验、超时和权限控制。
python
import os
from langchain.agents import create_agent
from langchain.tools import tool
from langchain_openai import ChatOpenAI
@tool
def get_weather(city: str) -> str:
"""查询城市天气;输入城市名称,返回用于出行判断的天气摘要。"""
weather_data = {
"北京": "小雨,降水概率 70%,气温 19℃",
"上海": "多云,降水概率 20%,气温 24℃",
}
return weather_data.get(city, "暂时没有该城市的天气数据")
model = ChatOpenAI(
model="qwen3.7-plus",
api_key=os.environ["DASHSCOPE_API_KEY"],
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
temperature=0,
timeout=30,
max_retries=2,
)
agent = create_agent(
model=model,
tools=[get_weather],
system_prompt=(
"你是出行助手。涉及实时天气时先调用工具,"
"再根据工具结果给出简短、明确的建议。"
),
)
ChatOpenAI 负责连接模型服务,get_weather 是模型可以选择的外部能力,system_prompt 规定什么时候应基于工具数据回答。create_agent 接收的是已经初始化好的模型对象,因此模型连接配置与 Agent 行为配置没有混在一起。
官方的 create_agent 既可以接收模型标识字符串,也可以接收已经初始化的模型实例。这里选择实例方式,是因为 api_key、base_url、超时和重试都属于模型连接边界;Agent 只需要知道"使用这个模型对象"。以后替换模型接入时,不必把认证细节重新塞进工具或系统提示中。
工具的函数名、类型标注和 docstring 会共同影响模型如何理解它。这里把 city 标为字符串,并在 docstring 中说明输入与返回值;如果描述含糊,模型可能选错工具或构造错误参数。即便工具由 Agent 调用,函数内部仍应像普通后端接口一样校验权限、参数和外部响应。
从模型视角看,它接触到的不是 Python 函数实现,而是由名称、描述和参数定义组成的工具 schema。schema 让模型知道"可以请求什么",harness 再把结构化请求交给实际函数。函数返回固定天气摘要后,这个结果会进入运行状态,而不是绕过 Agent 直接打印给用户。也正因为存在这层转换,清晰的工具描述和可靠的后端实现缺一不可。

从 schema 到真实函数之间存在一次明确的控制权交接。模型只能生成工具名和参数;harness 解析请求后,后端仍要完成参数、权限和外部服务校验;执行结果再以 ToolMessage 回到消息状态,供模型继续判断。把这条交接链保留下来,既能解释工具为什么可被模型使用,也能解释敏感能力为什么不能仅靠提示词保护。
工具请求和执行结果都已经回到消息状态后,invoke 的返回值就不能只剩最终文本;它还要保留支撑这次结果的运行轨迹。沿着同一条天气链路继续,就能看清这些消息最后怎样交付给调用方。
5. invoke 返回的是运行状态,不是裸字符串
创建 Agent 以后,把用户请求放进 messages 状态并调用 invoke:
python
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "查询北京今天的天气,并判断我是否需要带伞。",
}
]
}
)
final_message = result["messages"][-1]
print(final_message.text)
输入不是随意命名的 question 字段,而是 Agent 状态中的 messages。运行过程中,模型请求工具、工具返回数据、模型生成最终建议,都会留下相应消息;result["messages"][-1] 取的是这次运行结束时的最后一条消息。
沿着天气场景展开,这次 invoke 大致经历五步。第一步,用户消息进入状态;第二步,harness 把系统约束、可用工具和当前消息交给模型;第三步,模型返回工具调用意图和参数;第四步,harness 执行 get_weather,把返回值放回状态;第五步,模型读到工具结果后生成建议,运行才到达最终消息。模型也可能直接回答,或者在任务需要时再次请求工具,因此中间消息数量不是固定值。

时间线里真正稳定的是消息的因果顺序,而不是消息数量:HumanMessage 触发模型判断;需要外部数据时,带工具请求的 AIMessage 先出现;ToolMessage 必须携带对应结果;模型重新读取状态后,最终 AIMessage 才落在 messages[-1]。若模型无需工具,或一次任务需要多轮工具调用,中间阶段会缩短或继续展开,但最终文本仍从运行状态中读取。
这条执行链解释了为什么最终结果要从状态读取。Agent 交付的不只是最后一句文本,还包括运行中形成的上下文;直接把返回值当字符串,会丢掉后续调试和继续对话需要的信息。当前代码只取最后一条消息,是因为本篇的业务目标就是显示最终建议,不表示中间状态没有价值。
这段代码最需要关注的不是打印语句,而是三次交接:用户内容进入运行状态;模型根据系统约束和工具描述决定是否行动;最终回答再次回到状态。第 03 篇会细拆每类 Message 的角色,第 06 篇会细拆工具请求与结果怎样配对,本篇只确认状态不能被当成一个普通字符串返回值。
如果运行失败,可以沿实际路径定位:
- 模型创建前失败:检查 Python 环境、包名和导入路径。
- 模型请求被拒绝:检查密钥、Base URL、区域、模型名和账户权限。
- 模型没有调用工具:检查工具描述、系统约束和问题是否真的需要外部数据。
- 工具执行失败:检查函数参数、第三方接口、超时与权限;Agent 不会自动修复业务函数。
- 代码拿不到最终文本 :先检查返回状态是否包含
messages,再检查最后一条消息的实际内容,而不是假设invoke直接返回字符串。
这些故障也有明确的先后关系。导入失败时请求尚未发出;认证失败时模型还没有机会选择工具;模型返回工具请求以后,才可能出现参数或业务函数错误;工具结果已经写回但最终回答异常,才进入提示、上下文和模型输出的检查范围。按照运行阶段排查,可以避免用提示词修改去处理一个 API key 错误,也避免用增加重试去掩盖工具权限问题。
如果后续接入 LangSmith,trace 可以把模型调用、工具调用、状态变化和延迟展开观察;但观测工具不会改变上述责任边界。快速开始阶段先学会从异常位置和返回状态判断失败在哪一层,等运行链变长以后再增加完整观测,调试信息才有清晰的解释对象。
快速开始的目标到这里已经完成:不是把所有 LangChain 能力都装进一段代码,而是得到一个可以观察、可以扩展、也能明确排错的最小闭环。
6. 从最小闭环继续,但不要一次把能力堆满
第一个 Agent 跑通以后,最常见的冲动是立即加入记忆、多个工具、检索、middleware、流式输出和 LangSmith。这样做会让代码迅速变长,却很难判断每项能力解决了什么问题。
更稳妥的扩展顺序是沿执行依赖前进:
- 先理解 Model 怎样初始化,以及
invoke、stream、batch的差异。 - 再理解 Message 怎样保存角色、历史和程序可读字段。
- 当输出必须被业务代码稳定消费时,引入 Structured Output。
- 理解 Agent 循环后,再扩展 Tools、Runtime Context 与 State。
- 上下文变长以后,再处理 Context Engineering 和 Memory。
- 需要统一治理、检索、多 Agent、前端和生产观测时,再进入对应模块。
这个顺序不是要求所有项目都用齐这些能力。相反,每增加一层都应该能回答"它消除了哪个具体风险"。例如,用户下一句话不依赖上一轮,就没有必要为了"看起来像对话系统"先接记忆;流程完全由业务规则决定,也没有必要让模型决定下一步。
仍以出行助手为例。第一版只处理一次天气查询,当前代码已经够用;业务要求把建议写进固定字段时,先考虑 Structured Output,而不是先加记忆;用户追问"那明天呢"并且必须沿用上一轮城市时,才出现短期记忆需求;天气、交通和门票工具增多后,工具描述、错误处理和选择策略才成为新的风险;需要跨节点保存进度、人工批准某些操作时,状态与编排的重要性才会上升。

这棵决策树把扩展顺序改写成一组工程问题:没有固定字段要求,就不必先引入 Structured Output;下一轮不依赖历史,就不必制造记忆状态;工具和执行风险尚未增长,就保留当前最小工具集;只有恢复、审批或显式状态控制成为硬需求时,才下沉到更强的状态与编排能力。能力来自已出现的风险,而不是来自目录里"还有一章没用上"。
这种演进方式有意保留"暂时不用"的选择。框架提供能力,不代表应用必须启用能力。每次只增加一个能被场景证明有用的对象,测试时也更容易判断变化来自模型、工具、状态还是治理层。一次把所有组件接上,功能看似完整,任何异常却都可能从多个方向产生。
最小闭环还可以作为后续改动的回归基线。新增能力前先保留一组稳定输入,确认天气工具仍被正确选择、工具结果仍进入状态、最终消息仍能读取;新增后再比较运行路径。这样做不需要在第一篇就搭建完整测试平台,却能避免扩展过程把最初可工作的链路悄悄破坏。
总结:先判断需不需要行动循环
回到"北京今天需不需要带伞"。如果天气数据已经在输入里,Model 可以直接完成一次判断;如果应用需要模型先选择天气工具、读取结果再回答,LangChain Agent 才开始发挥作用。
最小闭环由几个清晰边界组成:ChatOpenAI 连接 qwen3.7-plus;工具提供模型外的数据;system_prompt 约束行为;create_agent 组织行动循环;messages 状态承载输入和运行结果。任何一层失败,都应回到对应对象排查,而不是笼统归因于"模型不稳定"。
这套边界也说明了 LangChain 没有替应用承担什么:它不保证天气数据正确,不替工具做权限校验,不保证模型一定选择理想行动,也不会用重试修复错误密钥。它提供的是一条可配置、可观察、可以继续扩展的运行骨架。应用仍要为模型选择、工具质量、状态规则和业务结果负责。
选择框架时也可以使用同一条判断:一次生成直接调用 Model;需要自主工具选择与循环时使用 LangChain;需要显式状态图和恢复控制时进入 LangGraph;需要开箱即用的长任务、文件系统和子 Agent 能力时再评估 Deep Agents;需要观察和评估运行质量时接入 LangSmith。
下一篇将暂时拿掉工具循环,只研究这里的 model:它怎样连接供应商,初始化参数分别控制什么,以及 invoke、stream、batch 为什么对应三种不同的应用体验。