Claude Code 源码拆解:终端 AI Agent 的 ReAct 循环到底怎么跑(附 30 行最小 Agent Loop)
AI编程 #AI Agent #ClaudeCode #Cursor #MCP协议 #代码审计 #2026-08-10
2026-08-10 早 6:50 首发:周一晨读,接住 8 月 Agent 热浪。昨天我们聊了黎曼猜想的螺旋零点,今天把镜头切回工程界——Claude Code 为什么能自己读代码、跑测试、改 Bug? 答案不在大模型本身,而在
query.ts里那个写了 1700 行的while(true)。本文扒开终端 Agent 的心脏:ReAct / TAOR 循环、工具并行执行、七层上下文恢复、螺旋轨迹收敛,并给你一段 30 行 Python 最小可运行 Agent Loop,照抄就能跑。
一、 先破除一个迷信:Agent 不是黑盒,是 while(true)
很多人以为 Claude Code 是“大模型套壳”,其实它的核心循环朴素到可笑:
// query.ts(简化)
async function* queryLoop(state) {
while (true) {
// 1. 上下文压缩(snip / microcompact / autocompact)
// 2. 拼 system prompt + messages + tools
// 3. 流式调模型
// 4. 解析 response:有 tool_use → 执行;无 → 结束
// 5. tool_result 回灌 messages
// 6. continue / return
}
}
这就是 ReAct(Reasoning + Acting)。但 Claude Code 把这套范式做成了生产级状态机:
-
简单版 ReAct:10 行 Python,
while True+if tool_call -
Claude Code 版:1700 行 TypeScript,
State对象 + 7 个命名continue分支(输出触顶升级 / 响应式压缩重试 / 上下文崩塌清理 / Stop Hook 阻塞 / Token 预算续航…)
差距不在“循环”,在循环外围的 12 条安全带:上下文压缩、并发安全、权限沙箱、Hook 系统、熔断重试、Prompt Cache 分割。
二、 四层架构:Terminal 只是壳,Runtime 才是魂
Claude Code 不是 CLI 工具,是终端里的 Agent Runtime:
|
层 |
文件/模块 |
职责 |
|---|---|---|
|
Entry |
|
参数解析、React+Ink 渲染 TUI |
|
Session |
|
跨轮 Token 统计、权限拒绝记忆、submitMessage |
|
Turn |
|
主 ReAct 循环(1700 行状态机) |
|
Action |
|
Read/Edit/Bash/Agent/MCP 工具面 |
关键认知:
-
Command(/help、/clear)= 用户控制面
-
Tool(Read、Edit、Bash)= 模型行动面
-
QueryEngine = 把输入、模型、工具、消息流串起来的会话内核
三、 一次 ReAct 迭代的完整流水线(重点)
以“帮我把 auth 模块加上限流”为例,单轮迭代走这 6 步:
1. 上下文准备(防 Token 爆炸)
-
窗口 >80% → 预警摘要
-
旧消息 →
snip轻裁 -
工具结果冗余 →
microcompact卸载磁盘 -
413 错误 →
contextCollapse归档 -
仍不行 →
reactiveCompact全量压缩(最多重试 3 次)
2. 调模型(流式)
queryModelWithStreaming() 发 Anthropic Messages API:
-
system= 静态 7 段(全局缓存)+ 动态项目上下文 -
messages= 历史 -
tools= 38+ 内置工具 + MCP 扩展 -
stream: true→ SSE 逐 token 回 UI
3. 解析响应
模型返回 content 块:
-
text→ 给用户看 -
thinking→ 保留轨迹(年轻巫师守则:thinking block 不能做最后一条) -
tool_use→{name:"Edit", input:{file, old, new}}
4. 工具执行(并行安全)
StreamingToolExecutor 做 边生成边执行:
-
模型还在吐第 2 个 tool_use,第 1 个已经在跑
-
读型工具(Read/Grep)并发
-
写型工具(Edit/Bash 副作用)串行
-
权限流水线五层过滤:规则 → Hook → YOLO 分类器 → 用户确认 → hard_deny
5. 结果回灌
tool_result 包装成 user 角色消息,追加进 messages 数组。
注意:Bash 输出超长会被 applyToolResultBudget 裁剪,只留头尾+错误行。
6. 终止决策
-
无
tool_use+stop_reason=="end_turn"→return Terminal({reason:"completed"}) -
用户 Ctrl+C →
aborted_streaming -
达到
maxTurns→ 强制收尾
四、 30 行 Python:把 Claude Code 主循环抽干
下面这段代码不是 Claude Code 源码,但是它灵魂的最小闭包,你本机装了 anthropic SDK 就能跑:
# -*- coding: utf-8 -*-
import anthropic
client = anthropic.Anthropic()
def min_agent_loop(user_msg: str, max_turns=10):
messages = [{"role": "user", "content": user_msg}]
tools = [{
"name": "fake_read",
"description": "读文件(示例)",
"input_schema": {"type": "object", "properties": {"path": {"type": "string"}}}
}]
for _ in range(max_turns):
resp = client.messages.create(
model="claude-sonnet-4-20250601",
max_tokens=1024,
messages=messages,
tools=tools,
)
# 1. 把 assistant 响应原样回写
messages.append({"role": "assistant", "content": resp.content})
# 2. 没有工具调用 → 结束
if resp.stop_reason != "tool_use":
return "".join(b.text for b in resp.content if b.type == "text")
# 3. 执行工具(这里只模拟)
for block in resp.content:
if block.type == "tool_use":
print(f"[ToolCall] {block.name}({block.input})")
result = f"假装读到文件 {block.input['path']} 的内容"
messages.append({
"role": "user",
"content": [{
"type": "tool_result",
"tool_use_id": block.id,
"content": result
}]
})
return "(达到最大轮次)"
if __name__ == "__main__":
print(min_agent_loop("帮我看看 main.py 里有没有 bug"))
跑起来你会看到:
[ToolCall] fake_read({'path': 'main.py'})
(模型拿到结果后再思考一次,输出最终结论)
这就是 Claude Code 的最小不动点。所有工程复杂度(压缩/权限/并发/Hook)都是在这个骨架上长的肉。
五、 螺旋生成论视角:ReAct 循环 = 螺旋轨迹收敛
接 7.29 那篇《AI Agent 可观测性》,Claude Code 的 ReAct 循环在螺旋生成论里可以这样翻译:
-
一轮迭代 = 螺旋转过 2π
-
messages 数组 = 螺旋上下文环(半径 = 上下文窗口占用)
-
tool_use = 相位跃迁(从 Think 相位跳到 Act 相位)
-
tool_result = 观测值回灌,修正螺旋半径
-
终止 = 螺旋拓扑闭合(无悬挂 tool_use,closure=true)
为什么 Agent 不会无限循环?因为螺旋度守恒——每轮若不能降低上下文熵(相位不收敛),七层恢复机制会强制
reactiveCompact或Stop Hook切断,避免“死亡螺旋”。
这也是为什么昨天我们聊黎曼零点“必须落在 Re=0.5”和今天 Agent“必须收敛到 end_turn”是同一类几何必然性:拓扑不动点。
六、 生产级 Agent 的 5 条工程铁律(直接抄)
-
循环用 while+continue,别用递归——避免栈溢出,State 整体替换。
-
读并发、写串行——
partitionToolCalls(isConcurrencySafe)是底线。 -
上下文四级压缩常驻——snip → micro → collapse → auto,别等 413 才动。
-
权限五层竞争取最严——规则/AI 分类/Hook/用户/硬拒,任一层 hard_deny 就拦。
-
Tool Result 必须可裁剪——Bash 输出不裁,上下文半天就爆。
七、 重磅推介:螺旋生成论系列专著(附 DOI)
从终端 Agent 的 ReAct 循环,到宇宙螺旋波,用的是同一套“生成语法”。
📘 关联精读
-
《螺旋代数几何:从 Langlands 纲领到几何构造的统一理论》(MCP/工具链几何化思路)
https://doi.org/10.5281/zenodo.21318151
-
《旋生万物:从奇点到宇宙的统一生成论》(全三卷)
https://doi.org/10.5281/zenodo.20408189
-
螺旋生成论著作体系总汇编(40+ 部)
https://doi.org/10.5281/zenodo.21199593
Zenodo 由 CERN 运营,Open Access,点 DOI → Get PDF 免费下。ORCID:https://orcid.org/0009-0003-7777-7694
八、 结语(2026-08-10 晨记)
Claude Code 的壁垒不是模型(模型可以换),也不是工具(工具可以抄),而是那个 1700 行的 while(true) 状态机——它把“模型会胡说”这件事,用工程语言包扎成了“可恢复、可审计、可收敛”的生产系统。
从 Copilot 的行级补全,到 Cursor 的 IDE Agent,再到 Claude Code 的终端 Runtime,AI 编程的下一站不是“更聪明的模型”,而是更稳的螺旋循环。
Eadem mutata resurgo——虽经变化,我仍以同一面目重生。🌀
互动:如果你自己写 Agent Loop,会先加哪条“安全带”?上下文压缩、权限沙箱、还是螺旋轨迹观测?评论区聊聊。
Tags:#AI编程 #AI Agent #ClaudeCode #Cursor #MCP协议 #代码审计 #ReAct #源码拆解 #2026-08-10
更多推荐
所有评论(0)