Agent Loop 与 Tool Use
Agent Loop 与 Tool Use
本章讲解最小 Agent Loop 的实现(
while stop_reason == "tool_use")与 Dispatch Map 工具分发模式,以及 learn-claude-code 的 12 层演进路线。参考:learn-claude-code s01-s02 — “Bash is all you need”
最小 Agent Loop
🔬 核心理念:
while stop_reason == "tool_use"— 一个循环 + 一个工具 = 一个 Agent。
Agent Loop 本质上是 ReAct 范式的最小实现。核心逻辑约 30 行代码:
def agent_loop(messages):
while True:
# ① 调用模型:传入完整 messages + tools 定义
response = client.messages.create(
model=MODEL,
system=SYSTEM,
messages=messages,
tools=TOOLS,
max_tokens=8000,
)
# ② 将 assistant 输出追加到上下文
messages.append({"role": "assistant", "content": response.content})
# ③ 唯一退出条件:模型不再要求调用工具
if response.stop_reason != "tool_use":
return response
# ④ 遍历 content block,执行所有工具调用
results = []
for block in response.content:
if block.type == "tool_use":
handler = TOOL_HANDLERS.get(block.name)
output = handler(**block.input)
results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": output,
})
# ⑤ 工具结果以 user 角色追加回上下文 → 闭环
messages.append({"role": "user", "content": results})四个核心步骤
| 步骤 | 动作 | 说明 |
|---|---|---|
| 1 | 调模型 | client.messages.create(...) 传入完整 messages + tools |
| 2 | 看回复 | 检查 response.stop_reason 是否为 "tool_use" |
| 3 | 执行工具 | 遍历 response.content,对每个 tool_use block 调用 handler |
| 4 | 结果塞回 | 封装为 tool_result 追加到 messages,回到步骤 1 |
关键设计洞察
messages既是上下文也是状态:所有对话历史、工具调用、执行结果都沉淀在统一的消息列表中,无需额外的状态对象stop_reason驱动控制流:不靠字符串规则判断"像不像最终答案",直接利用 API 的结构化字段- Harness 哲学:模型只负责决策(生成
tool_use),外部程序负责真正执行
Tool Use:Dispatch Map 模式
🔑 核心理念:“加一个工具,只加一个 handler” — 循环不用动,新工具注册进 dispatch map 就行。
工具分发表
TOOL_HANDLERS = {
"bash": lambda **kw: run_bash(kw["command"]),
"read_file": lambda **kw: run_read(kw["path"], kw.get("limit")),
"write_file": lambda **kw: run_write(kw["path"], kw["content"]),
"edit_file": lambda **kw: run_edit(kw["path"], kw["old_text"], kw["new_text"]),
}加工具 = 加 handler + 加 schema,循环永远不变。
路径沙箱 (safe_path)
def safe_path(p: str) -> Path:
path = (WORKDIR / p).resolve() # 解析绝对路径,消除 .. 和 .
if not path.is_relative_to(WORKDIR): # 防止逃逸工作区
raise ValueError(f"Path escapes workspace: {p}")
return path所有文件操作工具在执行前都经过沙箱校验,这是 Agent 安全的第一道防线。
两层不变原则
- Agent Loop 自身永远不变:s02-s12 所有机制都在最小循环上"叠加",核心骨架不修改
- 加工具不需要改循环:只需注册 handler 函数 + 添加 tool schema
learn-claude-code 的 12 层演进
s01 Agent Loop ← 地基:LLM → tool → tool_result → LLM
s02 Tool Use ← 层1:dispatch map + 路径沙箱
s03 TodoWrite ← 层2:任务规划与进度追踪
s04 Subagents ← 层3:子 Agent 上下文隔离
s05 Skills ← 层4:按需知识注入(类似"技能包")
s06 Context Compact ← 层5:上下文压缩与摘要
s07 Tasks ← 层6:持久化任务图(跨会话)
s08 Background Tasks ← 层7:异步并行执行
s09 Agent Teams ← 层8:多 Agent 分工协作
s10 Team Protocols ← 层9:团队通信协议
s11 Autonomous Agents ← 层10:自治任务认领(自主模式)
s12 Worktree Isolation ← 层11:Git worktree 隔离执行每一层只增加一个机制,层层叠加,最终将"模型调用"演进为"Agent Runtime"。