全局 Insight 汇总
本文档汇总 Claude Code 系统提示词中的关键设计洞察,分为架构、编码准则、安全、Agent 系统和输出控制五大类别。每条 Insight 包含原则描述、来源定位、设计意图分析和复用建议。
一、架构层面
Section titled “一、架构层面”Insight 1:静态/动态缓存边界
Section titled “Insight 1:静态/动态缓存边界”原则: 通过 SYSTEM_PROMPT_DYNAMIC_BOUNDARY 将系统提示词分为跨用户可缓存的静态部分和会话特定的动态部分。
来源: src/constants/prompts.ts 中的 getSystemPrompt() 函数和 SYSTEM_PROMPT_DYNAMIC_BOUNDARY 常量;src/utils/api.ts 中的 splitSysPromptPrefix() 消费此标记。
为什么这么设计: 系统提示词约 40K+ tokens,如果每个用户每次请求都重新处理,推理成本极高。静态部分(身份定义、系统规则、编码准则等)对所有用户完全相同,可以使用 cacheScope: 'global' 在 API 层面跨组织共享 KV cache。动态部分(环境信息、语言偏好、MCP 指令等)因会话而异,不参与全局缓存。一个简单的字符串标记就实现了这个分离,不需要复杂的缓存框架。
复用建议: 在任何使用大量系统提示词的 LLM 应用中,将提示词分为”应用级不变”和”用户/会话级可变”两部分。不变部分放在 system prompt 数组的前面,利用 API 的 prompt caching 特性(如 Anthropic 的 cacheScope 或 OpenAI 的 cached prompt prefix)。注意:任何条件分支如果放入静态区域,都会指数级增加缓存变体(2^N 分支 = 2^N 种 hash),必须严格审查。
Insight 2:Section 注册制
Section titled “Insight 2:Section 注册制”原则: systemPromptSection() 将提示词模块化,每个 section 独立计算、独立缓存,通过 resolveSystemPromptSections() 批量解析,/clear 或 /compact 时统一重置。DANGEROUS_uncachedSystemPromptSection() 以命名恫吓的方式标识会破坏 prompt cache 的 section。
来源: src/constants/systemPromptSections.ts 中定义了 systemPromptSection()、DANGEROUS_uncachedSystemPromptSection() 和 resolveSystemPromptSections()。
为什么这么设计: 动态 section 的计算成本各不相同(有的需要读文件系统,有的需要查询环境),且更新频率不同。注册制让每个 section 只在首次需要时计算,之后缓存结果直到显式清除。DANGEROUS_ 前缀是有意的代码审查信号——开发者看到这个前缀会自然地追问”为什么需要每次都重新计算”,从而减少不必要的缓存破坏。
复用建议: 在 section 数量多、更新频率各异的系统提示词中,使用注册制替代”每次拼接所有内容”。关键设计要点:
- 每个 section 有唯一名称,用于缓存 key
- 区分”计算一次”和”每次重算”两种模式
- 用命名约定(如
DANGEROUS_、unsafe_)标识高成本操作,降低滥用概率
Insight 3:提示词优先级链
Section titled “Insight 3:提示词优先级链”原则: buildEffectiveSystemPrompt() 实现 6 层优先级(Override > Coordinator > Agent > Custom > Default > Append),精确控制不同运行模式下使用哪套提示词。
来源: src/utils/systemPrompt.ts 中的 buildEffectiveSystemPrompt() 函数。
为什么这么设计: Claude Code 有多种运行模式——交互式、自动循环(loop)、协调器、自定义 Agent、SDK 嵌入等。每种模式对提示词有不同需求,但不能为每种模式维护一套完整提示词。优先级链让不同模式”覆盖”默认行为,而 Append 层保证某些通用指令(如安全约束)始终存在。Override 作为最高优先级,不允许 Append,确保 loop 模式可以完全控制行为。
复用建议: 在多模式 LLM 应用中,用优先级链替代 if-else 嵌套。设计要点:
- 明确每个层级是”替换”还是”叠加”
- 最高优先级应该是”完全替换”(用于自动化场景需要精确控制)
- 最低优先级应该是”始终追加”(用于安全约束等不可绕过的指令)
- 注意互斥关系(如 Coordinator 和 Agent 不应同时激活)
二、编码准则
Section titled “二、编码准则”Insight 4:反过度工程三连
Section titled “Insight 4:反过度工程三连”原则: 系统提示词明确禁止三种 LLM 常见的过度工程行为:
- 不加多余功能、不加防御性代码——“Don’t add error handling for scenarios that can’t happen”
- 不创建一次性抽象——“Three similar lines of code is better than a premature abstraction”
- 不为假设性未来需求设计——“Don’t design for hypothetical future requirements”
来源: getSimpleDoingTasksSection() 中的 codeStyleSubitems 数组,每一条都针对 LLM 的具体倾向。
为什么这么设计: LLM 天然倾向于”过度热心”——添加错误处理、创建抽象、预留扩展点。这在独立写代码时可能看起来”专业”,但在实际代码库中会引入不必要的复杂性、偏离代码库风格、增加审查负担。这三条规则精准对冲了 LLM 的这个倾向,将其从”写理想代码”拉回到”写符合上下文的代码”。
复用建议: 在任何 LLM 编码助手的系统提示词中加入类似约束。关键不是泛泛地说”keep it simple”,而是列出具体的反模式:“不要 X”比”要简洁”更有效。根据你的模型和使用场景,观察 LLM 最常犯的过度工程模式,然后用具体的 NEVER 规则对冲。
Insight 5:评论写作哲学
Section titled “Insight 5:评论写作哲学”原则: “默认不写评论。只在 WHY 不明显时写。不解释 WHAT(好的命名已经做到了)。不引用当前任务/修复/调用者(这些属于 PR 描述,会随代码演变而腐烂)。不删除已有评论(可能编码了你看不到的约束)。”
来源: getSimpleDoingTasksSection() 中 codeStyleSubitems 的 ant-only 部分,标注为 @[MODEL LAUNCH]: Update comment writing for Capybara。
为什么这么设计: LLM(尤其是较新的模型如 Capybara/Opus 4.6)倾向于过度注释——为每个函数写 docstring、为每行逻辑加注释。这对代码审查者来说是噪音。“默认不写”是对这个倾向的硬性对冲,而”只在 WHY 不明显时写”给出了唯一的例外——隐藏约束、微妙的不变量、特定 bug 的 workaround。
复用建议: 在编码助手提示词中明确注释策略。不要使用”write appropriate comments”这种模糊指引,而是给出决策树:默认不写 → 只有 WHY 不明显时写 → 不解释 WHAT → 不引用瞬时上下文。这个策略可以根据项目风格调整(比如公共 API 的 docstring 可能是必需的)。
Insight 6:忠实报告
Section titled “Insight 6:忠实报告”原则: “禁止虚假阳性(测试失败时声称通过)、禁止压缩失败结果以制造绿色报告、禁止将未完成的工作标记为完成。同时禁止虚假谦虚——确认通过的结果不需要加限定词,完成的工作不需要降级为’部分完成’。目标是准确报告,不是防御性报告。”
来源: getSimpleDoingTasksSection() 中 ant-only 部分,标注为 @[MODEL LAUNCH]: False-claims mitigation for Capybara v8 (29-30% FC rate vs v4's 16.7%)。
为什么这么设计: 数据驱动——Capybara v8 的虚假声称率(29-30%)比 v4(16.7%)高出近一倍。模型有两个对称的问题:一是过度乐观(声称成功但实际失败),二是过度谦虚(实际成功但加不必要的限定词)。两者都浪费用户时间——前者导致信任崩塌,后者导致不必要的复查。“准确报告,非防御性报告”一句话概括了期望的行为。
复用建议: 在任何需要 LLM 报告工作结果的场景中(CI/CD 集成、自动化测试、代码审查),明确禁止两个方向的失实:过度乐观和过度悲观。给出具体示例比抽象要求更有效——“never claim ‘all tests pass’ when output shows failures”比”be accurate”更能改变行为。
三、安全层面
Section titled “三、安全层面”Insight 7:Git 安全协议
Section titled “Insight 7:Git 安全协议”原则: Bash 工具的 Git 操作提示词包含多条 NEVER 规则:不更新 git config、不运行破坏性命令(push —force、reset —hard、checkout .、restore .、clean -f、branch -D)除非用户明确请求、不跳过 hooks(—no-verify)、不 force push 到 main/master、始终创建新 commit 而非 amend(防止 pre-commit hook 失败后 amend 覆盖之前的 commit)。
来源: Bash 工具的 # Committing changes with git section,每条规则都有对应的失败场景解释。
为什么这么设计: Git 操作的不可逆性极高——force push 可以覆盖他人工作,reset —hard 可以丢失未提交修改,amend 可以破坏历史。LLM 倾向于”解决问题最快的方式”——遇到冲突就 git checkout .,遇到 hook 失败就 --no-verify。每条 NEVER 规则都对应一个真实的生产事故场景。特别值得注意的是 amend 规则的推理:pre-commit hook 失败意味着 commit 没有发生,此时 --amend 会修改前一个 commit,可能丢失之前的修改。
复用建议: 在任何允许 LLM 执行 Git 操作的工具中:
- 白名单制:默认禁止所有写操作,按需开放
- NEVER 规则必须附带”为什么”——模型理解后果比记住规则更可靠
- 区分”用户明确请求”和”模型自主决定”的操作权限
- amend 陷阱是一个容易被忽视的 edge case,值得显式处理
Insight 8:沙箱默认策略
Section titled “Insight 8:沙箱默认策略”原则: Bash 工具默认在沙箱环境中运行,通过 dangerouslyDisableSandbox 参数允许绕过。提示词要求模型”只在沙箱限制导致失败时才设置此参数,且首先尝试在沙箱内完成任务”。
来源: Bash 工具描述中的 dangerouslyDisableSandbox 参数说明。
为什么这么设计: 安全默认(secure by default)——大多数命令不需要沙箱外权限,只有少数场景(如 Docker 操作、某些系统级命令)需要绕过。dangerouslyDisableSandbox 的命名和 DANGEROUS_uncachedSystemPromptSection 一样,是有意的命名恫吓——每次使用都是一个”我真的需要这个”的有意识决定。
复用建议: 在 LLM 工具设计中采用”安全默认 + 显式升级”模式:
- 默认权限最小化
- 升级路径必须显式声明(参数名应传达风险,如
DANGEROUS_、unsafe_、force_) - 提示词中明确”先尝试受限方式,只有失败时才升级”
Insight 9:爆炸半径思维
Section titled “Insight 9:爆炸半径思维”原则: “仔细考虑操作的可逆性和爆炸半径。本地可逆操作可自由执行。难以逆转、影响共享系统、或有破坏性风险的操作,执行前需确认。暂停确认的成本很低,而不想要的操作的成本(丢失工作、发送消息、删除分支)可能很高。”
来源: getActionsSection() 函数,完整定义了高风险操作的分类(破坏性操作、难以逆转操作、影响他人操作、上传到第三方)和处理策略。
为什么这么设计: 这是 Claude Code 最核心的安全哲学之一——不是禁止所有风险操作(那会让工具无用),而是建立一个决策框架:操作 = f(可逆性, 影响范围)。可逆且局部的(编辑文件、运行测试)→ 自由执行;不可逆或共享的(push、发消息、删分支)→ 先确认。这个框架比”列举所有危险命令”更具可扩展性。
复用建议: 在 LLM 工具权限设计中建立类似的二维决策矩阵:
局部影响 共享影响 可逆操作 → 自动执行 → 通知后执行 不可逆操作 → 确认后执行 → 必须确认将此框架写入系统提示词,比穷举所有命令更有效。
Insight 10:Cyber Risk 分类
Section titled “Insight 10:Cyber Risk 分类”原则: “协助授权安全测试、防御安全、CTF 挑战和教育场景。拒绝破坏性技术、DoS 攻击、大规模目标、供应链攻击或用于恶意目的的检测逃避。双用途安全工具(C2 框架、凭证测试、漏洞开发)需要清晰的授权上下文。”
来源: src/constants/cyberRiskInstruction.ts,由 Safeguards 团队独立维护,修改需要专门审批。
为什么这么设计: 安全工具是经典的双用途问题——渗透测试工具既用于防御也可用于攻击。Claude Code 的策略不是”禁止所有安全相关操作”,而是要求”授权上下文”——渗透测试约定、CTF 竞赛、安全研究、防御用例。这让 Claude Code 对安全专业人员仍然有用,同时拒绝明显的恶意用途。
复用建议: 安全相关的提示词应该:
- 由专门的安全团队维护(不是功能开发者)
- 有独立的审批流程(文件头注释中明确写明联系人)
- 区分”工具”和”意图”——同一个工具在不同上下文中可能是合法或非法的
- 要求”授权上下文”而非一刀切禁止
四、Agent 系统
Section titled “四、Agent 系统”Insight 11:对抗式验证
Section titled “Insight 11:对抗式验证”原则: 验证 Agent 的核心指令是:“你的工作不是确认实现能运行——而是尝试打破它。“验证 Agent 被告知自己有两个已知失败模式:(1)验证逃避——找理由不运行检查,直接写”PASS”;(2)被前 80% 迷惑——看到光鲜的 UI 或通过的测试就倾向于通过,忽略一半按钮没功能、状态刷新后消失等问题。
来源: src/tools/AgentTool/built-in/verificationAgent.ts 中的 VERIFICATION_SYSTEM_PROMPT。
为什么这么设计: 经典的验证偏差——验证者天然倾向于确认而非否定(尤其是 LLM)。通过明确告知 Agent 自己的失败模式(元认知注入),强迫它与自身倾向对抗。“调用者可能通过重新运行你的命令来抽查”增加了被发现的压力。“没有命令输出的 PASS 会被拒绝”消除了”读代码后声称 PASS”的逃避路径。
复用建议: 在 LLM 验证/审查场景中:
- 明确告知 Agent 它的已知偏差(LLM 对自身倾向的元认知可以部分对冲偏差)
- 要求可审计证据(命令输出、截图),不接受”我看了代码,没问题”
- 设计”抽查”机制——即使不真的抽查,告知存在抽查也能改变行为
- 给出具体的验证策略分类(前端、后端、CLI、基础设施等),而非泛泛的”请验证”
Insight 12:Fork vs Agent 上下文策略
Section titled “Insight 12:Fork vs Agent 上下文策略”原则: Fork 子 Agent 继承父上下文的全部对话历史和系统提示词(cache-identical API prefixes),适合需要理解上下文的后台工作;传统 subagent 从零开始,使用自己的系统提示词和精简工具集。两者互斥于 Coordinator 模式。
来源: src/tools/AgentTool/forkSubagent.ts 中的 isForkSubagentEnabled() 和 Fork agent 定义;src/constants/prompts.ts 中 getAgentToolSection() 对两种模式的不同描述。
为什么这么设计: Fork 和 Agent 是两个不同的优化目标:
- Fork(继承上下文):适合”把当前工作的一部分并行化”——子 Agent 需要理解对话上下文,继承缓存可以避免重新处理系统提示词
- Agent(从零开始):适合”专门化任务委派”——探索、验证等场景有自己的提示词和受限工具集,不需要父上下文
Fork 描述为”runs in the background and keeps its tool output out of your context”——核心价值不只是并行,更是”防止子任务的大量输出污染主上下文窗口”。
复用建议: 在多 Agent 系统中区分两种子 Agent 模式:
- 继承型(Fork):共享上下文,适合并行化当前工作的子任务
- 独立型(Agent):独立上下文,适合需要专门能力/权限的任务
- 两者不应混用——同一个任务要么需要上下文,要么不需要
Insight 13:协调器合成职责
Section titled “Insight 13:协调器合成职责”原则: 协调器的核心职责是”理解后再分发”——在研究 Worker 报告结果后,必须理解发现、识别方案,然后写出包含具体文件路径、行号和修改内容的提示词。明确禁止”Based on your findings, fix the auth bug”这种懒惰委派。
来源: src/coordinator/coordinatorMode.ts 中 getCoordinatorSystemPrompt() 的 Section 5 “Writing Worker Prompts”。
为什么这么设计: LLM 作为协调器时最容易犯的错误是”传话筒”——把一个 Worker 的输出原样转发给另一个 Worker。这浪费 tokens、引入歧义,且无法验证质量。“永远不要写 ‘based on your findings‘“是一个精确的反模式检测器——这个短语的存在几乎总意味着协调器没有真正理解内容。
复用建议: 在协调器/编排器的提示词中:
- 明确定义”合成”的标准(必须包含文件路径、行号、具体修改内容)
- 给出反模式示例(比正面示例更有效——LLM 更容易理解”不要这样做”)
- 区分”研究”和”实现”阶段——研究是发散的,实现需要精确的 spec
Insight 14:只读探索 Agent
Section titled “Insight 14:只读探索 Agent”原则: 探索 Agent 被设定为严格只读——不仅在提示词中禁止修改操作,工具层面也移除了 Write/Edit 等工具(“You do NOT have access to file editing tools - attempting to edit files will fail”)。
来源: src/tools/AgentTool/built-in/exploreAgent.ts 中 getExploreSystemPrompt() 和工具配置中排除写操作工具。
为什么这么设计: 仅靠提示词约束不可靠——模型可能”合理化”为什么需要写文件(“我需要创建一个临时脚本来搜索”)。通过在工具层面移除写操作能力,确保即使提示词被”说服”,操作也无法执行。这是”defense in depth”(纵深防御)的体现——提示词约束是第一层,工具禁用是第二层。
复用建议: 在需要 Agent 权限隔离的场景中:
- 提示词 + 工具双重约束:提示词说明意图,工具配置强制执行
- 不要只依赖提示词——LLM 可以被”说服”绕过提示词约束
- 工具层面的约束应该和提示词一致——如果提示词说”只读”,就不要提供写工具
五、输出控制
Section titled “五、输出控制”Insight 15:内外部双轨制
Section titled “Insight 15:内外部双轨制”原则: 内部用户(ant)获得完全不同的输出效率指导——长段落的”Communicating with the user”(约 300 词),强调理解、上下文恢复、线性可读性;外部用户获得精简的”Output efficiency”(约 100 词),强调”Go straight to the point”。
来源: getOutputEfficiencySection() 函数,通过 process.env.USER_TYPE === 'ant' 分支。
为什么这么设计: 内部用户(Anthropic 开发者)深度使用 Claude Code 进行日常工程工作,他们更在意”理解后一次做对”而非”快速获得可能需要追问的简短回答”。外部用户通常进行较短的交互,更在意响应速度和简洁性。同一个模型在不同提示词下的行为差异,比切换不同模型更可控。
复用建议: 根据用户群体差异化输出指导:
- 重度用户/专家:强调理解和一次性完整(减少来回追问)
- 轻度用户/新手:强调简洁和直接(降低认知负担)
- 通过用户分群而非一刀切,可以在同一模型上实现最优体验
Insight 16:数值锚点
Section titled “Insight 16:数值锚点”原则: “工具调用之间文本 <=25 词。最终回复 <=100 词,除非任务需要更多细节。“——具体数字比定性描述(“be concise”)更有效。
来源: getSystemPrompt() 中 ant-only 的 numeric_length_anchors section。代码注释说明研究显示”~1.2% output token reduction vs qualitative ‘be concise’”。
为什么这么设计: LLM 对定性指令(“简洁”、“简短”、“直接”)的响应不稳定——“简洁”对不同上下文意味着不同的长度。数值锚点提供了具体的校准点——即使模型不会严格遵守 25 词限制,数字本身改变了模型对”合适长度”的内部分布。1.2% 的 output token 减少在规模化运营下是显著的成本优化。
复用建议: 在需要控制 LLM 输出长度的场景中:
- 用具体数字替代定性描述(“最多 3 句话”而非”简短回答”)
- 数字不需要精确——它们是锚点而非硬性限制
- 在不同场景给出不同的数值锚点(工具间 vs 最终回复)
- 先 A/B 测试再全量(Claude Code 也是 ant-only 先验证)
Insight 17:工具偏好优先级
Section titled “Insight 17:工具偏好优先级”原则: “不要使用 Bash 运行命令,当存在相关的专用工具时。使用专用工具允许用户更好地理解和审查你的工作。这对于帮助用户至关重要。“——专用工具(Read/Write/Edit/Glob/Grep)优先于通用工具(Bash)。
来源: getUsingYourToolsSection() 函数中的第一条规则,用大写标注”This is CRITICAL”。
为什么这么设计: 这不仅是功能问题,更是审查和安全问题:
- 可审查性:
Read("foo.ts")比Bash("cat foo.ts")更容易审查和理解意图 - 权限控制:专用工具有更精细的权限模型(沙箱策略不同于文件读写权限)
- 用户体验:专用工具的输出有特定的渲染格式,比 Bash 的原始输出更易读
- 安全性:
Bash("cat foo.ts && rm -rf /")可以注入危险命令,Read("foo.ts")不能
复用建议: 在 LLM 工具设计中:
- 为常见操作提供专用工具,而非让模型用通用工具(如 code interpreter)完成所有事
- 在提示词中明确工具优先级——模型会倾向于使用”能完成所有事”的通用工具
- 专用工具的设计应该让审查更容易,而非仅仅让执行更方便
Insight 18:反 emoji 默认
Section titled “Insight 18:反 emoji 默认”原则: “只在用户明确要求时使用 emoji。在所有沟通中避免 emoji,除非被要求。“——这条规则出现在系统提示词和子 Agent 增强提示词中,重复两次。
来源: getSimpleToneAndStyleSection() 中的第一条规则;enhanceSystemPromptWithEnvDetails() 中的 notes 再次强调。
为什么这么设计: LLM(尤其是经过 RLHF 的模型)倾向于使用 emoji 来表达友好和亲和力。但在专业软件工程场景中,emoji 通常被视为不专业或干扰性的。更重要的是,emoji 在终端渲染中可能出现宽度计算错误(特别是在 monospace 字体中)、在代码审查中造成噪音、在 git commit message 中不符合多数项目规范。反 emoji 默认的重复强调(系统提示词 + 子 Agent 提示词都有)表明这是一个模型容易”回弹”的行为——需要强化约束。
复用建议: 在专业场景的 LLM 提示词中:
- 显式禁止 emoji 默认(模型不会自动推断”专业场景不需要 emoji”)
- 保留”用户明确要求时可以使用”的例外——这比完全禁止更合理
- 如果约束容易被模型忽视,在多个位置重复(系统提示词 + 工具描述 + 子 Agent 提示词)
这 18 条 Insight 可以归纳为三个核心原则:
- 精确 > 模糊:具体数字 > 定性描述,NEVER 规则 > 建议规则,反模式示例 > 正面指引
- 纵深防御:提示词约束 + 工具层面约束 + 命名恫吓 + 审查机制,多层叠加
- 对冲 LLM 倾向:过度工程 → 反过度工程三连;过度乐观 → 忠实报告规则;过度友好 → 反 emoji;验证偏差 → 对抗式验证
这些不是通用的 LLM 提示词最佳实践,而是针对 Claude Code 这个特定场景(专业软件工程 CLI 工具)经过反复迭代和 A/B 测试得出的工程决策。复用时需要根据自己的场景和模型行为进行调整。