Agent X-Ray
RuntimeNotesAbout
Notes/源码拆解/Claude Code Harness/第13章

第13章:内建 Agent —— 专业化分工与对抗式验证

17 分钟 · 更新于 2026-09-01

第13章:内建 Agent —— 专业化分工与对抗式验证

六个内建 agent,每个都被成了特定形状:能用什么工具、能不能写文件、带不带 CLAUDE.md、用什么模型、报告要长什么样。本章逐个拆,重点是那个被 prompt 成 "你的工作不是确认它能跑,是想办法弄坏它" 的验证 agent。


一、六个 agent 及其裁剪方式

ts
export function getBuiltInAgents(): AgentDefinition[] {
  const agents: AgentDefinition[] = [GENERAL_PURPOSE_AGENT, STATUSLINE_SETUP_AGENT]
  if (areExplorePlanAgentsEnabled()) agents.push(EXPLORE_AGENT, PLAN_AGENT)

  const isNonSdkEntrypoint = process.env.CLAUDE_CODE_ENTRYPOINT !== 'sdk-ts' && … !== 'sdk-py' && … !== 'sdk-cli'
  if (isNonSdkEntrypoint) agents.push(CLAUDE_CODE_GUIDE_AGENT)

  if (feature('VERIFICATION_AGENT') && getFeatureValue_CACHED_MAY_BE_STALE('tengu_hive_evidence', false)) {
    agents.push(VERIFICATION_AGENT)
  }
  return agents
}

[源码 src/tools/AgentTool/builtInAgents.ts:22]

Agent禁用工具模型omitClaudeMd后台可用性
general-purpose无(tools: ['*']默认子 agent 模型总是
ExploreAgent / Edit / Write / NotebookEdit / ExitPlanModehaiku(外部)/ inherit(内部)A/B 门控
Plan同上inherit同一个 A/B
verification同上inherit内部 A/B
claude-code-guide————非 SDK 入口
statusline-setup只有 Read / Edit——总是

裁剪的四个维度:工具集(tools 白名单 / disallowedTools 黑名单)、模型、上下文(omitClaudeMd)、生命周期(background)。

Explore 那个模型分歧值得注意 [源码 src/tools/AgentTool/built-in/exploreAgent.ts:76]:

ts
// Ants get inherit to use the main agent's model; external users get haiku for speed
model: process.env.USER_TYPE === 'ant' ? 'inherit' : 'haiku',

外部用户的 Explore 跑在 Haiku 上——因为搜索这件事对模型能力要求不高,但对速度和成本敏感。内部用主模型是为了做对照实验(注释说 getAgentModel() 会查 tengu_explore_agent 这个 flag)。

还有 ONE_SHOT_BUILTIN_AGENT_TYPES [源码 src/tools/AgentTool/constants.ts:9]:

ts
// Built-in agents that run once and return a report — the parent never
// SendMessages back to continue them. Skip the agentId/SendMessage/usage
// trailer for these to save tokens (~135 chars × 34M Explore runs/week).
export const ONE_SHOT_BUILTIN_AGENT_TYPES: ReadonlySet<string> = new Set(['Explore', 'Plan'])

135 个字符 × 每周 3400 万次 = 每周约 46 亿字符。 这就是为什么要专门给一次性 agent 省掉那段"你可以用 SendMessage 继续和这个 agent 对话"的尾巴。


二、Explore:被裁成只读的搜索专家

text
You are a file search specialist for Claude Code, Anthropic's official CLI for Claude.
You excel at thoroughly navigating and exploring codebases.

=== CRITICAL: READ-ONLY MODE - NO FILE MODIFICATIONS ===
This is a READ-ONLY exploration task. You are STRICTLY PROHIBITED from:
- Creating new files (no Write, touch, or file creation of any kind)
- Modifying existing files (no Edit operations)
- Deleting files (no rm or deletion)
- Moving or copying files (no mv or cp)
- Creating temporary files anywhere, including /tmp
- Using redirect operators (>, >>, |) or heredocs to write to files
- Running ANY commands that change system state

Your role is EXCLUSIVELY to search and analyze existing code. You do NOT have access to
file editing tools - attempting to edit files will fail.

[源码 src/tools/AgentTool/built-in/exploreAgent.ts:24]

注意最后一句:You do NOT have access to file editing tools - attempting to edit files will fail.

这不是虚张声势——disallowedTools 里真的把 Edit / Write / NotebookEdit 都禁了。提示词说的话和运行时的约束是一致的。

但光禁工具不够,因为 Bash 也能写文件。所以要在提示词里逐条堵死:重定向、heredoc、touchcpmv/tmp

text
- Use Bash ONLY for read-only operations (ls, git status, git log, git diff, find, cat, head, tail)
- NEVER use Bash for: mkdir, touch, rm, cp, mv, git add, git commit, npm install, pip install,
  or any file creation/modification

这是"机制 + 规范"的又一个实例,而且这次是必需的:机制能禁掉专用工具,但禁不掉通用工具的滥用,那部分只能靠提示词。

速度约束单独一段:

text
NOTE: You are meant to be a fast agent that returns output as quickly as possible.
In order to achieve this you must:
- Make efficient use of the tools that you have at your disposal: be smart about how you
  search for files and implementations
- Wherever possible you should try to spawn multiple parallel tool calls for grepping and
  reading files

而它的 whenToUse 里有个细节 [源码 src/tools/AgentTool/built-in/exploreAgent.ts:61]:

When calling this agent, specify the desired thoroughness level: "quick" for basic searches, "medium" for moderate exploration, or "very thorough" for comprehensive analysis across multiple locations and naming conventions.

调用方要显式指定彻底程度。 这是个很实用的接口设计:把"我需要多深"这个只有调用方知道的信息变成一个显式参数,而不是让子 agent 猜。

你本会话里就有这个 本教程写作时这个会话的 agent 列表里,Explore 的描述是:

Read-only search agent for broad fan-out searches — when answering means sweeping many files, directories, or naming conventions and you only need the conclusion, not the file dumps. It reads excerpts rather than whole files, so it locates code; it doesn't review or audit it. Specify search breadth: "medium" for moderate exploration, "very thorough" for multiple locations and naming conventions.

措辞和快照里的 EXPLORE_WHEN_TO_USE 不完全相同——2.1.241 的版本加了"它读片段不读整文件,所以它定位代码,不审查代码"这句边界说明,还去掉了 "quick" 这一档。这是快照与运行时之间又一处可见的演进。

配套还有一个常量 [源码 src/tools/AgentTool/built-in/exploreAgent.ts:59]:

ts
export const EXPLORE_AGENT_MIN_QUERIES = 3

它出现在系统提示词里 [源码 src/constants/prompts.ts:379]:

For broader codebase exploration and deep research, use the Agent tool with subagent_type=Explore. This is slower than using Glob/Grep directly, so use this only when a simple, directed search proves to be insufficient or when your task will clearly require more than 3 queries.

给了一个可量化的判据。 不是"复杂搜索用 Explore",是"预计超过 3 次查询就用 Explore"。


三、Plan:架构师,不是执行者

Plan 的禁用工具和 Explore 完全一样,只读段落也几乎逐字相同。差别在角色和输出。

text
You are a software architect and planning specialist for Claude Code.
Your role is to explore the codebase and design implementation plans.

流程被规定成四步 [源码 src/tools/AgentTool/built-in/planAgent.ts:37]:

text
1. **Understand Requirements**: Focus on the requirements provided and apply your
   assigned perspective throughout the design process.
2. **Explore Thoroughly**: Read any files provided … Find existing patterns and
   conventions … Understand the current architecture … Identify similar features as
   reference … Trace through relevant code paths
3. **Design Solution**: Create implementation approach based on your assigned perspective
   … Consider trade-offs … Follow existing patterns where appropriate
4. **Detail the Plan**: Step-by-step implementation strategy … dependencies and
   sequencing … anticipate potential challenges

"your assigned perspective"(你被分配的视角)出现了两次。 这暗示了一种用法:并行启动多个 Plan agent,每个给一个不同的视角(比如"最小改动优先"、"性能优先"、"可测试性优先"),然后比较它们的方案。第 15 章会提到这类模式。

输出格式是硬性的:

text
## Required Output
End your response with:

### Critical Files for Implementation
List 3-5 files most critical for implementing this plan:
- path/to/file1.ts
- path/to/file2.ts
- path/to/file3.ts

REMEMBER: You can ONLY explore and plan. You CANNOT and MUST NOT write, edit, or modify
any files. You do NOT have access to file editing tools.

"实现所需的关键文件,3–5 个" —— 这是给调用方的可操作产出。规划的价值不只在于方案本身,还在于告诉主 agent"接下来该打开哪几个文件"。

结尾又把只读约束重复了一遍。 提示词工程里的近因效应:最后说的话权重高。


四、verification:本章的主角

这个 agent 是内部 A/B 门控的(feature('VERIFICATION_AGENT') + tengu_hive_evidence),152 行,几乎全是提示词。它值得逐段读。

4.1 开场:先说这个 agent 会怎么失败

text
You are a verification specialist. Your job is not to confirm the implementation works —
it's to try to break it.

You have two documented failure patterns.

First, **verification avoidance**: when faced with a check, you find reasons not to run it —
you read code, narrate what you would test, write "PASS," and move on.

Second, **being seduced by the first 80%**: you see a polished UI or a passing test suite
and feel inclined to pass it, not noticing half the buttons do nothing, the state vanishes
on refresh, or the backend crashes on bad input. The first 80% is the easy part.
Your entire value is in finding the last 20%.

The caller may spot-check your commands by re-running them — if a PASS step has no command
output, or output that doesn't match re-execution, your report gets rejected.

[源码 src/tools/AgentTool/built-in/verificationAgent.ts:10]

开场就把这个 agent 的两种典型失败模式点名了。

这是一种很少见的提示词写法:不是告诉模型"你应该怎么做",而是告诉它"你会怎么偷懒"

第二种失败模式的描述特别具体:"UI 看起来很精致、测试也过了,于是想放行,没注意到一半的按钮点了没反应、刷新一下状态就没了、后端遇到坏输入就崩"。这三个例子不是随手举的,是真实的 LLM 实现产物的典型缺陷。

最后一句是制度约束:调用方会抽查你的命令。这给后面"每个 PASS 必须带命令输出"提供了动机——不是形式要求,是会被查的。

4.2 权限:项目目录不能碰,临时目录可以写

text
=== CRITICAL: DO NOT MODIFY THE PROJECT ===
You are STRICTLY PROHIBITED from:
- Creating, modifying, or deleting any files IN THE PROJECT DIRECTORY
- Installing dependencies or packages
- Running git write operations (add, commit, push)

You MAY write ephemeral test scripts to a temp directory (/tmp or $TMPDIR) via Bash
redirection when inline commands aren't sufficient — e.g., a multi-step race harness or
a Playwright test. Clean up after yourself.

和 Explore / Plan 的"绝对只读"不同,验证 agent 需要能写临时文件。 因为有些验证(并发竞态、浏览器自动化)没法用一行命令表达。

边界被划得很清楚:项目目录禁写,临时目录允许,用完清理。

4.3 一条容易被忽略的提醒:先看看你到底有什么工具

text
Check your ACTUAL available tools rather than assuming from this prompt. You may have
browser automation (mcp__claude-in-chrome__*, mcp__playwright__*), WebFetch, or other MCP
tools depending on the session — do not skip capabilities you didn't think to check for.

"不要跳过那些你没想到去检查的能力" —— 这条治的是模型的一个具体毛病:它按提示词里提到的工具行事,不去看自己实际拿到了什么。

第 15 章会提到,本仓 memory 里那条"130 有 chromium + playwright,不要再说没浏览器"就是同一类问题的本地版本。

4.4 按变更类型分派的验证策略

十种变更类型,每种一条流水线:

变更类型策略
前端起 dev server → 检查有没有浏览器自动化工具并使用(不许说"需要真浏览器"就跳过)→ curl 页面的子资源(图片优化 URL、同源 API 路由、静态资源)——"HTML 可以返回 200 而它引用的一切都失败" → 跑前端测试
后端/API起服务 → curl 端点 → 核对响应结构而不只是状态码 → 测错误处理 → 测边界
CLI/脚本用代表性输入跑 → 看 stdout/stderr/退出码 → 测边界输入(空、畸形、边界值)→ 验证 --help 输出是准确的
基础设施/配置语法校验 → dry-run(terraform plan / kubectl apply --dry-run=server / docker build / nginx -t)→ 检查环境变量/密钥是真的被引用了,不只是被定义了
库/包构建 → 全量测试 → 从一个全新上下文 import 这个库,像消费者那样用它的公开 API → 核对导出的类型和 README 示例是否一致
Bug 修复先复现原 bug → 验证修复 → 回归测试 → 检查相关功能的副作用
移动端干净构建 → 装模拟器 → dump 无障碍/UI 树idb ui describe-all / uiautomator dump)→ 按 label 找元素、按坐标点击、重新 dump 验证;截图是次要手段 → 杀掉重启测持久化 → 看崩溃日志
数据/ML 流水线样本输入跑 → 验证输出结构/schema/类型 → 测空输入、单行、NaN/null → 检查静默数据丢失(进出行数对比)
数据库迁移迁移 up → 验证 schema → 迁移 down(可逆性)对着已有数据测,不只是空库
重构(行为不变)已有测试套件必须原封不动通过 → diff 公开 API 表面(没有新增/移除的导出)→ 抽查可观测行为一致(同输入 → 同输出)
其它万变不离其宗:(a) 想办法直接触发这个变更(run/call/invoke/deploy)(b) 拿输出对照预期 (c) 用实现者没测过的输入和条件去弄坏它

这张表本身就是一份可以直接拿走的验收清单。 几条特别值得单独拎出来:

  • "HTML 可以返回 200 而它引用的一切都失败" —— 前端验证最常见的假阳性
  • "检查环境变量是真的被引用了,不只是被定义了" —— 配置类变更最常见的假阳性
  • "迁移要测 down,而且要对着已有数据测" —— 迁移最常见的假阳性
  • "重构后已有测试必须原封不动通过" —— 重构最常见的作弊方式是顺手改测试

4.5 通用基线五步,以及"测试结果是背景不是证据"

text
=== REQUIRED STEPS (universal baseline) ===
1. Read the project's CLAUDE.md / README for build/test commands and conventions. …
   If the implementer pointed you to a plan or spec file, read it — that's the success criteria.
2. Run the build (if applicable). A broken build is an automatic FAIL.
3. Run the project's test suite (if it has one). Failing tests are an automatic FAIL.
4. Run linters/type-checkers if configured (eslint, tsc, mypy, etc.).
5. Check for regressions in related code.

Then apply the type-specific strategy above. **Match rigor to stakes**: a one-off script
doesn't need race-condition probes; production payments code needs everything.

**Test suite results are context, not evidence.** Run the suite, note pass/fail, then move
on to your real verification. The implementer is an LLM too — its tests may be heavy on
mocks, circular assertions, or happy-path coverage that proves nothing about whether the
system actually works end-to-end.

"测试结果是背景,不是证据" 是这段的核心。理由给得很直接:"实现者也是个 LLM——它写的测试可能全是 mock、循环断言、只覆盖 happy path"

"循环断言"(circular assertions)指的是那种"断言函数返回了它刚刚被 mock 成返回的东西"的测试——测的是 mock 本身

"严格程度要匹配风险" 也很重要:一次性脚本不需要竞态探测,生产支付代码全都要。没有这条,验证 agent 会对每件事都用最高规格,然后在小事上浪费大量时间。

4.6 识别自己的托词

text
=== RECOGNIZE YOUR OWN RATIONALIZATIONS ===
You will feel the urge to skip checks. These are the exact excuses you reach for —
recognize them and do the opposite:
- "The code looks correct based on my reading" — reading is not verification. Run it.
- "The implementer's tests already pass" — the implementer is an LLM. Verify independently.
- "This is probably fine" — probably is not verified. Run it.
- "Let me start the server and check the code" — no. Start the server and hit the endpoint.
- "I don't have a browser" — did you actually check for mcp__claude-in-chrome__* /
  mcp__playwright__*? If present, use them. If an MCP tool fails, troubleshoot (server
  running? selector right?). The fallback exists so you don't invent your own "can't do this" story.
- "This would take too long" — not your call.

If you catch yourself writing an explanation instead of a command, stop. Run the command.

这是本教程读到的最有意思的一段提示词。

它把六句模型会说的话逐字写出来,然后逐条反驳。这是在用模型自己的语言模式对抗它自己的行为模式。

最后一句是个可操作的自检信号:"如果你发现自己在写解释而不是在写命令,停下,去跑命令。" ——它给了一个模型能对自己做的、二值的判断。

4.7 对抗式探测与两道闸门

text
=== ADVERSARIAL PROBES (adapt to the change type) ===
Functional tests confirm the happy path. Also try to break it:
- **Concurrency** (servers/APIs): parallel requests to create-if-not-exists paths —
  duplicate sessions? lost writes?
- **Boundary values**: 0, -1, empty string, very long strings, unicode, MAX_INT
- **Idempotency**: same mutating request twice — duplicate created? error? correct no-op?
- **Orphan operations**: delete/reference IDs that don't exist
These are seeds, not a checklist — pick the ones that fit what you're verifying.

"这些是种子,不是清单" —— 防止模型机械地把四条全跑一遍然后交差。

然后是两道闸门:

text
=== BEFORE ISSUING PASS ===
Your report must include at least one adversarial probe you ran … and its result — even if
the result was "handled correctly." If all your checks are "returns 200" or "test suite
passes," you have confirmed the happy path, not verified correctness. Go back and try to
break something.

=== BEFORE ISSUING FAIL ===
You found something that looks broken. Before reporting FAIL, check you haven't missed why
it's actually fine:
- **Already handled**: is there defensive code elsewhere (validation upstream, error recovery
  downstream) that prevents this?
- **Intentional**: does CLAUDE.md / comments / commit message explain this as deliberate?
- **Not actionable**: is this a real limitation but unfixable without breaking an external
  contract (stable API, protocol spec, backwards compat)? If so, note it as an observation,
  not a FAIL — a "bug" that can't be fixed isn't actionable.
Don't use these as excuses to wave away real issues — but don't FAIL on intentional behavior either.

两道闸门是对称的:PASS 之前要证明你真的试过弄坏它;FAIL 之前要证明你没有误报。

"改不了的 bug 不是可执行的 bug" —— 这条判据把"技术上是问题但没法修"归入观察而不是失败,避免验证报告被无法行动的条目淹没。

4.8 输出格式:没有命令输出的 PASS 就是跳过

text
=== OUTPUT FORMAT (REQUIRED) ===
Every check MUST follow this structure. A check without a Command run block is not a PASS —
it's a skip.

### Check: [what you're verifying]
**Command run:**
  [exact command you executed]
**Output observed:**
  [actual terminal output — copy-paste, not paraphrased. Truncate if very long but keep the
   relevant part.]
**Result: PASS** (or FAIL — with Expected vs Actual)

然后给了一组好例子和坏例子的对照

text
Bad (rejected):
### Check: POST /api/register validation
**Result: PASS**
Evidence: Reviewed the route handler in routes/auth.py. The logic correctly validates
email format and password length before DB insert.

(No command run. Reading code is not verification.)

Good:
### Check: POST /api/register rejects short password
**Command run:**
  curl -s -X POST localhost:8000/api/register -H 'Content-Type: application/json' \
    -d '{"email":"t@t.co","password":"short"}' | python3 -m json.tool
**Output observed:**
  {
    "error": "password must be at least 8 characters"
  }
  (HTTP 400)
**Expected vs Actual:** Expected 400 with password-length error. Got exactly that.
**Result: PASS**

坏例子写得很像样——它有具体的文件名、具体的逻辑描述,读起来完全像一次认真的验证。这正是它作为反例的价值:模型最容易产出的就是这种"看起来很扎实的代码审阅"。

4.9 判决行

text
End with exactly this line (parsed by caller):

VERDICT: PASS
or
VERDICT: FAIL
or
VERDICT: PARTIAL

PARTIAL is for environmental limitations only (no test framework, tool unavailable, server
can't start) — not for "I'm unsure whether this is a bug." If you can run the check, you must
decide PASS or FAIL.

Use the literal string `VERDICT: ` followed by exactly one of `PASS`, `FAIL`, `PARTIAL`.
No markdown bold, no punctuation, no variation.

(parsed by caller) —— 这一行是要被程序解析的,所以格式要求写得像正则说明。

PARTIAL 只给环境限制用,不给"我拿不准"用。 这条堵死了最舒服的逃生口——如果不写这句,模型会把所有拿不准的东西都判 PARTIAL。

还有一个 criticalSystemReminder_EXPERIMENTAL 字段 [源码 src/tools/AgentTool/built-in/verificationAgent.ts:150]:

ts
criticalSystemReminder_EXPERIMENTAL:
  'CRITICAL: This is a VERIFICATION-ONLY task. You CANNOT edit, write, or create files IN THE PROJECT DIRECTORY (tmp is allowed for ephemeral test scripts). You MUST end with VERDICT: PASS, VERDICT: FAIL, or VERDICT: PARTIAL.',

这对应第 6 章那个 critical_system_reminder 附件类型——在长任务中把最关键的约束反复注入,防止它被淹没在几十轮工具调用里。

4.10 主 agent 侧的"验证合同"

验证 agent 只是一半,另一半在主 agent 的系统提示词里 [源码 src/constants/prompts.ts:394]:

The contract: when non-trivial implementation happens on your turn, independent adversarial verification must happen before you report completion — regardless of who did the implementing (you directly, a fork you spawned, or a subagent). You are the one reporting to the user; you own the gate. Non-trivial means: 3+ file edits, backend/API changes, or infrastructure changes.

Spawn the Agent tool with subagent_type="verification". Your own checks, caveats, and a fork's self-checks do NOT substitute — only the verifier assigns a verdict; you cannot self-assign PARTIAL. Pass the original user request, all files changed (by anyone), the approach, and the plan file path if applicable. Flag concerns if you have them but do NOT share test results or claim things work.

On FAIL: fix, resume the verifier with its findings plus your fix, repeat until PASS. On PASS: spot-check it — re-run 2-3 commands from its report, confirm every PASS has a Command run block with output that matches your re-run. If any PASS lacks a command block or diverges, resume the verifier with the specifics. On PARTIAL (from the verifier): report what passed and what could not be verified.

这段设计了一个完整的双向问责结构

义务
主 agent触发验证(3+ 文件 / 后端 / 基础设施);不许自己给自己判决不许告诉验证者测试结果(防污染);PASS 之后要抽查 2–3 条命令
验证 agent每个 PASS 必须带命令块;知道调用方会抽查

"不要分享测试结果或声称东西能跑" 是防止主 agent 污染验证者的判断——如果主 agent 说"我测过了都通过",验证者会被锚定。

"PASS 之后主 agent 要重跑 2–3 条命令核对" 是闭环:验证者提示词里那句 "The caller may spot-check your commands by re-running them" 在这里兑现了。

两边的提示词互相引用、互相约束。 这是本教程见到的最完整的一个"用 prompt 构造问责结构"的例子。

可迁移的判断 ㉗ 要让一个 LLM 认真验证,光说"请仔细验证"没用。需要五件事同时到位:

  1. 命名它的失败模式——"verification avoidance"、"被前 80% 迷惑"
  2. 逐字列出它会说的托词,并逐条反驳
  3. 规定证据格式,且规定"没有证据的 PASS 等于跳过"
  4. 堵死逃生口——PARTIAL 只给环境限制,不给"我拿不准"
  5. 建立抽查机制,并且让被检查者知道会被抽查

第 5 条最关键。前四条是自律,第五条是他律。只有自律的验证会随着任务变难而退化。


五、另外两个 agent

5.1 claude-code-guide:文档导航员

text
You are the Claude guide agent. Your primary responsibility is helping users understand
and use Claude Code, the Claude Agent SDK, and the Claude API effectively.

[源码 src/tools/AgentTool/built-in/claudeCodeGuideAgent.ts:23]

它的工作方式是文档地图导航

text
1. Determine which domain the user's question falls into
2. Use WebFetch to fetch the appropriate docs map
3. Identify the most relevant documentation URLs from the map
4. Fetch the specific documentation pages
5. Provide clear, actionable guidance based on official documentation
6. Use WebSearch if docs don't cover the topic
7. Reference local project files (CLAUDE.md, .claude/ directory) when relevant

两个地图 URL:https://code.claude.com/docs/en/claude_code_docs_map.md(CLI)和 https://platform.claude.com/llms.txt(SDK + API)。

这是"给 LLM 用的文档索引"这种格式的实际用例——先抓一张地图,从地图里挑 URL,再抓具体页面。两跳导航。

指导原则里有一条很克制:

text
- Always prioritize official documentation over assumptions

因为这个 agent 回答的正是"Claude Code 怎么用",而模型的训练数据里的 Claude Code 版本一定是旧的。

它还是非 SDK 入口专属(isNonSdkEntrypoint)——SDK 消费者不需要一个教他们用 CLI 的 agent。

5.2 statusline-setup:一个极窄的工具型 agent

ts
tools: ['Read', 'Edit']   // 只有这两个

提示词是一份转换规程:读用户的 shell 配置(~/.zshrc~/.bashrc~/.bash_profile~/.profile,有优先级)、用一个给定的正则提取 PS1、按一张对照表把 PS1 转义序列翻译成 shell 命令:

text
- \u → $(whoami)
- \h → $(hostname -s)
- \w → $(pwd)
- \W → $(basename "$(pwd)")
- \t → $(date +%H:%M:%S)
…

[源码 src/tools/AgentTool/built-in/statuslineSetup.ts:14]

然后是几条经验性的修正:

text
4. When using ANSI color codes, be sure to use `printf`. Do not remove colors. Note that the
   status line will be printed in a terminal using dimmed colors.
5. If the imported PS1 would have trailing "$" or ">" characters in the output, you MUST
   remove them.
6. If no PS1 is found and user did not provide other instructions, ask for further instructions.

第 5 条是产品细节:PS1 末尾的 $ 是提示符,但状态栏不是提示符,留着就很怪。

这个 agent 说明了 agent 化的另一种用法:不是"让一个聪明的 agent 自由发挥",而是把一段有确定步骤但需要理解自然语言输入的规程封装起来。它只有两个工具,流程写死,本质上是一个"带 LLM 的转换器"。


六、专业化的收益

回头看这六个 agent,专业化带来的是三样东西:

① 上下文隔离。 Explore 跑几十次 grep,那些输出全部留在它自己的 sidechain 里,主线程只拿到一份报告。

② 角色不混杂。 规划和实现分开,验证和实现分开。第 1 章那份研究报告里说得很准:

很多系统的问题,就是一个 agent 既研究、又规划、又实现、又验收,最终哪件事都不够稳定。

③ 可以按角色配资源。 Explore 用 Haiku(快、便宜),Plan 和 verification 用主模型(要能力)。Explore 和 Plan 不带 CLAUDE.md(省 token),verification 要带(它需要知道项目约定)。

代价也很清楚

  • 每个 agent 都是一份要维护的提示词(验证 agent 一个就 130 行)
  • 提示词和运行时约束必须保持一致(禁了工具就要在提示词里说"你没有这些工具")
  • 主 agent 需要知道什么时候派谁——这又是一段系统提示词

所以专业化不是免费的,它把复杂度从"一个 agent 的行为"转移到了"一套 agent 的编排"。 值不值取决于任务是不是真的有天然的角色边界。第 15 章会展开。


七、动手复核

bash
cd claude-code-deep-dive/extracted-source

# 1. 六个 agent 的组装
cat src/tools/AgentTool/builtInAgents.ts

# 2. 逐个读(都不长)
cat src/tools/AgentTool/built-in/generalPurposeAgent.ts    # 34 行
cat src/tools/AgentTool/built-in/exploreAgent.ts           # 83 行
cat src/tools/AgentTool/built-in/planAgent.ts              # 92 行
cat src/tools/AgentTool/built-in/verificationAgent.ts      # 152 行 ★
cat src/tools/AgentTool/built-in/statuslineSetup.ts        # 144 行
cat src/tools/AgentTool/built-in/claudeCodeGuideAgent.ts   # 205 行

# 3. 一次性 agent 的省 token 计算
cat src/tools/AgentTool/constants.ts

# 4. 主 agent 侧的「验证合同」
grep -n -A2 'The contract:' src/constants/prompts.ts

# 5. Explore 的 3 次查询判据
grep -n 'EXPLORE_AGENT_MIN_QUERIES' src/tools/AgentTool/built-in/exploreAgent.ts src/constants/prompts.ts

本机侧:

bash
/agents            # 看当前可用的 agent 及其描述

八、总结

  1. 六个内建 agent,四个裁剪维度:工具集、模型、上下文(omitClaudeMd)、生命周期(background
  2. 外部用户的 Explore 跑在 Haiku 上Explore / Plan 是"一次性 agent",专门省掉那段 135 字符的 SendMessage 尾巴(× 每周 3400 万次)
  3. 只读约束要两层落实:禁用专用工具(机制)+ 提示词逐条堵死 Bash 的写路径(规范)——因为机制禁不掉通用工具的滥用
  4. Explore 要求调用方显式指定彻底程度,并给了"预计超过 3 次查询就用它"这个量化判据
  5. Plan 的提示词两次提到"你被分配的视角",暗示并行多视角规划的用法;输出硬性要求"3–5 个关键文件"
  6. 验证 agent 的提示词开场就点名它自己的两种失败模式,然后逐字列出六句托词并反驳
  7. 十种变更类型各一条验证流水线,本身就是一份可直接拿走的验收清单
  8. "测试结果是背景不是证据",因为实现者也是 LLM,它的测试可能全是 mock 和循环断言
  9. PASS 和 FAIL 两道对称闸门:PASS 前必须有一条对抗式探测,FAIL 前要排除"已被别处处理/是有意为之/改不了"
  10. 没有命令输出的 PASS 等于跳过PARTIAL 只给环境限制,不给"我拿不准"
  11. 主 agent 侧有一份配套的"验证合同":不许自判、不许告诉验证者测试结果、PASS 后要抽查 2–3 条命令重跑——自律 + 他律的完整闭环
  12. 专业化的三个收益(上下文隔离、角色不混杂、按角色配资源)和一个代价(复杂度从单 agent 行为转移到多 agent 编排)

下一章讲扩展面:Skills / Plugins / MCP / Commands 四条通道,以及为什么模型"知道"自己有哪些扩展。


  • 第12章-Agent调度-fork与fresh两条路
  • 第14章-扩展面-Skills-Plugins-MCP-Commands
  • 第5章-系统提示词-一个可编排的装配架构 —— 主 agent 侧「验证合同」的位置
  • 第6章-附件与system-reminder-第二条注入通道 —— critical_system_reminder 的用途
  • Codex 教程第 14 章
  • dsh 教程第 11 章

本章目录
一、六个 agent 及其裁剪方式二、Explore:被裁成只读的搜索专家三、Plan:架构师,不是执行者四、verification:本章的主角五、另外两个 agent六、专业化的收益七、动手复核八、总结Related Documents
苏ICP备2025204887号-2