Video thumbnail

    我逆向工程了 Claude 代码:学习这些 Agent 技巧

    Valuable insights

    1.Claude Code 的秘密武器:提示工程: Claude Code 优于其他代码代理的关键在于其复杂的提示工程。通过逆向工程揭示,其核心成功依赖于精心设计的系统提示和工具定义,而非底层模型差异。

    2.逆向工程方法与发现: 通过解包 CLI.js 文件并使用 Proxy Man 拦截请求,发现 Claude Code 的提示是动态构建的。其核心在于直接与 Anthropic API 交互,使得请求拦截成为可能。

    3.核心代理工作流理解: 代理工作流涉及系统提示、工具定义、用户消息和反复的工具调用循环。Claude Code 在本地协调此过程,其效能的核心在于系统提示的深度和广度。

    4.系统提示的关键性与迭代: 系统提示详细定义了代理的角色、语气、任务管理和工具使用。关键工作流在提示中多次重申,并辅以“必须”、“重要”等强调词,显著提升了 LLM 的任务执行可靠性。

    5.系统提醒与助推机制: Claude Code 在消息历史中插入系统提醒模块,持续提醒模型关键工具(如 To-Do 工具)的使用。这种不断的助推机制有效弥补了代理的“遗忘”问题,确保任务规划和管理的高效执行。

    6.自然语言定义工作流: Claude Code 的大部分工作流,包括任务管理和工具使用,都以自然语言直接定义在系统提示中,而非硬编码。这种设计提供了极大的灵活性,仅通过修改提示即可改变代理行为。

    7.提示格式化的重要性: 提示的格式化(如全大写、XML 标签)对模型理解语义至关重要。结构化和清晰的格式有助于 LLM 更准确地解析和遵循指令,尤其是在处理多行或复杂逻辑时。

    8.子代理机制与内存隔离: 子代理允许主代理委托特定任务,每个子代理拥有独立的系统提示和消息历史。关键在于主子代理之间内存不共享,子代理完成任务后仅返回总结给主代理。

    9.工具定义的详细性与准确性: Claude Code 的工具定义极为详细,包含了何时使用、如何使用、可用代理列表及大量示例。这种冗长的描述是实现准确工具调用的关键,即使是子代理的创建也依赖于此。

    10.模型特定提示调优: 为特定模型(如 Sonnet)优化的提示在其他模型上可能表现不佳。切换模型或构建代理时,需要进行模型特定的评估和提示迭代,以确保最佳性能。

    引言

    视频探讨了 Claude Code 代理在编码方面表现优于其他同类产品的原因,尽管它们底层使用了相同的模型。作者分享了其逆向工程 Claude Code 的过程,旨在揭示其“秘密武器”,并帮助观众理解如何利用这些原理来提升自己的编码代理性能。文章指出,Claude Code 的出色表现很大程度上归功于其深入的提示工程。在深入探讨之前,作者还提到了正在启动的 Beyond the Hype 通讯,旨在分享专业技巧、行业见解及未来项目的早期访问权,鼓励有兴趣的读者订阅以获取更多信息。

    解包 CLI Bundle

    Claude Code 最初发布时,许多人期望它会是开源项目,但事实并非如此。它仅提供了一个打包的 9兆字节 的 CLI.js 文件供分析。为了深入研究,作者使用了 WebCrack 工具对编译后的 JavaScript 文件进行解包和去混淆处理。最终得到的是一个令人震惊的 443,000行 长代码文件。在文件中,虽然发现了大量 Claude Code 的内置依赖项,但真正需要找到的是其与大型语言模型(LLM)的实际交互提示。作者尝试直接搜索“Claude Code”文本,但很快发现大部分提示和 LLM API 都是动态构建的,因此无法直接提取出长的固定文本字符串。这一发现促使作者迅速改变了策略,转而关注 Claude Code 允许用户手动设置 Anthropic Base URL 环境变量的事实,这表明 Claude Code 确实直接发起了 LLM 请求,为后续的拦截工作提供了思路。

    使用 Proxy Man 拦截请求

    由于 Claude Code 直接与 LLM API 进行通信,且允许设置自定义基础 URL,作者改变了策略,决定通过代理来拦截这些请求。于是,作者使用了 Proxy Man 工具来截获 Claude Code 与 Anthropic API 之间的所有网络请求。结果令人惊喜,所有的交互细节都开始浮现。每次 Claude Code 与用户互动时,都会向 Anthropic API 发送大量消息。一次 Anthropic API 调用包含核心部分:用户消息(包含完整的消息历史)、系统提示和工具定义,以及模型的响应和偶尔的工具使用。这些被拦截的数据揭示了 Claude Code 与 LLM 交互的底层机制,为进一步分析其内部工作流奠定了基础。

    理解核心代理工作流

    核心代理工作流涉及客户端(即 Claude Code)、大型语言模型(LLM)API(Anthropic)以及定义的工具。在消息历史的顶部,始终存在定义代理角色的系统提示。紧随其后的是工具定义。当用户消息(例如查询天气)传入时,客户端会带着这个请求调用 Anthropic API。助手模型随后会以一条消息响应,并可能包含进一步的工具调用指令,以获取更多信息。客户端根据工具定义执行这些工具调用,将结果附加到消息历史中,并再次向 LLM API 发送请求。这个循环会重复进行,直到 LLM 决定任务完成,然后将最终消息返回给用户。例如,在天气查询中,它可能分几轮获取天气状况和降水量,最终返回天气总结。这就是 Claude Code 在本地执行的核心编排流程,其真正的精髓在于其系统提示本身。

    工作流概览

    • 客户端(Claude Code)发送用户请求至 Anthropic API。
    • 助手模型响应,可能包含工具调用。
    • 客户端执行工具调用,获取结果。
    • 结果附加到消息历史,再次发送请求至 LLM API。
    • 此循环持续进行,直到 LLM 返回最终的用户消息。
    Claude Code 的核心编排,尽管包含大量用户体验改进,但其真正的精髓在于系统提示本身。

    深入系统提示

    从截获的请求中提取的系统提示内容非常全面。这个提示涵盖了代理应如何响应用户文档请求、其应遵循的语气和风格、如何主动行动以及如何遵守约定。它甚至具体规定了编码风格,例如“不要添加任何注释”,尽管有趣的是,即使有此规定,Claude 仍然倾向于添加大量注释。此外,提示还详细说明了代理如何进行任务管理、如何有效地使用工具,以及最终如何引用代码。这是一个非常长的文件,包含大量细节,但其中一些关键观察点值得关注,这些观察点构成了 Claude Code 卓越性能的基础。

    重复是关键

    第一个关键观察是,核心工作流在同一个系统提示的不同部分中被多次重申。以“to-do”工具为例,这个工具用于展示任务进展的清单。在任务管理部分,它被多次提及,甚至提供了如何管理不同类型任务的示例,包括有分解和无分解的任务。在执行任务时,明确指出需要使用“to-do write”工具。最终,在工具使用策略中,再次提醒“在整个对话中始终使用 to-do 文件来计划和跟踪任务”。此外,提示中还使用了“重要”、“非常重要”、“从不”、“必须”等强调词汇,以确保 LLM 对特定内容给予特别关注。这些重复的、详细的描述,辅以大量示例,是 Claude Code 能够实现极高准确性函数调用的关键。通过对比,像“lint”工具只被提及一次,其调用可靠性远低于“to-do write”工具,这直接反映了提及频率对可靠性的影响。为了改善用户体验,作者建议在 `cloud.md` 文件中直接添加运行 lint 和类型检查的要求。

    通过反复强调,你可以让 LLM 更加关注关键信息,从而提升其执行任务的准确性。
    工具名称
    提及次数
    调用可靠性
    to-do write
    多次
    lint
    一次
    低(约5/10)

    系统提醒助推

    Claude Code 还有另一种进一步提醒模型关键工具调用要求的方法,即在消息历史中添加“系统提醒”块。这个块会提醒模型存在待办事项列表和“to-do write”工具,并建议模型在需要时使用它。每当任务有所进展或每次调用“to-do write”工具后,这个提醒都会被重新插入。Claude 的待办事项管理和规划之所以如此有效,并非偶然,正是因为消息历史中不断提醒这些关键工具。因此,下次如果需要提醒 Claude Code 某些事情,不必感到沮丧,因为代理确实会遗忘,而这种持续的提醒机制是确保其连贯和高效运行的关键。

    工作流作为自然语言

    第二个观察是,Claude Code 内部的所有工作流几乎都通过自然语言在系统提示中定义。例如,在任务管理部分,系统提示清晰地阐述了代理管理任务的风格,甚至提供了任务分解的示例,区分了不需要分解的简单任务和需要分解的复杂任务。在执行任务的部分,它明确说明了如何使用“to-do”工具进行进一步跟踪、如何使用搜索工具,以及被提醒的 lint 检查,并强调“从不提交”。如此多的工作流都是直接在系统提示中以自然语言定义的,而不是硬编码在 CLI 内部。这种设计非常强大,因为如果需要更改或调整任何行为,只需修改提示即可,几乎不需要更改代码。虽然可能需要进行用户体验改进来处理用户批准,但更改核心流程仅需修改提示。

    自然语言定义工作流的优势

    • 高度灵活性:仅需修改提示即可改变代理行为。
    • 减少代码维护:核心逻辑在提示中,而非硬编码。
    • 易于迭代:快速调整工作流和规则,无需重新部署代码。

    提示格式化的重要性

    第三个观察是,提示的格式化仍然非常重要。Claude Code 的系统提示不仅可读性强,而且其结构本身为文本增加了更多的语义含义。例如,在编码部分,可以看到所有文本都使用全大写字母,并强调“重要。除非要求,否则不要添加任何加粗评论”。模型在理解此提示时会考虑所有这些格式。此外,XML 标签的使用在这里也发挥了强大作用。如前面示例部分所示,可以使用这些 XML 标签对来清晰地划定文本区域,LLM 会将这些区域视为一个连贯的整体。还可以像编写任何 XML 文档一样嵌套这些 XML 标签,以增加更多语义含义。因此,如果遇到更复杂、跨越多行的情况,使用 XML 标签进行格式化将产生很好的效果,帮助模型更好地理解和处理信息。

    探索子代理

    了解主代理的工作方式后,子代理是另一个有趣的特性。这是 Claude Code 最近发布的功能,允许主代理触发子代理来执行特定任务集,每个子代理都有自己定义的系统提示。从宏观层面看,主代理的 LLM 调用会返回响应和工具调用,其中子代理被视为另一个可触发的工具。当主代理的工具调用触发子代理创建时,Claude Code 会为该子代理创建一个新的消息历史。子代理获得自己的系统提示,工具调用中包含其应开始的消息(由主代理提供)。子代理然后继续执行,其内部流程与主代理类似,包括助手消息和工具调用循环。这个循环持续进行,直到子代理完成任务,返回一个不包含进一步工具调用的助手消息给主代理。这个最终消息被附加回主代理的消息历史中,但作为工具调用结果,而非系统消息。这意味着子代理的中间消息历史会被完全丢弃。因此,主代理与子代理之间的记忆并不共享,主代理仅能接收到子代理的最终总结。确保返回给主代理的消息包含执行任务所需的所有信息,以避免重复工作至关重要。

    子代理与主代理的通信

    • 子代理被视为工具,由主代理调用。
    • 子代理拥有独立的消息历史和系统提示。
    • 子代理完成任务后,仅将最终总结返回给主代理。
    • 主代理与子代理之间的内存不共享,中间历史被丢弃。

    实际子代理请求

    为了具体说明子代理在实际请求中的表现,一个用户消息请求主代理使用“需求分析代理”来规划工作。在响应中,主代理创建了一个工具调用,并启动了需求分析代理,同时提供了一个非常详细的创建提示。这个子代理的输入是根据 Claude 或 MD 上下文和用户输入综合生成的。在后续的消息中,子代理再次获取相同的 Claude.md 文件,并且主代理的内存也未共享。子代理继续执行工作,首先进行大量文件读取,然后执行几轮请求。在最后一轮中,可以看到左侧的消息历史包含工具调用和工具调用结果。最终,子代理返回了一个关于需求的总结消息。这个总结被主代理接收,并作为工具调用的结果插入到其消息历史中。值得注意的是,子代理运行期间的中间消息历史被完全丢弃。随后,主代理继续正常运行,由于被提醒使用 To-Do 工具,它利用该工具创建了计划,并继续执行整个任务。整个过程持续了大约30到40个请求,最终代理向用户返回了最终实现的功能。

    工具定义是否冗长?

    你可能会疑惑,在系统提示中并未明确提及使用子代理来处理任务的要求,那么 Claude 是如何知道何时使用子代理的呢?秘密在于工具定义部分。在系统提示之后,会看到详细的工具定义。“任务工具”基本上就是负责启动新代理以处理复杂多步骤任务的工具。其描述非常详细,与传统的一行 MCP 工具描述截然不同。这个格式精美的描述首先列出了所有可用的代理,并提供了大量如何触发这些不同代理的示例。它还包含了每个代理可用的工具、何时使用和何时不使用代理的指导,以及从代理直接提取信息的注意事项。与系统提示一样,这些工具定义也包含大量细节。当 Claude Code 能够进行如此准确的工具调用时,正是这些详细的提示和描述确保了其准确性。我们还观察到与系统提示中类似的工作流设计。在用法说明中,它会说明如何启动代理、如何处理代理返回,以及每次调用都是完全无状态的,因此不会向代理发送额外的消息,以及如何信任代理,以及在定义为主动使用时如何触发代理。

    Claude Code 能够进行如此准确的工具调用,其关键在于这些详细的提示和描述。

    如果你曾尝试在 Claude 中创建子代理,会发现在创建过程中,它会询问你是要手动配置还是使用 Claude 生成。将“使用 Claude 生成”标记为推荐的原因是,Claude 会主动为你的代理添加详细描述,并根据你过去的对话历史生成示例,从而在执行这些代理时提供最佳结果。另外,需要注意的是,触发子代理时,Claude Code 的系统提示实际上会被代理描述替换。因此,为了使你的子代理获得与主代理类似的性能,它需要遵循与主代理系统提示完全相同的最佳实践,以获得最佳结果。这正是 Claude 通常偏好你直接使用 Claude 生成代理描述的原因,因为它会添加额外信息并遵循最佳实践。当然,一旦生成了足够详细的代理,你可以随时修改它,但最好确保遵循其结构。

    其他显著特点

    此次调查还发现了一些其他值得注意的事实。例如,`/init` 命令调用定义了工作流,这同样不是硬编码,而是另一个提示模板。如果曾疑惑 Claude Code 为何总是知道要查看 `cursor rules` 文件和 `GitHub Copilot instructions` 文件,那是因为这些内容在提示中被明确定义了。文件结构也在此处清晰地概述。此外,当上下文耗尽时运行的 `compact` 命令,也清晰地概述了它需要做的工作。这同样是一个非常详细的提示,包含了详细的工作流描述、注意事项(dos and don'ts)、示例以及出色的格式化。这些都再次证明了 Claude Code 依赖于精心设计的提示来指导其复杂行为,而非简单的硬编码逻辑。

    提示调优与模型特定性

    鉴于 Claude Code 中涉及如此多的提示工程,值得注意的是,提示调优是高度依赖模型家族的。对于那些尝试将 Sonnet 模型切换到其他外部提供商模型的用户来说,可能会发现工具调用能力和准确性不如 Sonnet。在大多数情况下,这并非因为这些模型能力较弱,而是因为这些系统提示——以及所有在此看到的提示——都必须针对所使用的模型家族进行专门调优。适用于 OpenAI 模型的提示可能在 Anthropic 模型上表现不佳。因此,无论何时切换模型或构建代理,都应确保有评估和提示调优技术到位,以便能够快速迭代。显而易见,优秀的代理循环由精心设计的提示定义,这些提示包含清晰的指令和工作流。提示工程在 2025年 仍然是一个重要的领域,并将在相当长一段时间内保持其重要性。现在,你已经掌握了开始构建自己的编码代理所需的所有原则。如果想了解如何更好地利用 Claude Code 来提取更多价值,可以查看相关工作流视频。在此之前,祝你出货愉快,下次再见。

    Useful links

    These links were generated based on the content of the video to help you deepen your knowledge about the topics discussed.

    Beyond the Hype newsletter
    WebCrack
    Proxy Man
    Anthropic APIs
    Claude Code
    OpenAI
    This article was AI generated. It may contain errors and should be verified with the original source.
    VideoToWordsClarifyTube

    © 2025 ClarifyTube. All rights reserved.