AI Agent从入门到精通(一):用LangGraph搭建你的第一个Agent

前言
你一定用过 ChatGPT、豆包、Kimi 这些大模型产品。它们很聪明,但有个致命弱点——只会说,不会做。
问它"北京今天天气怎么样?“,它要么瞎编一个答案,要么老实告诉你"我无法获取实时信息”。
但如果大模型能自己查天气、查数据库、调 API 呢?这就是 AI Agent。
本文带你从零搭建一个能"自主使用工具"的 AI Agent,你将理解:
- Agent 和普通 LLM 调用的本质区别
- LangGraph 是什么、为什么需要它
- Agent 到底怎么知道该调哪个工具(核心原理)
- 30 分钟跑通你的第一个 Agent
一、普通 LLM 调用 vs AI Agent
普通 LLM 调用
用户: “北京今天天气怎么样?”
LLM: “北京气候宜人,适合出行。” ← 瞎编的,它根本不知道今天天气
这是一个一问一答的过程。LLM 只能基于训练数据"猜"答案。
AI Agent
用户: “北京今天天气怎么样?”
Agent 内部:
🧠 思考: 用户问天气,我有查天气的工具,应该先查一下
🔧 行动: 调用 get_weather(“北京”) → 返回"晴天,32°C"
🧠 思考: 拿到真实数据了,可以回答了
💬 回答: “北京今天晴天,32°C,空气质量良好。”
Agent = LLM + 工具 + 自主决策循环。它不是一口气给答案,而是"想一步、做一步、看一步",直到搞定为止。
这个"边想边干"的模式,学术界叫 ReAct(Reasoning + Acting)。

二、两个核心概念
2.1 有向图
LangGraph 的核心思想是把 Agent 的执行流程建模为一个有向图。
什么是有向图?用大白话说:
一堆"节点"用带箭头的线连起来,只能顺着箭头走。
生活中最直观的例子——地铁线路图:每个站 = 节点,站与站之间的轨道 = 边,单行线 = 有向。
LangGraph 中:
- 节点 = 一步操作(比如调用 LLM、执行工具)
- 边 = 操作之间的流转方向
- 条件边 = 根据上一步的结果决定下一步去哪(像分岔路口)
2.2 ReAct 循环
ReAct = Reasoning(推理)+ Acting(行动),核心就是一个循环:
思考(Reason) → 行动(Act) → 观察结果(Observe) → 再思考 → 再行动 → …
不断循环,直到 Agent 判断"我已经有足够信息了",输出最终答案。用有向图画出来:
┌──────────┐
│ START │
└────┬─────┘
▼
┌──────────┐
┌───▶│ Agent │ (LLM 推理)
│ └────┬─────┘
│ ▼
│ 需要工具?
│ ├─ 是 → [Tools] (执行工具)
│ │ │
│ └─────────┘ (结果返回,再次推理)
│
└─ 否 → [END] (输出最终答案)
三、环境搭建
3.1 安装依赖
pip install langgraph langchain-openai langchain-core python-dotenv
主要安装的包:
langgraph:图编排框架,本文主角langchain-openai:对接 OpenAI 兼容接口的 LLMlangchain-core:基础数据结构(消息、工具定义等)
3.2 配置大模型 API
本文使用火山方舟(字节跳动的模型服务平台),原因:国内直连无需翻墙、兼容 OpenAI 接口格式、豆包模型支持 Function Calling。
.env
OPENAI_API_KEY=你的火山方舟 API Key
OPENAI_BASE_URL=https://ark.cn-beijing.volces.com/api/v3
四、动手实现:最简 Agent
完整可运行的 Agent,核心只有 30 行左右。6 个关键步骤:
① 定义工具 —— Agent 的"手和脚"
@tool
def get_weather(city: str) -> str:
“”“查询指定城市的天气情况”“”
data = {“北京”: “晴天,32°C”, “深圳”: “雷阵雨,30°C”}
return data.get(city, f"{city}:暂无数据")
② 定义 State —— 图的全局状态
class AgentState(TypedDict):
messages: Annotated[list, add_messages]
③ 创建 LLM 并绑定工具(bind_tools = 递菜单)
llm = ChatOpenAI(model=“doubao-1-5-pro-32k”, …).bind_tools(tools)
④ 定义节点
def agent_node(state):
return {“messages”: [llm.invoke(state[“messages”])]}
⑤ 定义条件边
def should_continue(state):
return “tools” if state[“messages”][-1].tool_calls else “end”
⑥ 构建图 → 编译 → 运行
workflow = StateGraph(AgentState)
workflow.add_node(“agent”, agent_node)
workflow.add_node(“tools”, ToolNode(tools))
workflow.add_edge(START, “agent”)
workflow.add_conditional_edges(“agent”, should_continue,
{“tools”: “tools”, “end”: END})
workflow.add_edge(“tools”, “agent”)
app = workflow.compile()
result = app.invoke({“messages”: [HumanMessage(“北京天气怎么样?”)]})
每一步对应的概念:
| 步骤 | 做了什么 | 对应概念 |
|---|---|---|
| ① | 定义 Agent 能力 | 工具(Tool) |
| ② | 定义共享数据结构 | 状态(State) |
| ③ | 把工具菜单递给 LLM | bind_tools |
| ④ | 定义图中的操作节点 | 节点(Node) |
| ⑤ | 根据结果决定走向 | 条件边 |
| ⑥ | 组装并运行 | 图(Graph) |
五、核心原理:Agent 怎么知道要调工具

这是初学者最常见的困惑:
“我只是问了句’北京天气怎么样’,Agent 怎么就知道要调 get_weather 这个函数?”
答案藏在 bind_tools 这一行里。
5.1 bind_tools 到底做了什么
当你写 llm.bind_tools(tools) 时,LangChain 会把你定义的工具转换成一份结构化描述,在每次调用 LLM 时一起发过去。
实际发送给大模型 API 的请求长这样:
{
“messages”: […用户消息…],
“tools”: [
{
“type”: “function”,
“function”: {
“name”: “get_weather”,
“description”: “查询指定城市的天气情况”,
“parameters”: {
“properties”: {
“city”: {“type”: “string”}
},
“required”: [“city”]
}
}
}
]
}
看到了吗?工具的名字、描述、参数格式,全部以 JSON Schema 的形式附在请求里。
5.2 LLM 的决策过程
大模型收到请求后,相当于看到了一份"菜单":
| 工具名 | 功能描述 | 参数 |
|---|---|---|
| get_weather | 查询指定城市的天气情况 | city (string) |
| get_time | 获取当前时间 | timezone (string) |
然后 LLM 做了一个推理判断:
“用户问的是天气 → 菜单里有个 get_weather 能查天气 → 参数需要城市名 → 用户说的是北京 → 调用 get_weather,参数填’北京’”
于是 LLM 返回的不是普通文字,而是一个结构化的工具调用请求:
{
“tool_calls”: [{
“function”: {
“name”: “get_weather”,
“arguments”: “{“city”: “北京”}”
}
}]
}
5.3 工具描述的重要性
LLM 决定调不调工具、调哪个工具,完全依赖工具的描述文本。
回看代码里的 docstring:
@tool
def get_weather(city: str) -> str:
“”“查询指定城市的天气情况”“” # ← 这就是"菜单描述"
…
如果描述写成含糊的"一个工具函数",LLM 就不知道什么时候该调它。写好工具描述 = 给 LLM 一份清晰的使用说明书。
5.4 一个类比总结
| 环节 | 餐厅类比 | Agent 类比 |
|---|---|---|
| 定义工具 | 厨师准备好菜品 | 开发者写 @tool 函数 |
| bind_tools | 服务员递上菜单 | 把工具描述附在请求里 |
| LLM 推理 | 顾客看菜单点菜 | LLM 选择工具+填参数 |
| 执行工具 | 厨房做菜 | ToolNode 执行函数 |
| 返回结果 | 菜端上桌 | 结果追加到消息列表 |
没有菜单(bind_tools),顾客(LLM)只能瞎猜;有了菜单,才能精准点菜。
六、运行流程拆解
6.1 简单问题:单次工具调用
输入:“北京今天天气怎么样?”
Step 1: START → agent → LLM 返回 tool_calls=[get_weather(“北京”)]
Step 2: → tools → 执行得到 “晴天,32°C”
Step 3: → agent → LLM 整理答案,无 tool_calls
Step 4: → END
消息链:System → Human → AI(tool_call) → Tool(结果) → AI(最终回答),共 5 条。
6.2 复杂问题:多次工具调用
输入:“深圳和成都哪个更适合今天出门?”
Step 1: agent → 先查深圳 tool_calls=[get_weather(“深圳”)]
Step 2: tools → “雷阵雨,30°C”
Step 3: agent → 还需要成都 tool_calls=[get_weather(“成都”)]
Step 4: tools → “阴天,25°C”
Step 5: agent → 两城对比,返回最终答案
Step 6: END
Agent 自动循环了两次,没有任何硬编码。是 LLM 自己判断"信息不够,再查一次"。
关键洞察
-
LLM 自主决定循环次数 — 不是代码写死调几次,是 LLM 判断信息够不够
-
每轮 LLM 能看到完整历史 — messages 不断追加,LLM 有全部上下文
-
条件边是唯一的"开关" — 只做一件事:看有没有 tool_calls
七、总结
| 概念 | 一句话解释 |
|---|---|
| AI Agent | LLM + 工具 + 自主决策循环 |
| LangGraph | 用有向图编排 Agent 执行流程的框架 |
| State | 图的全局状态,所有节点共享的"记忆" |
| Node | 图中的一步操作 |
| 条件边 | 根据运行时状态动态选择下一步 |
| ReAct | 推理→行动→观察→循环 |
| bind_tools | 把工具"菜单"递给 LLM |
参考资料
-
LangGraph 官方文档
-
LangGraph Quick Start Tutorial
-
ReAct 论文 (Yao et al., 2022)
-
火山方舟 API 文档
-
OpenAI Function Calling 文档
这里给大家精心整理了一份全面的AI大模型学习资源,包括:AI大模型全套学习路线图(从入门到实战)、精品AI大模型学习书籍手册、视频教程、实战学习、面试题等,资料免费分享!
👇👇扫码免费领取全部内容👇👇
1. 成长路线图&学习规划
要学习一门新的技术,作为新手一定要先学习成长路线图,方向不对,努力白费。
这里,我们为新手和想要进一步提升的专业人士准备了一份详细的学习成长路线图和规划。可以说是最科学最系统的学习成长路线。
2. 大模型经典PDF书籍
书籍和学习文档资料是学习大模型过程中必不可少的,我们精选了一系列深入探讨大模型技术的书籍和学习文档,它们由领域内的顶尖专家撰写,内容全面、深入、详尽,为你学习大模型提供坚实的理论基础。(书籍含电子版PDF)

3. 大模型视频教程
对于很多自学或者没有基础的同学来说,书籍这些纯文字类的学习教材会觉得比较晦涩难以理解,因此,我们提供了丰富的大模型视频教程,以动态、形象的方式展示技术概念,帮助你更快、更轻松地掌握核心知识。

4. 2026行业报告
行业分析主要包括对不同行业的现状、趋势、问题、机会等进行系统地调研和评估,以了解哪些行业更适合引入大模型的技术和应用,以及在哪些方面可以发挥大模型的优势。

5. 大模型项目实战
学以致用 ,当你的理论知识积累到一定程度,就需要通过项目实战,在实际操作中检验和巩固你所学到的知识,同时为你找工作和职业发展打下坚实的基础。

6. 大模型面试题
面试不仅是技术的较量,更需要充分的准备。
在你已经掌握了大模型技术之后,就需要开始准备面试,我们将提供精心整理的大模型面试题库,涵盖当前面试中可能遇到的各种技术问题,让你在面试中游刃有余。

7. 资料领取:全套内容免费抱走,学 AI 不用再找第二份
不管你是 0 基础想入门 AI 大模型,还是有基础想冲刺大厂、了解行业趋势,这份资料都能满足你!
现在只需按照提示操作,就能免费领取:
👇👇扫码免费领取全部内容👇👇
更多推荐

所有评论(0)