# 三行速读
- 这一章把 “会聊天” 变成 “会执行”:核心是
tool_use -> tool_result回写闭环。 - 你要真正看懂的是
run_one_turn的停止 / 继续条件,而不只是最终回答文本。 - 后面所有章节都在这个 loop 上加层,不会推翻它。
# 先修知识
- Python 基础:函数、循环、字典、异常处理。
- 命令行基础:知道
subprocess.run在做什么。
# 读完后你应该能做到(可检验清单)
# 本篇要解决什么
这篇只做一件事:把 “会聊天的模型” 变成 “能持续做事的智能体”。
很多新手第一次做 Agent,会卡在同一个点:模型能给建议,但你还要手动执行命令、复制结果、再贴回去。这个过程一旦超过几轮,就很容易乱。
s01 的目标就是把这个人工往返自动化,形成最小闭环:
- 用户提问。
- 模型决定是否调用工具。
- 程序执行工具。
- 工具结果写回会话。
- 模型继续,直到完成。
# 用一个类比先理解
把它想成 “客服工单流转”:
- 用户提需求。
- 客服把需求交给执行同事(工具)。
- 执行同事返回结果。
- 客服继续处理下一步。
如果没有这条流转链,客服只能停在 “建议你这样做”,但工单永远不会真正办完。
# 为什么这一步必须现在做
因为后面所有能力(权限、记忆、任务、多智能体)都依赖这条主循环。如果循环本身不稳定,后续只是往不稳定底座上加功能。
所以学习顺序是对的:先把 loop 跑通,再谈扩展。
# 关键代码怎么读
# 1) 把状态显式放进 LoopState
1 |
|
这三个字段分别回答:现在聊到哪、第几轮、为什么继续下一轮。新手最容易忽视的是第三个字段,它对后续错误恢复非常关键。
# 2) 工具执行后一定要回写 tool_result
1 | def execute_tool_calls(response_content) -> list[dict]: |
tool_use_id 是关联键。没有这层对应关系,模型不知道哪条结果对应哪次调用。
# 3) 单轮函数 + while 循环
1 | def run_one_turn(state: LoopState) -> bool: |
这个拆分非常适合新人理解:单轮负责 “做一轮”,主循环负责 “反复做”。
# 你可以怎么复现
- 只保留一个工具(
bash)先跑通闭环。 - 用
print打出每次tool_use和tool_result。 - 人工输入一个需要两步以上的任务,观察 loop 是否自然停止。
# 常见误区
- 误区 1:把最终答案当核心,忽略中间工具回写。
- 误区 2:为了 “看起来聪明” 先加很多工具,结果循环逻辑没站稳。
- 误区 3:把状态藏在全局变量里,后续难调试。
# 一句话总结
s01 的本质不是 “调用一次模型”,而是建立一个可持续执行的闭环,这就是后续所有章节的地基。
# 补充解读:把 s01 的代码完整走一遍
这一节专门补 “之前略过的代码细节”。如果你是第一次学 Agent,建议按这个顺序读源文件:
- 先看常量:
SYSTEM、TOOLS。 - 再看状态:
LoopState。 - 再看工具执行:
run_bash、execute_tool_calls。 - 最后看循环:
run_one_turn->agent_loop。
# A. run_bash 为什么要先做危险命令拦截
1 | dangerous = ["rm -rf /", "sudo", "shutdown", "reboot", "> /dev/"] |
这一段虽然很朴素,但它在教学里有两个意义:
- 告诉你 “工具执行” 不是直接裸跑命令,安全门要前置。
- 告诉你 “工具层可以失败”,而失败也要作为
tool_result回写,不能吞掉。
很多新人第一次写 Agent 会漏掉 “失败也要回写”。结果模型只看到 “没结果”,容易重复发同一个命令。
# B. extract_text 为什么单独存在
1 | def extract_text(content) -> str: |
这函数看起来像工具函数,但它在告诉你一件现实:模型响应是结构化 block,不是永远一段纯文本。把 “渲染展示层” 和 “内部 block 层” 分开,是后面扩展工具类型的基础。
# C. run_one_turn 的停止条件其实是状态机
1 | if response.stop_reason != "tool_use": |
你可以把它理解成一个极小状态机:
- 不是
tool_use-> 停止。 - 是
tool_use且有结果 -> 继续。 - 回写成功后把
transition_reason标成tool_result。
这个 transition_reason 在教学版里只是一个字段,但在真实系统里会发展成恢复策略、可观测指标的一部分。
# D. 时序图(建议照着打印日志自己验证)
messages加入用户输入。- 调用模型。
- 如果模型要工具:执行工具、回写结果。
- 继续下一轮。
- 直到
stop_reason != tool_use。
建议你在 run_one_turn 前后各加一行日志,打印 turn_count 与 stop_reason ,会非常直观。
# 进阶练习(巩固本章)
- 在
run_bash中增加stderr和stdout分开返回的模式,观察模型后续行为变化。 - 在
LoopState里新增last_tool_name,每轮记录最近一次工具调用,验证状态是否更可调试。 - 强制让模型执行 3 次以上工具调用,检查 loop 是否稳定收敛。
# 统一术语口径(本章)
Agent Loop:智能体每一轮 “思考 -> 调工具 -> 回写 -> 继续” 的主循环。tool_use:模型提出的工具调用请求。tool_result:工具调用完成后返回给模型的结果块。
# 章节衔接(从易到难)
- 本章先解决 “能不能形成闭环执行”。
- 下一章
s02解决 “闭环不变的前提下,如何扩展更多工具能力”。