Claude Code 为何如此强悍

Claude Code 之所以出色,在于其简洁的设计理念和对大型语言模型(LLM)优缺点的深刻理解。它通过精心设计的提示词、工具和简单的控制循环,有效地弥补了模型的不足,并充分发挥其优势。构建高效 AI 代理的关键原则包括:保持系统简单、善用小型模型、使用 XML 标签等结构化提示、优先选择 LLM 驱动的搜索而非 RAG,并让代理自行管理待办事项列表。此外,通过明确的语气和算法式指令,可以显著提升代理的可控性和用户体验。

核心原则:保持简单

LLM 的调试和评估已经足够困难。任何额外的复杂性(如多代理系统、复杂的 RAG 搜索算法)都会使调试难度增加十倍。

Claude Code 在每个设计节点都选择了架构上的简洁性:一个主循环、简单的搜索、简单的待办事项列表。构建高效代理的首要原则是抵制过度工程化的冲动。

    • 控制循环: 保持一个主循环和一个消息历史记录。
    • 小型模型: 尽可能广泛地使用更小、更便宜的模型。
    • 提示词: 使用 claude.md 文件来协作和记忆用户偏好,并大量运用 XML 标签、Markdown 和示例。
    • 工具设计: 优先使用 LLM 驱动的搜索,而非基于 RAG 的搜索。让代理管理自己的待办事项列表。
    • 可控性: 通过明确的语气、风格指导和算法式指令来引导模型。

1. 控制循环设计

保持单一主循环

可调试性远比复杂的、经过精心调整的多代理系统重要。Claude Code 只有一个主线程,它维护一个扁平的消息列表。当遇到复杂任务时,它会生成一个自身的克隆作为子代理来处理,但这个子代理无法再生成新的子代理,从而确保最多只有一个分支。这种设计结合了待办事项列表,使代理既能分解问题,又能始终关注最终目标。

结论:你的应用很可能不需要一个多代理系统。每增加一个抽象层,都会让系统更难调试。

广泛使用小型模型

Claude Code 超过 50% 的重要 LLM 调用都使用了 claude-3-5-haiku 这样的小型模型。它被用来读取大文件、解析网页、处理 git 历史和总结长对话。这些小型模型比标准模型(如 Sonnet 4, GPT-4.1)便宜 70-80%,应该被广泛使用。

2. 提示词策略

Claude Code 的系统提示词非常详尽,包含了大量启发式规则、示例和重要提醒,总长度接近 2800 个 token。

使用 claude.md 协作上下文

这是编码代理的一个主流模式。claude.md 文件允许开发者传递代码库本身无法推断的上下文信息,并固化严格的偏好,例如强制 LLM 跳过某些文件夹或使用特定的库。Claude Code 在每次用户请求时都会发送 claude.md 的全部内容。

使用特殊的 XML 标签、Markdown 和示例

结构化提示是关键。Claude Code 广泛地同时使用 XML 标签和 Markdown。

  • <system-reminder>: 在提示的末尾用来提醒 LLM 那些它可能会忘记的事情。

    <system-reminder>这是一个提醒,你的待办事项列表当前为空。不要明确向用户提及此事,因为他们已经知道了。如果你正在处理的任务可以从待办事项列表中受益,请使用 TodoWrite 工具创建一个。如果不是,请忽略。再次强调,不要向用户提及此消息。</system-reminder>

  • <good-example><bad-example>: 用于阐明启发式规则,尤其是在模型面临多个看似合理的选择时,通过对比明确指出哪个是更优路径。

    尝试在整个会话中保持当前工作目录,使用绝对路径并避免使用 cd。只有在用户明确要求时才可以使用 cd

    pytest /foo/bar/tests

    cd /foo/bar && pytest tests

    • Markdown 标题: 用于在系统提示中划分清晰的区域,例如:语气与风格主动性任务管理工具使用策略等。

3. 工具设计

工具提示本身就长达 9400 个 token,设计非常精巧。

LLM 搜索优于 RAG 搜索

Claude Code 不使用 RAG,而是像人类一样搜索代码库,使用复杂的 ripgrepjqfind 命令。由于 LLM 对代码有很好的理解,它能用复杂的正则表达式找到任何它认为相关的代码块。

    • RAG 的问题: 引入了新的、隐藏的失败模式(相似性函数、重排器、分块策略等)。
    • LLM 搜索的优势: 模型完成了大部分繁重工作,减少了系统的活动部件。这就像 LLM 时代的摄像头与激光雷达之争,前者更具通用性。

如何设计好工具?(高层 vs. 底层)

答案是两者都用。Claude Code 提供了不同层级的工具:

    • 底层: Bash, Read, Write
    • 中层: Edit, Grep, Glob
    • 高层: Task, WebFetch, exit_plan_mode

这种分层设计的权衡在于使用频率使用准确性grepglob 使用频率很高,因此被设计成独立工具。而更高层的工具如 WebFetch 则非常确定,能让 LLM 避免执行多个繁琐的底层操作,保持任务的专注度。

让代理管理自己的待办事项列表

这是一个解决长期运行的 LLM 代理中“上下文腐烂”问题的好方法。Claude Code 使用一个由模型自己维护的显式待办事项列表。这既能让 LLM 保持任务的连贯性(提示词中要求它频繁参考待办事项列表),又赋予了模型在执行过程中灵活调整路线的权力

4. 提升可控性

明确语气和风格

Claude Code 的系统提示中有专门的章节来控制代理的美学行为,包括语气、风格和主动性,并附有大量指令和示例。这使得它的反馈感觉很有品味。

  • 示例指令:
      • 重要:除非用户要求,否则不应在回答中添加不必要的前言或后记(例如解释你的代码或总结你的行为)。
      • 如果你不能或不愿帮助用户,请不要解释原因,因为这会显得说教和烦人。
      • 除非用户明确要求,否则不要使用表情符号。

“这很重要” 仍然是最佳实践

不幸的是,要让模型不做某事,最有效的方法仍然是使用 “重要”、“非常重要”、“绝不”、“总是” 这样的词。Claude Code 大量使用了这种方法,你也应该这么做。

  • 示例指令:
      • 重要:除非被要求,否则不要添加任何注释。
      • 非常重要:你必须避免使用 findgrep 这样的搜索命令。请改用 Grep、Glob 或 Task 工具来搜索。
      • 重要:你绝不能为用户生成或猜测 URL,除非你确信这些 URL 是为了帮助用户编程。

编写算法,附带启发式规则和示例

识别 LLM 需要执行的最重要任务,并为其编写出明确的算法至关重要。避免给出一大堆“该做”和“不该做”的清单,因为它们难以跟踪且容易相互冲突。

Claude Code 系统提示中的“任务管理”、“执行任务”和“工具使用策略”部分清晰地阐述了要遵循的算法,并为 LLM 可能遇到的各种场景提供了大量启发式规则和示例。