Files
claude-code/docs/conversation/the-loop.mdx
claude-code-best 2d07ffd0ce docs: 重写 Agent Loop,从源码走读改为设计分析
移除所有源码行号、TypeScript 类型定义和函数签名,
聚焦循环四个阶段的设计考量、错误恢复哲学和状态管理原理,
增加"为什么不是批量执行"的设计论证。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-20 00:17:25 +08:00

167 lines
7.1 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "Agent Loop"
description: "理解 Claude Code 的核心循环机制——AI 如何自主决定工具调用、处理错误、管理上下文,直到任务完成。"
keywords: ["Agentic Loop", "tool_use", "状态机", "auto-compact", "streaming"]
---
## 什么是 Agentic Loop
传统聊天机器人:你问一句,它答一句。
Claude Code 不一样:你说一个需求,它可能连续执行十几步操作才给你最终结果。
这背后的机制叫做 **Agentic Loop**(智能体循环)。它是一个"思考→行动→观察"的不断循环,直到任务完成或遇到终止条件。
<Frame caption="Agentic Loop 循环示意">
<img src="/docs/images/agentic-loop.png" alt="Agentic Loop 循环图" />
</Frame>
### 为什么需要循环而非一次回答
因为软件工程任务本质上是**探索性**的。AI 不可能在第一步就知道所有信息:
- 它需要先读代码才能知道怎么改
- 它需要先运行命令才能知道结果
- 它需要先搜索才能找到相关文件
- 它需要先修改才能验证是否正确
每一步工具执行都产生**真实信息**——命令输出、文件内容、错误信息——这些是 AI 在执行前不可能预知的。因此AI 必须在每一步后根据新信息重新决策。
## 循环的四个阶段
每次循环迭代包含四个阶段,形成一个完整的"感知→决策→执行→反馈"周期。
### 阶段一:上下文预处理
在调用 API 之前,系统会依次检查和处理上下文。这是一个串行管道,每一步的输出是下一步的输入:
```
原始消息
→ 工具结果截断(单条输出过长时截断)
→ 历史压缩Snip 压缩旧消息)
→ 微压缩(工具结果摘要化)
→ 自动压缩(对话接近 token 上限时触发 AI 摘要)
处理后的消息 → 发往 API
```
**设计考量**:为什么是串行管道而非一次性处理?因为每个步骤释放的 token 数会影响下一步的决策。例如,如果 Snip 压缩已经释放了足够的 token自动压缩就不需要触发了。
### 阶段二:流式 API 调用
系统以流式方式调用 Claude API。流式传输不是"锦上添花"——它是核心设计决策:
- **用户体验**:用户看到 AI 逐字输出,而非等待数秒后一次性显示
- **工具并行执行**AI 在流式输出过程中就可能发出工具调用,系统可以立即开始执行,不必等流结束
- **可取消性**:用户随时可以中断正在进行的流式响应
### 阶段三:工具执行
如果 AI 请求了工具调用,系统执行工具并将结果回传。这里有两个关键设计:
**并行执行**:当 AI 在一次响应中请求多个独立工具调用时(如同时读两个文件),系统并行执行它们。这直接减少了用户等待时间。
**权限检查**:每个工具执行前都经过权限验证。危险操作(如执行 shell 命令)需要用户确认,安全操作(如读文件)可以自动放行。
### 阶段四:终止或继续
每次迭代结束时,系统判断是否需要继续:
| 条件 | 结果 |
|------|------|
| AI 请求了工具调用 | 继续(下一轮迭代) |
| AI 只返回文本,没有工具调用 | 终止(任务完成) |
| 用户中断 | 终止(用户取消) |
| 达到最大 turn 数 | 终止(安全限制) |
| Token 预算耗尽 | 终止(成本控制) |
## 错误恢复:自愈的状态机
Agentic Loop 不是"正常路径走完就结束"的简单循环。它包含了多层错误恢复机制,使系统在各种异常情况下都能优雅处理。
### 输出截断恢复
当 AI 的响应被 token 上限截断时AI 话说了一半被切断):
1. **首次截断**:静默提升输出 token 上限,重试
2. **仍然截断**:注入提示消息让 AI "接着说",最多重试 3 次
3. **恢复耗尽**:将截断的响应作为最终结果返回
### 上下文过长恢复
当对话历史超过 API 的 token 限制时413 错误):
1. **压缩重试**:即时压缩对话历史,生成摘要后重试
2. **压缩后仍过长**:返回错误信息,让用户决定如何处理
关键设计:系统通过标志位防止无限循环——每种恢复路径只尝试一次,不会在"压缩→失败→压缩"之间死循环。
### 模型降级
当主模型不可用时(过载、维护等):
1. 已收集的响应被保留为历史记录
2. 自动切换到备用模型
3. 通知用户发生了降级
4. 从中断点继续,而不是从头开始
## 状态管理
每次迭代的状态是不可变更新的——系统创建新的状态对象而非就地修改。状态中包含:
- **对话消息**:当前所有消息的数组
- **压缩跟踪**:压缩操作的累计状态
- **恢复计数**:各种错误恢复已尝试的次数
- **继续原因**:上一轮为什么继续(用于检测和避免循环)
**设计考量**:状态中记录"继续原因"是一个关键的防循环机制。系统可以在后续迭代中检查"上一轮是因为压缩重试而继续的",从而避免在同一个恢复路径上反复尝试。
## 为什么不是"一次规划,批量执行"
一个自然的疑问是:为什么不先让 AI 规划好所有步骤,然后一次性批量执行?
答案在于软件工程的**不确定性**
- **每步结果影响下一步**:搜索结果决定了要改哪些文件,修改后的编译结果决定了是否需要进一步调整
- **错误需要即时修正**如果某步失败AI 需要立即调整策略,而非继续执行无效计划
- **用户可能中途干预**:循环架构允许用户随时打断和修正方向
这不是说 AI 不做规划——事实上系统内置了规划模式Plan Mode用于复杂任务。但规划的结果仍然是逐步执行的每一步都有机会根据新信息调整。
## 一个完整的迭代示例
> 用户:"帮我找到项目里所有未使用的导入语句,然后删掉它们"
```
迭代 1: 探索
AI: 先找到所有 TypeScript 文件
工具: Glob("**/*.ts") → 返回 42 个文件
决策: 需要进一步分析 → 继续
迭代 2: 分析
AI: 搜索这些文件中的 import 语句
工具: Grep("import.*from") → 在 15 个文件中找到 120 条 import
决策: 结果太多,需要进一步筛选 → 继续
迭代 3: 精确修改
AI: 分析哪些 import 未被使用,删除它们
上下文预处理: 120 条结果被微压缩为摘要
工具: FileEdit × 3 → 删除 5 条未使用导入
决策: 需要验证 → 继续
迭代 4: 验证与总结
AI: 验证修改后编译通过
工具: Bash("tsc --noEmit") → 编译通过
决策: 任务完成 → 终止
```
注意这个过程中的关键特征:
- AI 在每一步后根据结果自主决定下一步
- 上下文在迭代过程中动态调整(微压缩被触发)
- 用户全程无需介入
## 接下来
- **流式响应** — 理解流式传输的设计细节和用户体验考量
- **多轮对话** — 跨迭代的上下文管理和会话持久化
- **上下文压缩** — 深入理解自动压缩的触发条件和策略
- **工具系统** — 了解 AI 可以调用哪些工具及其设计