Skip to content

第 7 章:Tools 与 Agent

章节定位

前面几章我们已经把 AI 学习助手 从“单轮问答”推进到“链式处理”和“RAG 问答”。这一章开始,系统要从“只会回答”升级为“会调用外部能力”。

Tools 与 Agent 是 LangChain 应用里非常关键的一步。Tools 负责把外部能力显式暴露给模型,Agent 负责决定“什么时候调用哪个工具、调用几次、如何整合结果”。如果前面的链式应用更像是预先写死流程,这一章就是把流程的一部分交给模型动态决策。

配套示例

  • 目录:examples/chapter-07
  • 入口:examples/chapter-07/main.py
  • 依赖:examples/chapter-07/requirements.txt
  • 运行:cd examples/chapter-07 && python3 main.py

示例层级与边界

  • 层级:教学版
  • 本章重点:理解 Tool 的输入输出边界,以及 Agent 为什么只该用在需要动态决策的地方。
  • 不要误判:示例没有接入真实大模型规划,也没有覆盖权限控制、沙箱隔离和多轮恢复机制。

本章目标

  • 理解 Tool 和 Agent 的区别
  • 知道为什么单纯的 Prompt 和链不够用
  • 学会给 AI 学习助手 增加一个工具调用能力
  • 能设计一个最小可用的 Agent 方案
  • 了解工具边界、失败重试和安全控制

前置知识

  • 已理解 Prompt、Model、Parser 的基础抽象
  • 已完成基础链式应用和 RAG 入门
  • 知道“模型输出不等于真实执行结果”

核心概念

1. Tool 是什么

Tool 可以理解为“模型可调用的外部函数”。这个函数可以是:

  • 搜索知识库
  • 读取本地文档
  • 计算数学结果
  • 查询课程目录
  • 生成学习计划

从工程角度看,Tool 的关键不是“能做什么”,而是“输入输出是否明确”。如果一个能力无法被清晰描述为输入和输出,模型就很难稳定使用它。

2. Agent 是什么

Agent 不是一个单独的模型,而是一种“让模型边想边做”的运行方式。它通常包含以下循环:

  • 观察用户问题
  • 判断是否需要工具
  • 调用一个或多个工具
  • 读取工具结果
  • 继续推理或直接回答

和链式应用相比,Agent 的差异在于流程不是一次性写死的,而是根据当前上下文动态选择。

3. 为什么需要 Agent

如果 AI 学习助手 只做 RAG,它只能回答“资料里已有的内容”。但真实学习场景经常需要:

  • 检查课程目录
  • 查询某章的先后关系
  • 生成练习题
  • 做简单计算
  • 把多个信息源综合起来

这些需求都不是“单次检索后直接回答”能稳定解决的。Agent 适合把这些能力串起来,但也意味着更难调试,所以必须先理解边界。

分模块讲解

1. Tool 设计原则

一个好的 Tool 通常满足四点:

  • 输入明确
  • 输出稳定
  • 作用单一
  • 失败可控

例如“查询课程章节列表”比“帮我了解这个项目”更适合作为 Tool。前者边界清楚,后者太宽泛,模型很难正确调用。

2. Agent 和链的边界

链适合固定流程,例如:

用户问题 -> 检索资料 -> 总结回答

Agent 适合流程不固定的场景,例如:

用户问题 -> 判断是否需要检索 -> 需要则查资料 -> 再决定是否补充工具 -> 最后回答

如果任务流程已经完全确定,就不要上 Agent。Agent 的成本更高、行为更不稳定,应该用在“需要动态决策”的地方。

3. 给 AI 学习助手增加工具

这一章建议把 AI 学习助手 先升级成 V3,支持三个最小工具:

  • search_outline:查询课程大纲或章节名
  • get_chapter_summary:读取某章摘要
  • generate_practice:生成练习题

这三个工具的共同点是:它们都围绕“学习路径”本身工作,不会把项目带偏到无关业务。

4. Agent 的最小运行方式

一个最小 Agent 需要解决三件事:

  • 模型是否有工具列表
  • 工具结果如何回传
  • 什么时候结束任务

你可以把它理解成“会调用工具的问答助手”,而不是“一个万能机器人”。

最小示例说明

下面是一个概念化的最小结构,表达的是设计方式,不是完整生产代码:

python
tools = [
    search_outline,
    get_chapter_summary,
    generate_practice,
]

agent = create_agent(model=model, tools=tools)

result = agent.invoke({
    "input": "帮我找出第 7 章前需要先掌握什么,并给我两个练习题"
})

这个示例的重点不是 API 细节,而是结构:

  • 模型知道有哪些工具可用
  • 用户输入进入 Agent
  • Agent 自行判断是否需要调用工具
  • 最终把工具结果整合成答案

真实框架版对照

examples/chapter-07/main.py 新增了一个 真实框架版 演示,用来对照教学版的最小 Agent。

这一版更接近真实 LangChain 接口的地方在于:

  • Tool 改成 @tool 装饰后的真实工具对象
  • Agent 规划结果用 AIMessage.tool_calls 表示
  • 工具执行结果回填为 ToolMessage

你暂时还不需要在这一章就引入完整线上 agent runtime,但应该开始熟悉这些真实接口长什么样,因为后续排查 Agent 问题时,你看到的通常就是这些结构。

本章实践

建议把本章实践做成 AI 学习助手 V3

实践目标

  • 用户问“我现在应该先学哪一章”
  • 系统能查询课程大纲
  • 系统能返回当前章节的前置知识
  • 系统能顺便生成 2 到 3 道练习题

实践步骤

  1. 先把“课程目录查询”做成第一个 Tool
  2. 再把“章节摘要读取”做成第二个 Tool
  3. 再把“练习题生成”做成第三个 Tool
  4. 最后让 Agent 自主决定调用顺序

实践判断标准

  • 工具边界清晰
  • 回答中能看出工具确实被调用过
  • Agent 出错时能明确看到是检索问题、生成问题还是组合问题

常见坑

  • 把所有能力都做成一个大 Tool,结果模型不知道怎么用
  • 让 Agent 处理本来可以用固定链完成的任务,增加不必要的不稳定性
  • 工具返回内容太长,导致模型上下文被挤爆
  • 不给工具明确输入格式,后面调试会非常痛苦
  • 只看最终回答,不看工具执行过程,出了错也不知道错在哪里

练习题

  1. 设计一个 search_outline 工具,要求输入是章节编号,输出是章节名称和一句摘要。
  2. 设计一个 generate_practice 工具,要求根据章节主题输出 3 道练习题。
  3. 思考一下:哪些学习场景适合 Agent,哪些场景只适合链?
  4. 如果工具返回了错误信息,Agent 应该如何向用户解释,而不是直接报错?

本章总结

这一章的关键结论是:Tool 让模型“能做事”,Agent 让模型“会选择做什么事”。

AI 学习助手 来说,Tools 和 Agent 的价值不是为了炫技,而是为了把“课程导航、章节查询、练习生成、知识辅助”这些任务整合成一个更自然的学习体验。

但也要记住,Agent 不是默认最优解。只要任务流程可以稳定写死,就优先用链;只有当任务确实需要动态决策时,再引入 Agent。

学完本章,你现在应该会

  • 区分 Tool 和 Agent 的职责边界
  • 判断一个学习场景适合固定链还是适合 Agent 动态决策
  • AI 学习助手 V3 设计出边界清晰的几个工具
  • 从最终回答反推出 Agent 是否真的调用了工具

最小验收 checklist

  • [ ] 我至少设计了 2 到 3 个输入输出明确的 Tool
  • [ ] 我能解释为什么不能把所有能力都塞进一个大 Tool
  • [ ] 我能说出 Agent 在这个章节里到底帮我省掉了什么固定流程
  • [ ] 我知道排查 Agent 问题时要看工具调用过程,不只看最后答案

建议你动手改一版

  • 先只实现 search_outlineget_chapter_summary 两个 Tool,再决定是否值得加第三个 Tool
  • 给某个 Tool 补一个错误返回格式,练习让 Agent 优雅处理失败
  • 把一个原本可以固定执行的任务强行交给 Agent,再比较它和链的稳定性差异

卡住时先回看这里

下一章预告

下一章我们会把这种“模型动态决策 + 多工具调用”的思路进一步工程化,进入 LangGraph。那一章会解决一个更现实的问题:当流程开始出现分支、循环、重试和人工介入时,怎样把整个系统组织得可控、可调试。