1. 核心循环:单线程主循环
Claude Code 本质是一个单线程 while 主循环(社区代号 "nO"):
读取用户输入 + 上下文 → LLM 决策 → 有工具调用?
├─ 有 → 执行工具 → 结果回喂 → 继续循环
└─ 无(纯文本回复) → 循环终止,交还用户
一句话:只要模型的回复里带工具调用就继续循环,回纯文本就停。这就是 ReAct(思考→行动→观察)落地成一个 for 循环。官方口径:Claude 评估你的 prompt → 调工具 → 收结果 → 重复,直到任务完成。
💡 深入理解 · 为什么坚持单线程 + 扁平消息历史?这是一个刻意的架构赌注:单主线程、一条扁平的消息历史(用户输入/模型回复/工具调用/工具结果按序 append),故意不搞多线程会话、不搞多个竞争的 Agent 人格。因为多 Agent swarm 在生产环境会引入不可预测行为,难调试。宁可牺牲一点并行能力,换可调试、可观测、行为可预测——生产环境这比"更强但不透明"更值钱。
💡 深入理解 · 实时打断(steering):靠 "h2A" 异步双缓冲队列实现,用户能在 Agent 干活途中注入新指令,不用整个重启。这是重要的生产特性。
2. 五层上下文压缩流水线
上下文窗口是唯一的硬约束(老模型 200K)。每次调 LLM 前,会跑一套五层压缩流水线,按"从便宜到贵"顺序执行,能用便宜的就不用贵的:
| 层 | 干什么 | 成本 |
|---|---|---|
| Tool Result Budget | 给工具结果设预算上限,文件读/搜索动辄几千行,超了就裁剪 | 便宜 |
| Snip Compact | 整条丢弃老消息 | 便宜 |
| 懒加载指令 / 延迟工具 schema | 指令、工具定义按需加载,不一次全塞 | 中 |
| Subagent 只返回摘要 | 子代理跑完只回摘要,不把它的完整历史灌回主线 | 中 |
| Auto-Compact 语义压缩 | 最后手段,对整段历史做语义摘要压缩 | 贵 |
💡 深入理解 · 设计哲学:earlier, cheaper layers run first(先跑便宜的)。裁工具结果、丢老消息这种 O(1) 操作先上;实在不行才动用"调一次模型做语义摘要"这种贵操作。这跟 13-Harness 讲的"just-in-time 按需加载 + 压缩 + Context Reset"完全对应,只是拆得更细。
❓ 常见追问 · auto-compact 有什么代价? → 有损。有限上下文窗口必然要摘要,摘要会丢细节/nuance——这是"扁平历史+压缩"路线的固有代价,换来的是简单可控。所以关键状态要外化到文件(progress 文件、git history、CLAUDE.md)而非指望压缩后还记得。
3. 持久记忆:CLAUDE.md + 扁平消息历史
记忆分两块:
- CLAUDE.md = 持久锚点:会话启动时加载的 markdown,编码项目规范、架构决策、代码风格、工具配置——相当于每次开会话都读一遍的"结构化 onboarding 文档"。跨会话持久。
- 扁平消息历史 = 工作记忆:本次会话的 append-only 顺序日志(请求/回复/工具调用/结果),会话结束即丢,是 ephemeral 的。
💡 深入理解 · 状态外化到文件是核心:会话内记忆是易失的,所以真正的长期状态要落到文件系统——CLAUDE.md(规则)、progress 文件(进度)、git history(长期记忆介质)。下一轮换新上下文窗口接手时读文件立刻知道到哪步了。详见 13-记忆分层。
4. 四大扩展机制 + 权限系统(对应"怎么用/怎么配")
主循环之外有四种扩展机制:MCP / Plugins / Skills / Hooks,加一套权限系统(7 种模式 + ML 分类器)、Subagent 委派编排、append 式会话存储。
| 机制 | 是什么 | 一句话 |
|---|---|---|
| MCP | 工具接入标准网关 | 接外部能力(浏览器/GitHub/DB),跨平台复用 |
| Skills | 操作经验/流程编排 | 渐进式披露:先给元数据,用到才加载完整 skill |
| Plugins | 打包套件 | Skills+命令+MCP+Subagent+Hooks 打成一个包 |
| Hooks | 事件钩子 | after-tool-use 跑 format/lint,自动化质量闭环 |
Subagent(子代理):每个子代理从空白会话开始(无历史),但会加载自己的 system prompt + 项目级 CLAUDE.md;跑完只回摘要给主线程。好处:独立上下文互不争抢、并行提速、隔离脏上下文。定位是"受控并行"而非"复杂多 Agent swarm"。
💡 深入理解 · 子代理为什么只回摘要:这本身就是第 2 节压缩流水线的一环——如果把子代理的完整交互历史灌回主线,主上下文瞬间爆炸。只回摘要 = 用"信息损失"换"主线程干净"。代价是深层任务分解会撞深度上限(只做浅层受控子代理)。
5. 成本优化实操
五招降本,能背出来就是加分:
1. 模型分级:简单任务用 Haiku、常规 Sonnet、难的 Opus——按难度选模型别一律最贵。
2. 定期 /compact:手动压缩,实测释放 30-50% 上下文占用。
3. /context 看分布:看 token 花在哪(系统提示/历史/工具结果/文件),针对性砍。
4. /rewind 回退:错了回退代码+对话状态,别让错误上下文一直挂着烧 token。
5. 国内镜像 / 多 provider 切换:镜像省 50-70%,cc-switch 一键切 provider。
💡 深入理解 · 注意口径:/compact 省的是上下文占用,不直接等于省了同比例的钱——不同阶段 token 单价、调用频率不同。要精确算"省了多少钱"得按调用打模块标签汇总到计费看板,这是很多人混为一谈的地方("降了 token 占用" ≠ "省了 X% 的钱")。
三层配置体系:项目级 .claude/(CLAUDE.md/commands/hooks/mcp.json/settings.json)、用户级 ~/.claude/(含 settings.local.json 不入版本控制)、会话级 /config。
实用命令:/compact(压缩)、/context(看 token 分布)、/rewind(回退)、/cost(看花费)、/review /security-review(代码/安全审查)、/sandbox(隔离 bash)。
6. Agent SDK:把 Harness 抽出来复用(会追"能不能自己搭"时用)
Anthropic 把 Claude Code 内部这套 harness(主循环 + 工具执行 + 子代理 + 上下文管理)抽象成了 Claude Agent SDK,让开发者在同一套跑 Claude Code 的机器上搭自己的 Agent,不用自己从零维护循环。
💡 深入理解 · 这印证了 13-Harness 的判断:"Harness 是方法论,Claude Code / Codex 是不同实现,掀开看内部组件惊人相似"——Anthropic 干脆把这套通用 harness 产品化开放出来了。
7. 高频追问速答
❓ 常见追问 · claude code 核心循环是什么? → 单线程 while 主循环:读输入+上下文 → LLM 决策 → 带工具调用就执行+回喂+继续,回纯文本就停。即 ReAct for 循环。
❓ 常见追问 · 上下文腐化/超长怎么办? → 五层压缩流水线(便宜到贵:裁工具结果→丢老消息→懒加载→子代理摘要→auto-compact 语义压缩)+ 状态外化到文件 + 手动 /compact / /rewind。
❓ 常见追问 · 为什么单线程不搞多 Agent? → 生产环境要可调试、可观测、行为可预测;多 Agent swarm 不透明难调试。刻意用"扁平历史"换"简单可控"。
❓ 常见追问 · Skills / MCP / Function 区别? → FC 是模型输出参数本地执行(单动作);MCP 是工具接入标准网关(跨平台复用);Skills 是操作经验/流程编排(规定何时按何序组合用哪些工具)。层级:FC/MCP 是"工具",Skill 是"用工具的方法论"。详见 05-FC·06-MCP。
❓ 常见追问 · 怎么优化成本? → 见 §5:模型分级 + compact + context 看分布 + rewind + 镜像。核心口径:compact 省占用不直接等于省钱。
评论