Claude Code 用过的都说好,丝滑、懂你,甚至让你写码都感觉上头,国内的DeepSeek v3.1,Qwen, Kimi k2, 智谱GLM-4.5都已经支持了Claude Code的调用,但为什么CC如此好,背后的原因是什么?以及该如何在自己的 Agent/工作流里复刻Claude Code 的体验 2.保持单一循环。 说真的,99% 的场景根本不需要什么框架或多智能体协作。Claude Code 就只有一个主循环,最多带一个分支(而且分支也是它自己) 注意:这篇博文并非 Claude Code 的架构揭秘(市面上已经有一些不错的了)。这篇文章旨在成为构建优秀 LLM 智能体的指南,其基础是作者过去几个月使用和捣鼓 Claude Code 的个人经验 Claude Code 是我迄今为止用过的最令人愉悦的 AI 智能体/工作流。它不仅让针对性修改或凭感觉写点一次性工具这类事变得不那么烦人,使用 Claude Code 本身就让我感到快乐。它有足够的自主性来做一些有趣的事情,同时又不会像其他一些工具那样,带来突兀的失控感。当然,大部分的重活儿都是由新的 Claude 4 模型(尤其是其多模态思维能力)完成的。但我发现,即便与同样使用底层模型的 Cursor 或 Github Copilot 智能体相比,Claude Code 在客观上也确实没那么烦人!到底是什么让它这么好用?如果你正在一边读一边点头,那么我将尝试给出一些答案 Claude Code (CC) 的使用体验之所以很棒,是因为它就是好用。CC 的构建基于对 LLM 擅长什么和不擅长什么的深刻理解。它的提示词和工具弥补了模型的不足之处,并帮助它在自己擅长的领域大放异彩。它的控制循环非常简单,易于理解和调试。 CC 一发布,我们 MinusX 就开始使用了。为了探究其内部机制,同事Sreejith 写了一个记录器,可以拦截并记录每一个网络请求。接下来的分析来自我过去几个月的广泛使用经验。这篇文章试图回答这个问题 ——“是什么让 Claude Code 如此出色,以及你如何在自己的基于聊天的 LLM 智能体中提供类似 CC 的体验?”我们已经在 MinusX 中集成了其中大部分经验,也很期待看到你将它们付诸实践! 如果说这篇文章只有一个核心要点,那就是 —— 保持简单,傻瓜原则(Keep Things Simple, Dummy)。LLM 的调试和评估已经够头疼的了。你引入的任何额外复杂性(如多智能体、智能体间的交接、或复杂的 RAG 搜索算法)只会让调试难度增加 10 倍。如果这样一个脆弱的系统侥幸能跑起来,你之后也会因为害怕破坏它而不敢做任何大的改动。所以,把所有东西都放在一个文件里,避免过度复杂的样板代码,并且至少要把它推倒重来几次 :) Claude Code 在每一个关键节点都选择了架构上的简洁 —— 单一主循环、简单的搜索、简单的待办事项列表等等。抵制过度设计的冲动,为模型构建好约束框架,然后就让它自己“大展身手”吧!这不就是端到端自动驾驶的翻版吗?惨痛的教训,不是吗? 尽管多智能体系统现在非常流行,Claude Code 只有一个主线程。它会周期性地使用几种不同类型的提示词来总结 git 历史、将消息历史合并成一条,或者搞出一些有趣的 UX 元素。但除此之外,它维护的是一个扁平的消息列表。它处理层级任务的一个有趣方式是,通过生成一个自身的克隆作为子智能体来处理,但这个子智能体无法再生成更多的子智能体。这里最多只有一个分支,其结果会作为一个“工具响应”被添加回主消息历史中。 如果问题足够简单,主循环就通过迭代式地调用工具来处理。但如果有一个或多个复杂任务,主智能体就会创建自己的克隆。这种“最多单分支”和待办事项列表的结合,确保了智能体既有能力将问题分解为子问题,又能始终关注最终期望的结果。 我非常怀疑你的应用是否真的需要一个多智能体系统。每增加一层抽象,都会让你的系统更难调试,更重要的是,这会让你偏离通用模型改进的康庄大道。 CC 发出的所有重要的 LLM 调用中,超过 50% 是发给claude-3-5-haiku的。它被用来读取大文件、解析网页、处理 git 历史和总结长对话。它甚至被用来生成那个用于提示正在处理中的单词标签——毫不夸张地说,每次按键都会调用!这些小模型比标准模型(如 Sonnet 4, GPT-4.1)便宜 70-80%。所以,大胆地用吧! Claude Code 的提示词极其详尽,充满了启发式规则、示例和那种“敲黑板”式的重点提醒。系统提示词本身约有 2800 token,而工具定义部分则更是占据了高达 9400 token 的惊人篇幅。用户提示词总是包含claude.md文件的内容,这通常又有 1000-2000 个 token。系统提示词包含了对于语气、风格、主动性、任务管理、工具使用策略和执行任务等部分。它还包含了日期、当前工作目录、平台和操作系统信息,以及最近的 git 提交记录。 大多数代码智能体的开发者都已经形成了一个共识模式,那就是使用上下文文件(也叫 Cursor Rules /claude.md/agent.md)。Claude Code 在有和没有claude.md的情况下,其表现有天壤之别。这是一种让开发者传递代码库中无法推断的上下文,以及明确所有严格偏好的绝佳方式。例如,你可以强制 LLM 跳过某些文件夹,或使用特定的库。CC 会在每次用户请求时,发送claude.md的全部内容。 ,:这些标签用来固化启发式规则。当模型面临一个十字路口,有多个看似合理的路径/工具调用可以选择时,它们特别有用。示例可以用来对比不同情况,并清楚地指明哪条路径是更可取的。例如: CC 与其他流行的代码智能体的一个显著区别在于它抛弃了 RAG。Claude Code 搜索你的代码库的方式和你自己一样,使用非常复杂的ripgrep、jq和find命令。由于 LLM 对代码的理解能力非常强,它可以使用复杂的正则表达式来找到任何它认为相关的代码块。有时,它甚至会用一个小模型来读取整个文件。 RAG 理论上听起来不错,但它引入了新的(而且更重要的是,隐藏的)失败模式。该用什么相似度函数?用什么重排器?如何对代码进行分块?如何处理大的 JSON 或日志文件?而使用 LLM 搜索,它只需要看 10 行 JSON 文件就能理解其结构。如果需要,它还可以再看 10 行——就像你一样。最重要的是,这是可以通过强化学习(RL)来优化的——这正是那些大模型公司已经在做的事情。模型完成了大部分的重活儿——理应如此,这极大地减少了智能体中活动部件的数量。另外,将两个复杂的智能系统以这种方式连接起来本身就很丑陋。我最近和一个朋友开玩笑说,这是 LLM 时代的摄像头与激光雷达之争,而且我不是在开玩笑。 这个问题让每一个构建 LLM 智能体的人夜不能寐。你应该给模型通用的任务(比如有意义的动作),还是应该给它底层的任务(比如打字、点击和 bash 命令)?答案是:看情况(而且你应该两者都用) Claude Code 既有底层工具(Bash,Read,Write),也有中级工具(Edit,Grep,Glob)和高级工具(Task,WebFetch,exit_plan_mode)。CC 可以用 bash,那为什么还要单独给一个 Grep 工具呢?这里的真正权衡在于,你期望智能体使用该工具的频率 vs. 智能体使用该工具的准确性。CC 使用 grep 和 glob 非常频繁,以至于将它们做成单独的工具是合理的,但同时,它也可以为特殊场景编写通用的 bash 命令。 类似地,还有像WebFetch或mcp_ide_getDiagnostics这样更高级的工具,它们的功能非常确定。这避免了 LLM 需要执行多个底层的点击和输入操作,让它能保持在正轨上。工具描述中有详尽的提示词和大量示例。系统提示词中还有对于“何时使用某个工具”或如何在两个可以完成相同任务的工具之间进行选择的信息。 这样做有很多好处。上下文退化是长时运行的 LLM 智能体中的一个常见问题。它们一开始满怀热情地解决一个难题,但随着时间的推移,它们会迷失方向,最终输出一堆垃圾。 目前智能体设计中有几种方法来解决这个问题。许多智能体尝试过明确的待办事项(一个模型生成待办事项,另一个模型实现它们),或者多智能体交接+验证(PRD/PM 智能体 → 实现者智能体 → QA 智能体)。 我们已经知道,由于种种原因,多智能体交接不是一个好主意。CC 使用了一个明确的待办事项列表,但这个列表是由模型自己维护的。这让 LLM 保持在正轨上(它被强烈提示要频繁参考待办事项列表),同时给予模型在实现过程中随时修正路线的灵活性。这也有效地利用了模型的多模态思维能力,可以即时拒绝或插入新的待办事项 CC 明确地尝试控制智能体的美学行为。系统提示词中有对于语气、风格和主动性的部分——充满了指令和示例。这就是为什么 Claude Code 在其注释和积极性方面让人感觉很有品味。我建议直接将这部分的大段内容复制到你的应用中 不幸的是,在要求模型不要做某件事方面,CC 并没有更高明的办法。IMPORTANT,VERY IMPORTANT,NEVER和ALWAYS似乎仍然是引导模型避开雷区的最佳方式。我期望模型未来会变得更具可引导性,从而避免这种粗暴的方式。但就目前而言,CC 大量使用这种方法,你也应该如此。一些例子: 识别出 LLM 需要执行的最重要任务,并为其写出算法,这是极其重要的。尝试角色扮演成 LLM,通过示例进行推演,识别出所有的决策点并明确地写下来。如果能以流程图的形式呈现会更有帮助。这有助于结构化决策过程,并辅助 LLM 遵循指令。一定要避免的是,写一大堆杂乱的“该做”和“不该做”。它们很难被追踪,而且容易相互矛盾。如果你的提示词长达几千个 token,你很可能会无意中写下相互冲突的“该做”和“不该做”。在这种情况下,LLM 会变得极其脆弱,并且无法融入新的用例。 Claude Code 系统提示词中的Task Management、Doing Tasks和Tool Usage Policy部分,清晰地阐述了需要遵循的算法。这也是一个可以添加大量启发式规则和 LLM 可能遇到的各种场景示例的地方 在引导 LLM 方面,很多工作其实是在尝试逆向工程它们的后训练/RLHF 数据分布。应该用 JSON 还是 XML?工具描述应该放在系统提示词里还是直接放在工具定义里?你应用当前的状态信息呢? 看看它们在自己的应用中是怎么做的,并以此来指导你自己的设计,是很有帮助的。Claude Code 的设计非常有主见,借鉴它有助于形成你自己的设计思路


