Logo Vincent
返回文章列表

Claude Code Agent Loop:拆解 AI 编程助手的心脏

Claude
Claude Code Agent Loop:拆解 AI 编程助手的心脏

什么是 Agent Loop

你在终端里输入一句话,Claude Code 就开始干活——读文件、改代码、跑测试、修 bug,循环往复,直到任务完成。

这个”循环往复”的东西,就是 Agent Loop

它是 Claude Code 的心脏。没有它,Claude 只是一个聊天机器人;有了它,Claude 变成了一个能自主完成复杂任务的编程 Agent。

简单说,Agent Loop 做的事情就一句话:

用户输入 → 调 API → 模型回复 → 如果要用工具就执行工具 → 把结果喂回去 → 继续调 API → 直到不需要工具为止。

看起来简单,但魔鬼在细节里。

核心循环:一个 while(true)

Claude Code 的 Agent Loop 本质上是一个 AsyncGenerator 函数

export async function* query(
  params: QueryParams,
): AsyncGenerator<StreamEvent | Message, Terminal>

用 Generator 而不是普通函数,是因为它需要在执行过程中不断 yield 中间结果(流式消息、工具进度、状态更新),同时保持循环状态。

核心结构长这样:

while (true) {
  1. 准备消息(压缩、裁剪、折叠)
  2. 调用 Claude API(流式)
  3. 收集模型回复
  4. 有 tool_use?→ 执行工具 → 收集结果 → continue
  5. 没有 tool_use?→ 检查是否需要恢复 → 否则退出
  6. 把 [原消息 + 助手回复 + 工具结果] 组装成新消息
  7. 进入下一轮
}

整个循环里有 7 个 continue 出口——每一个都对应一种”还不能停,继续跑”的场景。

流式响应:模型还在说话,工具已经开始干活

Claude Code 不是等模型说完再执行工具,而是边流式接收回复边执行工具

当模型返回的 content block 中出现 tool_use 类型时,StreamingToolExecutor 会立即把它加入执行队列:

if (message.type === "assistant") {
  const msgToolUseBlocks = message.message.content.filter((content) => content.type === "tool_use");

  if (msgToolUseBlocks.length > 0) {
    toolUseBlocks.push(...msgToolUseBlocks);
    needsFollowUp = true;
  }

  // 模型还在输出,工具已经开始跑了
  if (streamingToolExecutor) {
    for (const toolBlock of msgToolUseBlocks) {
      streamingToolExecutor.addTool(toolBlock, message);
    }
  }
}

这意味着:当 Claude 在一次回复中调用了 3 个工具(比如同时读 3 个文件),第一个文件在模型还没说完话的时候就已经开始读了。

这就是为什么 Claude Code 感觉比想象中快。

Claude Code 流式并行执行模型

并行工具执行:不是所有工具都能并行

StreamingToolExecutor 管理着工具的并发执行,但不是无脑并行——它区分两种工具:

  • Concurrent-safe:可以和其他 concurrent-safe 工具并行跑(比如同时读多个文件)
  • Exclusive:必须独占执行(比如写文件、跑 Bash 命令)
private canExecuteTool(isConcurrencySafe: boolean): boolean {
  const executingTools = this.tools.filter(t => t.status === 'executing')
  return (
    executingTools.length === 0 ||
    (isConcurrencySafe && executingTools.every(t => t.isConcurrencySafe))
  )
}

每个工具被跟踪为一个状态机:

queued → executing → completed → yielded

结果按添加顺序返回(不是完成顺序),保证消息流的确定性。

工具生命周期:三道关卡

Claude Code 有 40+ 内置工具(Bash、Read、Edit、Grep、Glob、Agent 等),每个工具都遵循统一的生命周期:

validateInput() → checkPermissions() → call()

Claude Code 工具生命周期三阶段

第一关:输入校验。 参数格式对不对?路径合不合法?不合法直接拒绝,不浪费一秒。

第二关:权限检查。 这个操作允许吗?权限系统是三层的:

  1. Hook 预检查(用户配置的 PreToolUse 钩子)
  2. 规则引擎匹配(settings.json 里的 allow/deny 规则)
  3. 用户交互确认(弹窗问你 Yes/No)

第三关:执行。 前两关都过了,才真正执行工具逻辑。

这套设计保证了安全性——Claude 永远不会”先斩后奏”。

五层压缩:上下文永远不会爆

长对话最大的敌人是上下文窗口限制。Claude Code 为此设计了五层递进的压缩体系

Claude Code 五层压缩体系

第 1 层:Tool Result Budget

每条工具结果有大小上限。比如你 cat 了一个 10 万行的文件,它不会把 10 万行全塞进上下文,而是裁剪到合理大小。

第 2 层:History Snip

对历史消息做轻量裁剪,去掉已经不重要的旧对话片段。

第 3 层:Microcompact

缓存感知的优化——在不破坏 API 缓存命中率的前提下,对消息做微调压缩。

第 4 层:Context Collapse(实验性)

把多轮对话”折叠”成摘要,保留关键信息但大幅减少 token 数。这是 feature flag 控制的实验功能。

第 5 层:Autocompact

最后一道防线。当 token 数逼近阈值时,自动触发全量压缩:

const AUTOCOMPACT_BUFFER_TOKENS = 13_000;

export function getAutoCompactThreshold(model: string): number {
  const effectiveContextWindow = getEffectiveContextWindowSize(model);
  return effectiveContextWindow - AUTOCOMPACT_BUFFER_TOKENS;
}

还有个断路器:连续失败 3 次就停止重试,防止无限循环。

这五层就像一个漏斗,从细粒度到粗粒度,确保无论对话多长,上下文永远在可控范围内。

你用 /compact 手动触发的,其实就是第 5 层。

七种恢复路径:尽一切可能不中断

Agent Loop 里最精妙的部分是错误恢复机制。遇到问题不是直接报错退出,而是有 7 条恢复路径:

1. Prompt-Too-Long(413 错误)

消息太长 API 拒绝了?先尝试 Context Collapse 排水(便宜,保留细节),不行再触发 Reactive Compact(全量摘要)。

2. Reactive Compact

413 或者媒体文件太大时的紧急压缩。和 Autocompact 不同,这是”已经出错了才触发”的应急方案。

3. Max Output Tokens 升级

模型输出被截断了?自动升级到更高的 token 上限重试:

if (isWithheldMaxOutputTokens(lastMessage)) {
  state = {
    maxOutputTokensOverride: ESCALATED_MAX_TOKENS,
    transition: { reason: "max_output_tokens_escalate" },
  };
  continue;
}

4. Max Output Tokens 恢复

升级了还是被截断?注入一条”请从断点继续”的消息,让模型接着写:

const recoveryMessage = createUserMessage({
  content: "Output token limit hit. Resume directly...",
});

5. Stop Hook 阻断

Post-sampling hook 返回了阻断信号?把错误信息喂回模型,让它调整行为后重试。

6. Token Budget 续航

token 预算还没用完?注入一条 nudge 消息继续。

7. 正常的下一轮

工具执行完了,组装新消息,进入下一个循环迭代。

这 7 条路径的设计哲学很明确:能恢复就恢复,能继续就继续,用户感知到的中断越少越好。

模型降级:流量高峰也不掉线

当主模型(比如 Opus)负载过高时,Claude Code 有自动降级机制:

if (innerError instanceof FallbackTriggeredError && fallbackModel) {
  currentModel = fallbackModel

  // 清理已经产生的消息(变成"墓碑")
  for (const msg of assistantMessages) {
    yield { type: 'tombstone', message: msg }
  }

  // 清空状态,用降级模型重试
  assistantMessages.length = 0
  toolResults.length = 0

  yield createSystemMessage(
    `Switched to ${renderModelName(fallbackModel)} due to high demand...`
  )
  continue
}

注意”墓碑”机制——已经流式输出到终端的消息会被标记为 tombstone,UI 层会把它们移除。用户看到的是:原来的输出消失,换成降级模型的新输出。

工具摘要:Haiku 打辅助

每次工具执行完,Claude Code 会异步调用 Haiku(最快最便宜的模型)生成一句话摘要:

nextPendingToolUseSummary = generateToolUseSummary({
  tools: toolInfoForSummary,
  signal: toolUseContext.abortController.signal,
});

这个摘要在下一轮 API 调用之前 yield 出来,用于在终端显示进度提示。

关键词是异步——Haiku 的摘要生成和主模型的下一轮思考是并行的。Haiku 只需要 ~1 秒,而主模型一个 turn 通常 5-30 秒,所以摘要永远不会成为瓶颈。

错误隐藏:先自己消化,消化不了再告诉用户

Agent Loop 有一个很有意思的设计——错误隐藏(Withholding)

let withheld = false;
if (contextCollapse?.isWithheldPromptTooLong(message)) withheld = true;
if (reactiveCompact?.isWithheldPromptTooLong(message)) withheld = true;
if (reactiveCompact?.isWithheldMediaSizeError(message)) withheld = true;
if (isWithheldMaxOutputTokens(message)) withheld = true;

if (!withheld) {
  yield yieldMessage; // 只有恢复失败才让用户看到
}

当出现 413、输出截断等可恢复错误时,Claude Code 不会立即把错误展示给用户。它先尝试自动恢复——压缩上下文、升级 token 上限、从断点续写。只有恢复全部失败,用户才会看到错误。

这就像一个好的客服:后厨出了问题,先自己解决,实在解决不了才告诉顾客。

全景图

把所有模块串起来,这就是 Claude Code Agent Loop 的完整架构:

Claude Code Agent Loop 全景架构图

为什么这个设计值得学习

Claude Code 的 Agent Loop 不是学术论文里的理论框架,而是经过大规模生产验证的工程实现。几个值得借鉴的设计理念:

  1. Generator 模式:用 AsyncGenerator 实现”边执行边输出”,比回调或事件驱动更清晰
  2. 流式并行:不等模型说完就开始执行工具,最大化利用等待时间
  3. 分级压缩:五层递进而不是一刀切,在精度和成本之间找到平衡
  4. 静默恢复:能自愈的错误不暴露给用户,降低认知负担
  5. 状态机式工具管理:queued → executing → completed → yielded,清晰可追踪
  6. 优雅降级:主模型不可用时自动切换,用户几乎无感

如果你正在构建自己的 AI Agent,这些模式都可以直接借鉴。

写在最后

Agent Loop 是 Claude Code 最核心的模块,整个 query.ts 有 1700+ 行,是项目中最大的单文件之一。

但它的核心思想其实很简单:循环调用 → 执行工具 → 自动恢复 → 直到完成。 复杂的是边界情况的处理——而这些边界情况,恰恰是一个生产级 Agent 和一个 demo 的区别。

下次你在终端里看着 Claude Code 忙前忙后地改代码、跑测试、修 bug 的时候,你知道了——在它的心脏里,是一个永不轻言放弃的 while(true)。

相关推荐

AI-first 创业公司,为什么只需要一种编程语言?

技术架构越简单 = AI Coding 效率越高。从 Java 的"防人"设计到 TypeScript 全栈通吃,聊聊 AI 时代创业公司的编程语言选择。

cc-ping:一行命令 Ping 所有 Claude Code 配置

用多个 Claude Code API Key 或中继?cc-ping 帮你管理配置、一键切换,还能并行 Ping 所有节点比速度。

震惊!程序员用这个工具,4分钟干完95分钟的活!效率暴涨24倍

躺床上发3条消息,4分钟搞定3个项目。传统方式需要95分钟,这就是冷兵器和热兵器的差距。

CCBot - 研发提效 24 倍

通过 IM 机器人控制 Claude Code,3 个项目 4 分钟全部搞定。传统编程需要 95 分钟,效率提升 24 倍。

Claude Code /add-dir:被低估的 Monorepo 神器

Claude Code 默认只能看到当前目录。/add-dir 打破这个限制——分享我每天跨 5 个仓库使用的经验。

Claude Code 省 Token 小技巧:感叹号的妙用

一个简单却容易被忽略的技巧——用感叹号直接执行命令,省 token、提速度、更可控。

我做了个机器人,让团队在飞书里用 Claude Code

CCBot 让你的团队在飞书群聊里直接用 Claude Code——不需要终端、不需要 SSH。开源、自部署、五分钟搞定。

Claude Code /btw 命令详解:不打扰主线的快问快答

详细介绍 Claude Code 的 /btw 命令——它是什么、怎么用、什么时候该用,以及它和子代理、/compact 的区别。

Claude Code /compact:释放上下文,不丢进度

任务做到一半上下文满了?/compact 帮你压缩对话继续干活——和 /clear、/rewind 的区别一次讲清。

Claude Code /config:一文搞懂所有可调设置

用 Claude Code 却从没打开过 /config?这篇带你逐项拆解——从权限模式到自动压缩,从主题切换到通知配置,帮你打造最顺手的 AI 编程环境。

Claude Code /context:你的上下文都被什么吃了?

对话到一半 Claude Code 说上下文不够了?/context 用一张可视化网格告诉你:上下文被什么占了、占了多少、怎么优化。

Claude Code /diff:这次对话改了什么,一目了然

Claude Code 帮你改了一堆文件,但你不确定到底改了什么?/diff 用交互式界面展示所有改动——既有 git 视角的全量 diff,也有按对话轮次拆分的逐步 diff。

Claude Code /fast:同样的 Opus,两倍速——值不值?

/fast 不会降级模型,还是 Opus,只是更快。什么时候该开、什么时候该关,以及实际体验差异。

Claude Code 引用外部知识的最佳实践:GitHub MCP + Context7

用 GitHub MCP 和 Context7 MCP 两个工具组合,解决 Claude Code 知识过时导致的代码错误问题。

Claude Code /hooks:让 AI 按你的规矩办事

想在 Claude Code 执行命令前自动检查?想在任务完成后自动通知?/hooks 让你用脚本、AI 甚至 HTTP 请求,在关键节点插入自定义逻辑。

Claude Code /init:10 秒自动生成 CLAUDE.md

别再手写 CLAUDE.md 了。看看 /init 自动生成的效果、怎么自定义输出,以及一个让 Claude Code 效率翻倍的小技巧。

Claude Code MCP:让 AI 连接 GitHub、数据库等一切工具

MCP 把 Claude Code 从代码阅读器升级为全栈 Agent。哪些 MCP 服务器值得装、配置怎么写,实测分享。

Claude Code /memory 详解:让 AI 真正记住你的项目

详细介绍 Claude Code 的 /memory 命令和记忆系统——CLAUDE.md 手动指令、Auto Memory 自动记忆、模块化规则,让 Claude 跨会话记住项目规范和个人偏好。

Claude Code /model:Opus、Sonnet、Haiku 怎么选?

不是每个任务都需要 Opus。怎么切换模型、哪个场景用哪个、怎么省 token 又不掉质量。

Claude Code /permissions:谁能干什么,你说了算

每次 Claude Code 要跑命令都弹窗问你?嫌烦又不敢全放开?/permissions 帮你精细控制每个工具的权限——该放的放,该拦的拦。

Claude Code /plan 详解:先想清楚再动手

详细介绍 Claude Code 的 /plan 命令和 Plan Mode——只读规划模式,让 Claude 先分析代码、制定方案,确认后再动手,避免复杂任务翻车。

Claude Code + Playwright MCP:AI 终于能"看见"页面了

一个 Modal 溢出的 bug,Claude Code 反复修了 5 次都没搞定。直到接入 Playwright MCP 让它真正看到页面,一次定位,一次修复。

Claude Code /resume 命令详解:别让对话白聊

详细介绍 Claude Code 的 /resume 命令——恢复历史对话、管理会话、实用技巧,让你的每一轮对话都不浪费。

Claude Code /review:让 AI 帮你做 Code Review

提了 PR 没人看?想在合并前多一道把关?/review 让 Claude Code 像一个资深开发者一样审查你的代码——还有 /ultrareview 和 /security-review 两个进阶选择。

Claude Code Skills 详解:打造你的专属命令库

详细介绍 Claude Code 的 Skills 功能——创建自定义斜杠命令、复用提示词模板、共享团队最佳实践,让 AI 编程更高效更一致。

Claude Code /stats:看看 AI 到底帮你写了多少代码

好奇 Claude Code 到底写了多少行代码?/stats 给你完整数据——token、编辑次数、工具调用,教你怎么看。

Claude Code /status 命令详解:一眼看清会话全貌

详细介绍 Claude Code 的 /status 命令——它是什么、怎么用、能看到哪些信息,以及它在日常工作流中的实际价值。

Claude Code /tasks 命令详解:后台任务尽在掌控

详细介绍 Claude Code 的 /tasks 命令——查看后台任务、管理并行 Agent、掌控长时间运行的进程,让多任务开发井井有条。

Claude Code /usage 命令详解:你的额度还剩多少

详细介绍 Claude Code 的 /usage 命令——查看用量、了解限额、避免突然被限速,让你对自己的额度心中有数。

Claude Code /vim:在 AI 编程助手里用 Vim 键位

习惯了 Vim 的操作方式?/vim 让你在 Claude Code 的输入框里用 hjkl 移动、dd 删行、ciw 替换单词——不用改变肌肉记忆。

Claude Code 使用指南:从安装到实战,一篇就够(2026)

用了半年 Claude Code 的经验总结——5 分钟安装配置、最常用的命令、CLAUDE.md 编写技巧,以及没人告诉你的实战心得。

Claude 全家桶:从聊天到写代码到自动办公,一文讲清楚

一篇文章带你了解 Anthropic 的 Claude 全家桶——Claude.ai、Claude Code、Claude Cowork,以及 Opus、Sonnet、Haiku 三大模型家族。

Claude Code /agents 详解:自定义 AI 子代理,各司其职

详细介绍 Claude Code 的 /agents 命令——查看、管理和创建自定义 Agent,让不同任务由专门的 AI 角色来执行,从代码探索到架构规划各司其职。

Claude Code /doctor 详解:一键诊断你的开发环境

详细介绍 Claude Code 的 /doctor 命令——自动检测安装状态、API 连接、MCP 配置、上下文用量等问题,帮你快速定位和修复环境故障。

Claude Code /effort 详解:控制 AI 思考的深度

详细介绍 Claude Code 的 /effort 命令——调节 Claude 的推理努力程度,在速度和质量之间找到最佳平衡点,让每一次对话都恰到好处。

Claude Code /cost 详解:你的 AI 编程到底花了多少钱

详细介绍 Claude Code 的 /cost 命令——实时查看会话 API 成本,了解各模型定价和 Token 消耗明细,让每一分钱都花得明明白白。

Claude Code /export 详解:把 AI 对话带走

详细介绍 Claude Code 的 /export 命令——将对话导出为文件或复制到剪贴板,方便分享、存档和复盘,让每一次有价值的对话都不浪费。

Claude Code /rewind 详解:AI 改错了?一键回退

详细介绍 Claude Code 的 /rewind 命令——将代码和对话回退到任意历史节点,支持只回退代码、只回退对话、或两者同时回退,是你和 AI 协作时的后悔药。

Claude Code /plugin 详解:给你的 AI 编程助手装插件

详细介绍 Claude Code 的 /plugin 命令——管理插件的安装、启用、禁用和更新,通过插件扩展 Claude Code 的命令、技能、Agent 和 Hook,打造你专属的 AI 编程工具链。

Claude Code /theme 详解:给你的终端换个好看的皮肤

详细介绍 Claude Code 的 /theme 命令——6 种预设主题 + 自动模式,支持深色/浅色、色盲友好、ANSI 兼容,60+ 色值覆盖终端全部 UI 元素。

Claude Code /insights 详解:用 AI 分析你自己用 AI 的方式

详细介绍 Claude Code 的 /insights 命令——五阶段数据分析流水线、七大洞察章节、多维度会话统计,用 Claude Opus 生成专属 HTML 使用报告。

Claude Code /rename 详解:给你的会话取个有意义的名字

详细介绍 Claude Code 的 /rename 命令——手动命名、AI 自动生成(Haiku 模型)、启动参数命名、Plan 模式自动命名,以及双标题系统与 Bridge 同步机制。

Claude Code settings.json 配置详解:5 层优先级、3 种文件路径,一篇搞懂

Claude Code 的 settings.json 到底放哪里?用户级、项目级、本地级有什么区别?什么是 managed-settings.json?一篇讲清 5 层配置的优先级规则、合并逻辑和实际使用场景。

Claude Code settings.json 详解(二):permissions 权限系统全解析

深入解析 Claude Code 的 permissions 配置——allow/deny/ask 三类规则、通配符语法、MCP 工具权限、defaultMode 各模式含义,以及 additionalDirectories 的作用。

Claude Code settings.json 详解(三):hooks 钩子全解析

深入解析 Claude Code 的 hooks 配置——四种钩子类型、核心事件(PreToolUse/PostToolUse/Stop/Notification)、stdin/stdout 协议、exit code 语义,以及实用配置示例。

Claude Code settings.json 配置模板:env、模型、认证等实用字段速查

Claude Code settings.json 常用字段速查表:env 环境变量、模型切换、apiKeyHelper 动态认证、Git 署名、思考深度、语言与界面、自动更新等,附可直接复制的配置示例。

© 2026 vincentqiao.com . 保留所有权利。