📚 Harness 学习计划 / 第3周 / Day11_读书AIAA第3章

Day 11 · 读书《AI Agents in Action》第3章:Tool Use

属性
日期 2026-08-27
周次 第3周:读书+对照分析
轨1 · Agent 通用架构认知
时间 1 小时
状态 ✅ 已完成

📋 Checklist


✍️ 读书笔记

核心概念 1:Agent Loop(五步循环)

Tool Use 是 Agent 和 Chatbot 的分水岭。Chatbot 只能"说",Agent 能"做"。

五步循环

用户输入
  → ① Plan:LLM 分析意图,决定需要什么工具
  → ② Call:LLM 输出结构化 tool_call({name, args})
  → ③ Execute:Harness 真正执行工具(调 API、查数据库等)
  → ④ Observe:结果喂回给 LLM
  → ⑤ Respond:LLM 判断——够了就输出回答,不够就回到 ① 继续调工具

职责边界:LLM 管 ①→②→⑤(决策),Harness 管 ③→④(执行)。

核心概念 2:Tool Schema 设计

Tool 用 JSON Schema 定义,三个关键字段:

字段 作用 PM 视角
name LLM 内部标识 和开发对齐即可
description 告诉 LLM「什么时候用这个工具」 prompt engineering,PM 核心工作
parameters.description 告诉 LLM「从用户话里提取什么」 prompt engineering,PM 核心工作
enum 限定可选值,防 LLM 瞎编 业务边界定义
required 必填字段 业务规则

高质量 Tool 的 5 条标准

  1. Name 见名知意(search_product 不是 tool_01
  2. Description 说清"什么时候用"
  3. 参数 Description 说清"填什么"
  4. 用 enum 约束边界
  5. 考虑异常情况(为空、超时、报错时返回什么)

核心概念 3:ReAct 模式(Reasoning + Acting)

ReAct = 边想边做,且思考过程可见

Thought / Action / Observation 含义

标签 谁产生的 含义
Thought: 模型 "我现在的判断是什么,下一步应该做什么"
Action: 模型 "我要调用这个工具,参数是这些"
Observation: Harness "工具执行完了,返回的结果是这个"(不是模型说的,是 Harness 塞回去的)

ReAct 对话流:模型输出 Thought → 模型输出 Action → Harness 返回 Observation → 模型输出 Thought → ... 循环直到模型输出最终 Answer。

与普通 Tool Loop 的区别:

普通 Tool Loop ReAct 模式
思考过程 不可见(黑盒) 可见(Thought 作为文本输出)
典型输出 直接 tool_call: search_product(...) Thought: 我需要先搜索Action: search_product(...)
调试性 不知道为什么调了这个 Tool 能看到推理过程,好定位问题
用户体验 只能看到最终结果 可展示"正在为您搜索..."
循环能力 有循环(执行→思考→再执行) 有循环(且每步都显式写出)

核心区别不是"有没有循环",而是"思考过程是否可见"。两者都支持多轮循环,但 ReAct 把每一步推理写出来。

思考步骤显式化:隐式 = LLM 心里想,不说出来。显式 = 边想边说,每一步都写下来。显式化同时提升推理质量和可调试性。

四种 Tool 类型

类型 干什么 SmallRig 举例
Retrieval(检索) 查信息 search_productquery_order
Computation(计算) 算数据 calculate_discountconvert_currency
Action(执行) 做操作 add_to_cartcreate_order
Memory(记忆) 存/读信息 save_preferenceget_history

Action 类需要确认机制(Day 9 结论"确认优先"的理论支撑)。

行动启示:对照 SmallRig 项目

维度 书中模式 AI 搜索现状 差距
Tool 定义 多 Tool Schema 只有搜索(隐式) 需显式定义多个 Tool
Agent Loop Plan→Call→Execute→Observe→Respond 单次调用→返回 没有循环,没有多轮
Tool 类型 检索+计算+执行+记忆 仅检索 缺 Action(下单/加购)
多 Tool 编排 链式调用,ReAct 需设计 Tool 衔接关系
错误处理 Fallback 策略 搜索结果为空时无兜底

核心启示:改造第一步不是换模型,而是把隐式搜索变成显式 Tool 定义 + 五步循环。

PM 和开发的职责边界

角色 职责
PM 定义 Tool Schema(JSON),确保 description 清晰、enum 完整、异常场景覆盖
开发 实现 Harness 层:解析 tool_call → 路由 → 执行 → 异常处理 → 格式化 tool_result → 循环上限控制
接口 双方对齐 JSON Schema

📘 PM 参考模块:如何阅读和设计 Tool Schema

以下内容可直接作为 PM 撰写 Tool 定义时的参考模板。

模块一:PM 阅读 Tool Schema 的心法

把 Schema 当成你写给 LLM 的"新员工操作手册"

{
  "name": "search_product",           // ← 工具的名字,LLM 内部标识用
  "description": "搜索 SmallRig 商品,根据关键词返回商品名称和价格",  // ← 🔑 PM 最该关注!告诉 LLM「什么时候用这个工具」
  "parameters": {
    "type": "object",                  // ← 固定写法,不用管
    "properties": {
      "keyword": {                     // ← 参数名
        "type": "string",              // ← 数据类型:字符串/数字/布尔
        "description": "商品搜索关键词"  // ← 🔑 PM 最该关注!告诉 LLM「从用户话里提取什么填进来」
      },
      "category": {
        "type": "string",
        "description": "商品分类",
        "enum": ["cage", "plate", "light", "other"]  // ← 🔑 白名单,限制 LLM 只能选这些
      }
    },
    "required": ["keyword"]            // ← 哪些参数必须填
  }
}

PM 阅读心法表

字段 PM 怎么看 类比
name 工具名,和开发对齐即可 函数名
description 这是 prompt engineering——LLM 靠这段文字决定「现在该不该调这个工具」 告诉新人"什么情况下用这个工具"
parameters.description 也是 prompt engineering——LLM 靠这段文字从用户原话里提取参数值 告诉新人"这个字段填什么"
enum 业务边界——限定可选范围,防止 LLM 瞎编 下拉框选项
required 业务规则——不填就报错 必填字段

一句话:PM 的核心工作是写好 description 和定义 enum/required,这些决定了 LLM 调工具调得准不准。

模块二:tool_result 错误返回的设计模板

这是 PM 设计 Tool 时必须覆盖的异常场景。 Harness 返回的 tool_result 直接引导 LLM 下一步行为。

正确返回格式

// ✅ 正常返回
{
  "success": true,
  "data": [
    { "product_id": "220B", "product_name": "220B 兔笼", "price": 49.9 },
    { "product_id": "300B", "product_name": "300B 兔笼", "price": 79.9 }
  ]
}

错误返回格式(PM 需要设计每种异常场景)

// ❌ 差的错误返回(LLM 不知道怎么办)
{ "error": "查询失败" }

// ✅ 好的错误返回(LLM 知道下一步该做什么)
{
  "success": false,
  "error": "未找到商品",
  "reason": "关键词 'xyz123' 未匹配到任何商品",
  "suggestion": "请尝试用产品型号(如 220B)或品类名(如 兔笼)搜索,或告知用户当前没有找到相关商品"
}

PM 设计 Tool 时的异常场景清单

异常类型 举例 tool_result 应该包含
结果为空 搜索"xyz123"无结果 error + reason + suggestion: "换关键词或告知用户"
参数错误 category 填了 "abc" error + suggestion: "可选值为 cage/plate/light/other"
服务超时 接口 30s 无响应 error + suggestion: "告知用户稍后重试,不要再次调用此工具"
权限不足 查询他人订单 error + suggestion: "告知用户需要登录或无权查看"
重试达上限 同一 Tool 已重试 2 次 error + suggestion: "请不要再调用此工具,基于已有信息回答"

设计原则:tool_result 里永远不只说"出错了",还要说"为什么出错"和"建议 LLM 下一步做什么"。

模块三:重试上限的三层设计

上限不直接告诉 LLM(LLM 不知道数字),而是通过 Harness 硬逻辑 + tool_result 终止信号间接传达。

上限类型 触发条件 LLM 收到什么(终止信号)
同 Tool 重试 2 次 第 3 次调用同一 Tool tool_result: "请不要再调用此工具,告知用户稍后重试"
总轮次 8 轮 第 9 次 Tool Call Harness 拒绝执行,返回 "已达对话上限,请基于已有信息回答"
超时 30s 超过 30s Harness 终止,返回 "处理超时,请告知用户稍后重试"

LLM 不"知道"上限数字,但收到终止信号后会停止调用。


❓ 错题本:今日提问与答案

以下为今天学习过程中提出的全部 17 个问题及对应答案。


第一轮:六层讲课后确认(7 问)

Q1:作为 PM,怎么辨认 JSON Schema 里每个参数是什么意思?

把 Schema 当成你写给 LLM 的"新员工操作手册"。

字段 PM 怎么看 类比
name 工具名,和开发对齐即可 函数名
description prompt engineering——LLM 靠这段文字决定「现在该不该调这个工具」 告诉新人"什么情况下用这个工具"
parameters.description prompt engineering——LLM 靠这段文字从用户原话里提取参数值 告诉新人"这个字段填什么"
enum 业务边界——限定可选范围,防止 LLM 瞎编 下拉框选项
required 业务规则——不填就报错 必填字段

PM 的核心工作是写好 description 和定义 enum/required,这些决定了 LLM 调工具调得准不准。


Q2:ReAct 模式是指内部的 Loop 吗?LLM 自行决定调用哪些工具完成这次输出?

是的,完全正确。ReAct 就是 LLM 内部的决策循环:LLM 看到用户输入 → 自己判断需要调工具A → 拿到结果 → 自己判断还需要调工具B → 判断够了 → 输出答案。PM 不需要告诉 LLM「先调 A 再调 B」,只需要定义好工具包,LLM 自己决定调用顺序。


Q3:Plan → Call → Execute → Observe → Respond 展开说说

我理解成:计划用什么工具 → 通过 tool_call 调用 Harness 工具 → Harness 返回结果给 LLM → LLM 再决定是继续 loop 还是输出结果。

这个理解正确。具体:

LLM 只管 ①②⑤(决策),Harness 管 ③④(执行)。


Q4:ReAct 是什么意思?就是 Loop 循环?

ReAct 不只是 Loop,它是「边想边做」的特定模式。ReAct = Reasoning + Acting。

与普通 Loop 的核心区别:ReAct 的思考过程可见(Thought 作为文本输出),普通 Loop 的思考过程不可见(黑盒推理)。


Q5:需要设计 Tool 链——PM 定义好了 Tool 包,LLM 自己决定调用,为什么还说是 Tool 链?

"Tool 链"不是指 PM 写死调用顺序,而是指 PM 在设计时需要考虑 Tool 之间的衔接关系:

PM 不定义调用顺序,但定义"Tool 之间的关系图"。


Q6:显式 Tool 定义 + 五步循环——PM 和开发各自做什么?高质量 Tool 的要求是什么?

PM 职责:定义高质量 Tool Schema(JSON),写好 description + enum + required + 异常场景。

开发职责:实现 Harness 层(解析 tool_call → 路由 → 执行 → 异常处理 → 格式化 tool_result → 循环上限控制)。

高质量 Tool 的 5 条标准:

  1. Name 见名知意
  2. Description 说清"什么时候用"
  3. 参数 Description 说清"填什么"
  4. 用 enum 约束边界
  5. 考虑异常情况(为空、超时、报错时返回什么)

Q7:ReAct 模式和 Day 3 学的 Claude Tool Use 轮转,是不是同一个东西?"思考步骤显式化"是什么意思?

本质上是同一个东西(都是"调工具→拿结果→再决策"的循环),但 ReAct 更强调"思考步骤的显式化"。

显式化 = LLM 把思考过程写出来,而不是藏在黑盒里。隐式(Claude)= 心里想不说出来,显式(ReAct)= 边想边说,每一步都写下来。显式化的价值:可调试、可审计、用户可理解 Agent 为什么这么做。


第二轮:写学习记录后追问(5 问)

Q8:enum 如果实际类目有 50 个,需要全写吗?

不需要全写。三种策略:

类目数量 推荐策略 原因
≤10 enum 全写 简单直接
10-50 只写一级类目 enum 平衡精度和可维护性
50+ 不写 enum,靠 description 软引导 + Harness 后校验 穷举不现实

enum 是"硬约束",类目多时改为 description "软引导" + Harness "后校验"。


Q9:ReAct 模式和普通 Tool Loop 由谁决定?模型还是 Harness?怎么判断模型有没有这个能力?

由模型训练时决定,Harness 不改模型输出格式。

判断方法:看 Model Card 是否写"supports ReAct"、看官方 System Prompt 示例里有没有 Thought:/Action:/Observation: 标签、或直接实测。

Claude 和 Hermes 原生都不支持 ReAct(它们用 JSON FC 格式),可通过 System Prompt 模拟。对 SmallRig 来说 ReAct 不是硬需求。


Q10:多个 Tool 之间的字段名如何保持一致?(search_product 返回 id,add_to_cart 需要 product_id)

PM 先定义全局字段字典,再写每个 Tool Schema,所有 Tool 对齐同一本字典。

先画表:商品ID→product_id, 商品名→product_name, 价格→price
然后所有 Tool 输入输出都对齐同一套字段名

Q11:空结果/异常时的重试上限怎么设计?

2-2-8-30 法则:

三个上限都通过 Harness 硬逻辑 + tool_result 终止信号传达给 LLM,LLM 不"知道"数字但收到信号后停止。


Q12:工具报错时,引导 LLM 正确下一步的提示写在哪里?是 System Prompt 吗?

两个地方:System Prompt 给通用原则("不要重复调用相同参数的工具"),tool_result 给本次具体建议("订单号不存在,请用手机号查询")。

tool_result 是主力,因为它在当前对话上下文里,LLM 刚看到就据此决策。PM 重点设计每种异常场景的 tool_result 返回内容。


第三轮:打开文件后追问(3 问)

Q13:笔记中加一个 PM 参考模块——包含 Tool Schema 阅读心法和 tool_result 错误返回示意

已添加「📘 PM 参考模块」,包含三个子模块:


Q14:ReAct 模式和普通 Tool Loop 的区别再说一次。Thought / Action / Observation 分别是什么?

核心区别不是"有没有循环"(两者都支持多轮循环),而是思考过程是否可见

标签 谁产生的 含义
Thought: 模型 "我现在的判断是什么,下一步应该做什么"
Action: 模型 "我要调用这个工具,参数是这些"
Observation: Harness "工具执行完了,返回的结果是这个"(不是模型说的,是 Harness 塞回去的)

ReAct 对话流:Thought → Action → Observation → Thought → ... → 最终 Answer。


Q15:重试上限放在哪里让 LLM 接收到?

上限不直接告诉 LLM,上限是 Harness 的硬逻辑。LLM 能"感知"到上限是通过 tool_result 的终止信号:

上限类型 触发条件 LLM 收到什么(终止信号)
同 Tool 重试 2 次 第 3 次调用同一 Tool tool_result: "请不要再调用此工具,告知用户稍后重试"
总轮次 8 轮 第 9 次 Tool Call Harness 拒绝执行,返回 "已达对话上限,请基于已有信息回答"
超时 30s 超过 30s Harness 终止,返回 "处理超时,请告知用户稍后重试"

LLM 不"知道"上限数字,但收到终止信号后会停止调用。


第四轮:最新追问(2 问)

Q16:超时是直接砍断交互不通知 LLM 直接结束?

不是。三个上限都是通知 LLM 的,没有"直接砍断"。

上限类型 LLM 是否收到通知 LLM 还能做什么
同 Tool 重试 2 次 ✅ 收到 tool_result 基于已有信息回答用户,或换一个 Tool
总轮次 8 轮 ✅ 收到 tool_result 基于已有信息回答用户
超时 30s ✅ 收到 tool_result 告知用户"处理超时,请稍后重试"

超时是 Harness 在 30s 内主动中断工具执行,返回 {"error": "处理超时", "suggestion": "请告知用户稍后重试"},LLM 看到后输出友好回复给用户。不是系统级 HTTP 超时的"砍断"。

Q17:错题本没收集到所有问题,需要完整归档

本问题——已通过本次更新完整归档全部 17 个 Q&A。


📤 产出