The Agent Loop
"一个工具 + 一个 while 循环 = 一个 Agent 的雏形"
从零推导这个循环为什么存在、怎么工作。
问题起源:Claude 碰不到真实世界
打开 Claude,问"1+1等于几"——Claude 回答"2"。一轮结束。这是一次请求-响应,没有循环。
但如果你问"我当前目录下有什么文件?"——Claude 不知道。它看不到你的电脑。它有推理能力,但碰不到真实世界。
RUN: 开头 = 请求执行命令。
🔧 RUN: ls
这就是"工具请求"——Agent 的原点
Claude 的回复不再是纯文本回答,而是一个工具请求。模型从"回答问题"变成了"请求行动"。这就是 Agent 的"行动"。
人肉循环:你在 Claude 和终端之间搬运信息
Claude 请求 ls,你执行后得到 a.py b.py c.py。你得把这个结果再发一条消息告诉 Claude:
a.py b.py c.py如果任务更复杂——"找出所有 Python 文件,检查有没有 TODO 注释"——Claude 可能需要调多次工具:
🔧 RUN: ls *.py
🔧 RUN: grep TODO a.py b.py
b.py: (无)
循环诞生:把人肉循环变成代码
把上面的"你来回来去搬运信息"抽象成逻辑,就是两层判断:
伪代码
两层循环 & 名字解释
其实有两个循环:外层 REPL + 内层 Agent Loop
外层 REPL:用户连续提多个任务。("创建 a.py"→"再写个 b.py"→"看看 git 状态")外层每轮调用一次内层。
内层 Agent Loop:单个任务内部,Claude 调多次工具,直到完成。
外层循环人控制节奏,内层循环模型控制节奏。外层 messages 跨任务保留——所以后面说"再改一下那个文件",模型记得。
Agent
就是 Claude(LLM)。能感知(读对话历史)、推理(理解任务)、行动(调用工具)。它不是一个特殊程序,它就是那个模型本身。
Agent Loop
一个 while 循环,让 LLM 可以多次调用工具,每次拿到结果后决定下一步,直到它自己判断任务完成。没有这个循环,LLM 调一次工具就停了,你必须手动把结果贴回去再问一遍。
代码拆解:s01 的四个组成部分
s01 总共 120 行,由四个独立组件构成。Agent Loop 只是其中之一:
初始化:身份 + 环境 + 能力
在循环之外,只执行一次。决定 Agent 是谁、在哪、能做什么。
工具执行函数:Agent 的"手"
真正在操作系统上执行命令。三个安全约束:黑名单拦截、120s超时、50000字符截断。
Agent Loop:内层循环
这是核心。接收 messages,反复"调LLM → 执行工具 → 塞结果",直到 stop_reason 不再是 tool_use。
外层 REPL:用户交互循环
接收用户输入,调用 agent_loop,打印结果,等下一个输入。history 跨任务共享。
关键细节:response.content 不是纯文本
response.content 是一个block 列表。理解它的结构是理解 Agent Loop 的前提:
{
"role": "assistant",
"content": [
{ "type": "text",
"text": "这里有 3 个文件" }
]
}
stop_reason = "end_turn"
{
"role": "assistant",
"content": [
{ "type": "tool_use",
"id": "toolu_001",
"name": "bash",
"input": {"command": "ls"} }
]
}
stop_reason = "tool_use"
真实数据追踪:messages 在每一步的变化
任务:"创建一个 hello.py 输出 Hello World"。
user → assistant → user → assistant → ...。Harness 冒充 user 塞 tool_result,就是为了维持这个交替。
messages = [ {"role": "user", "content": "创建 hello.py 输出 Hello World"} ]
role序列: [user] → 合法,可以调用 API
messages = [
{"role": "user", "content": "创建 hello.py ..."},
{"role": "assistant", "content": [{"type": "tool_use", "id": "toolu_001", ...}]}
]
role序列: [user, assistant] — stop_reason="tool_use",不能停
messages = [
{"role": "user", ...},
{"role": "assistant", ...}, ← tool_use
{"role": "user", "content": [{"type": "tool_result", "tool_use_id": "toolu_001", ...}]}
]
role序列: [user, assistant, user] → 合法!可再次调用 API
messages = [
{"role": "user", ...},
{"role": "assistant", ...}, ← tool_use
{"role": "user", ...}, ← tool_result
{"role": "assistant", "content": [{"type": "text", "text": "已创建 hello.py"}]}
]
role序列: [user, assistant, user, assistant] — stop_reason="end_turn" ✅
规律
① role 严格交替永不打破。② Harness 冒充 user维持交替。③ Claude 控制退出,stop_reason 决定一切。
Agent Loop = 不断往 messages 末尾追加 assistant(tool_use) + user(tool_result),直到 stop_reason 变成 end_turn。
从 s01 带走的三个核心认识
Agent = 模型 + 循环 + 工具
不需要"工作流引擎"、不需要"决策树"。一个 while 循环 + API 就够了。
循环什么时候停?模型说了算
退出条件是 stop_reason,不是硬编码的"检查任务完成"。信任模型的判断。
模型没记忆,你替它记
每次 API 调用无状态。messages 列表就是模型的"记忆"。你负责维护它。
落地案例:Agent Loop 在真实 AI 产品中的应用
学完 Agent Loop 之后,你会发现几乎所有 AI Agent 产品底层都是这个 while 循环。以下是三个真实的 Agent 产品如何应用这个模式。
🤖 场景一:Claude Code 的 Agent Loop(你正在用的)
打开 Claude Code,说"帮我写一个登录页面"。Claude Code 的内部就是你在 s01 学到的那个 while 循环,只不过它比你写的多了几十个工具:
你学完 s01 之后,回到 Claude Code 里观察它的一次工具调用:它会先 Read 文件 → 分析内容 → Edit 修改 → 也许再 Bash 运行测试 → 看输出 → 如果失败再改。这个连续的"思考-行动-观察"就是 Agent Loop。你现在能看懂它在干什么了。
🌐 场景二:Browser-Use Agent(让 AI 操作浏览器)
browser-use 是一个开源项目,让 AI Agent 像人一样操作网页——点击按钮、填写表单、滚动页面。它的核心就是 Agent Loop:
观察:截取当前网页截图 + DOM 结构 → 发给 LLM。
决策:LLM 返回下一步动作(click 这个按钮 / type 这段文字 / scroll 到下面)。
行动:用 Playwright 执行这个动作。
循环:截取新的网页状态,发给 LLM,直到 LLM 说"任务完成"。
这个工具让非程序员也能自动化网页操作——"帮我在淘宝搜索蓝牙耳机,按销量排序,把前 10 个结果导出到表格"。底层就是 s01 的 while 循环,只不过工具从 bash 换成了 click/type/scroll。
🏠 场景三:智能家居 Agent(Home Assistant + LLM)
Home Assistant 的 LLM Agent 集成 让用户用自然语言控制家里所有设备。它的 agent 循环:
用户:"我要睡觉了,把家里调成睡眠模式。"
LLM:分析意图 → 调 tool_use:关客厅灯、关窗帘、设空调到 26°C、启动安防。
Harness:执行 4 个工具调用 → 返回结果。
LLM:检查结果 → 灯关了 ✓ 窗帘关了 ✓ 空调设好了 ✓ 安防异常 ✗。
LLM:再调 tool_use:检查安防传感器 → 发现阳台门没关 → 提醒用户。
这就是 s01 的循环在物理世界运行。工具从 bash 变成了 IoT 设备 API,但 Agent Loop 的结构完全不变。