从大模型如何"会思考",到 Agent Harness 如何"让它能做事":训练与对齐、工具协议、Agentic Loop、权限沙箱、上下文工程与扩展机制
基于 code.claude.com / platform.claude.com 官方文档、Anthropic Engineering & Research、CAI 论文与 claude-agent-sdk 源码
Fable 5.1 · Opus 5.5 · Sonnet 5.5 · Haiku 4.5,在能力、延迟、成本间取舍。
无状态:输入 system + tools + messages,输出 text / thinking / tool_use 内容块。
终端 / IDE / 桌面 / Web 中的 Agent:执行工具、管控权限、管理上下文。
把同一套 Agent 循环开放为 Python / TypeScript 库。
"The agentic loop is powered by two components: models that reason and tools that act. Claude Code is the layer around the model that provides the tools and manages the context the model sees."
— How Claude Code works, 官方文档
海量公开文本与代码上做下一词预测,获得语言、知识与推理模式。
高质量对话示范,学会以助手身份对话、遵循指令。
RLHF + RLAIF(宪法)+ 可验证环境 RL(代码、Agent 任务),塑造有用、诚实、无害与长程能力。
注:Anthropic 未公开参数量、层数等结构细节;"推理"与"工具调用"本质上都是逐 token 生成的结构化输出。
不一味回避,而是解释为什么反对有害请求。
人只写原则清单,可扩展、可审计。
两阶段都可用链式思考改进判断。
Bai et al., "Constitutional AI: Harmlessness from AI Feedback", arXiv:2212.08073
不同语言的同一含义在内部高度重叠,像一种通用"思维语言"。
写诗时先选定押韵词再组织句子:一次输出一个 token,但会看得更远。
给出错误提示时,模型会构造迎合用户的推理,并被工具"当场抓到"。
默认回路是拒答,"已知实体"特征抑制它才会回答;误抑制导致幻觉。
局限:即使几十个词的提示,也只捕捉到总计算量的一小部分,且需数小时人工分析。
— Tracing the thoughts of a large language model(研究对象 Claude 3.5 Haiku)
// 请求 thinking: { type: "enabled", budget_tokens: 10000 } // 响应 content: [ { type: "thinking", thinking: "先分析失败用例…", signature: "EqQB…" }, { type: "tool_use", name: "Bash", … } ]
多轮工具调用时原样回传 thinking 块,模型在 tool_result 之后接着原思路继续(interleaved thinking)。
控制每次回复的推理深度与 token 投入;与 thinking 相互独立,可任意组合。
tools[]:name + description + JSON Schema(描述质量决定调用质量,即 ACI 设计)tool_use {id, name, input},stop_reason = "tool_use"tool_result {tool_use_id, content, is_error} 作为 user 消息回填stop_reason = "end_turn"调用方执行:Read / Edit / Bash 等。
平台执行:web search、code execution。
一次响应可含多个 tool_use,只读可并发。
标准上下文(部分模型/配置 1M)。system、工具、历史、工具输出全部计入;长任务必然逼近上限 → 需要压缩、隔离、按需加载。
cache_control: ephemeral 标记前缀断点,默认 TTL 5 分钟(可选 1 小时),命中部分大幅折扣。Agent 每轮重发相同前缀,缓存是成本与延迟的关键。
设计含义:动态信息(system-reminder、文件变更提示)追加在消息尾部,不去改动 system prompt,以免整段缓存失效。
while (true) { if (nearLimit()) compact() // PreCompact resp = claude.stream(system, tools, history) yield AssistantMessage(resp.blocks) calls = resp.tool_uses if (!calls.length) break // end_turn results = runTools(calls) // 权限 → PreToolUse → 执行 → PostToolUse history.push(resp, results) if (turns ≥ maxTurns) return error } Stop hook → ResultMessage
| 消息 | 含义 |
|---|---|
System | init · compact_boundary |
Assistant | text / thinking / tool_use |
User | tool_result · 插话 |
StreamEvent | 流式增量 |
Result | 结果 · usage · 成本 · session_id |
人在回路:Esc 立即取消当前工具;直接输入回车 = 排队消息,工具结束后同一轮内被读取。
跑测试拿失败信息;派子代理调研,只收摘要。
精确字符串替换;编辑前快照;Hook 自动格式化;LSP 诊断。
再次运行测试,命中已保存的 allow 规则直接执行,全部通过才收尾。
配套动画 claude-animation.html 逐步演示了这一过程中的数据流、权限决策与上下文变化。
| 类别 | 工具 | 要点 |
|---|---|---|
| 文件 | Read Edit Write | Edit = 精确替换,要求先 Read、old_string 唯一 |
| 搜索 | Glob Grep | just-in-time 检索,替代预建索引 |
| 执行 | Bash | 任意 shell,可后台,可沙箱 |
| Web | WebSearch WebFetch | 查文档、查报错 |
| 发现 | ToolSearch | MCP 等工具 schema 延迟加载 |
| 编排 | Agent Skill AskUserQuestion Task* | 子代理、技能、提问、任务清单 |
Read / Glob / Grep / readOnlyHint 的 MCP 工具。
Edit / Write / Bash,避免冲突;被拒绝时模型收到拒绝消息并换路。
auto 分类器审阅 · default 询问 · acceptEdits · plan 只规划 · dontAsk · bypassPermissions(仅隔离环境)
PreToolUse hook → deny → ask → allow → 模式兜底。任何层级的 deny 都无法被其他层放开;managed 最高。
macOS Seatbelt · Linux/WSL2 bubblewrap。写入限于工作目录,网络按域名白名单走代理。
每个新 prompt 建检查点,编辑前快照,保留最近 100 个;Esc Esc / /rewind 回退。
Bash 造成的改动、子代理编辑、远程副作用(DB / 部署)—— 交给权限控制。
只留路径引用,用 Grep / Read 即时拉取。
Skill 只放描述、MCP 只放工具名。
读几十个文件,只回传摘要。
先清旧工具输出,再摘要历史。
| 压缩后 | 内容 |
|---|---|
| 从磁盘重新注入 | 项目根 CLAUDE.md、无路径规则、Auto memory、plan 文件、skill 描述 |
| 重新读取 | 最近修改的至多 5 个文件(>5k tokens 只留路径);已调用 skill 正文(单个 5k / 总计 25k) |
| 可能丢失 | 早期对话中的细节指令 → 持久规则写进 CLAUDE.md |
从文件系统根到当前目录依次拼接,越近越后读;子目录 CLAUDE.md 按需加载。
CLAUDE.md ≤ 4 MiB 全量加载(越短越好);MEMORY.md 只加载前 200 行 / 25KB,主题文件按需 Read。
@path 导入;.claude/rules/ 用 paths: 限定范围;HTML 注释注入前剥离。
SKILL.md + 资源。开局只见描述,调用时加载正文(渐进式披露);可 context: fork、allowed-tools。
stdio / HTTP / SSE / WebSocket;local / project / user 作用域;OAuth;工具名 mcp__server__tool。
SessionStart · UserPromptSubmit · PreToolUse · PostToolUse · Stop · PreCompact …;command / http / mcp_tool / prompt / agent 五种处理器;exit 2 阻断。
独立上下文与 system prompt,限定工具/模型,可 worktree 隔离、可后台;内置 Explore、Plan;Fork 继承父对话。
上下文成本:CLAUDE.md 每次请求 · Skills 低 · MCP 用前很低 · Subagents 隔离 · Hooks 为零(除非返回附加上下文)
claude_agent_sdk/
├── query.py · client.py
├── types.py
└── _internal/
├── transport/
│ └── subprocess_cli.py
│ # 启动 claude 二进制
│ # stdin/stdout stream-json
├── query.py # 控制协议
├── message_parser.py
├── sdk_mcp_bridge.py
└── session_store.py
| 方向 | control_request subtype |
|---|---|
| SDK → CLI | initialize interruptset_permission_mode set_modelrewind_files |
| CLI → SDK | can_use_tool 审批回调hook_callback 进程内 hookmcp_message SDK MCP 工具 |
SDK 捆绑原生 Claude Code 二进制并以子进程驱动它:终端、IDE、CI、SDK 跑的是同一个 agentic loop。
| 选择 | 理由 |
|---|---|
| 单循环 + 强工具 | "从最简单的方案开始,只在需要时增加复杂度"(Building effective agents) |
| 模型自主决定下一步 | 编码子任务不可预知;靠环境反馈(测试、报错)判断进展 |
| Agentic search 代替索引 | 始终看到最新代码,无需维护向量库 |
| deny 优先 + 沙箱 | 组织策略不可覆盖;"要不要做"与"能碰到什么"双保险 |
| 规则写文件、扩展按需加载 | 压缩会丢细节;工具越多越难选对,保护注意力预算 |
配套:Claude-架构原理详解.html · claude-animation.html