找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4631

积分

0

好友

635

主题
发表于 5 天前 | 查看: 21| 回复: 0

很多人用 Claude Code 写代码时,感觉它特别“靠谱”。任务拆得清晰,代码改得稳健,不会随意添加冗余内容,也很少跑偏方向。表面上看,这似乎是模型能力强,或者 prompt 写得巧妙。但实际情况并非如此。

Agent OS架构图

我深入分析了它的 npm 包源码,发现真相完全不同。它根本不是一个简单的命令行聊天机器人,而是一整套Agent 操作系统。它的强大,源自模块化的提示词装配、专门的 Agent 调度、可治理的工具执行流程,以及将安全和扩展都做成系统级机制。这套设计让它从玩具级工具进化成了能长期使用的产品级系统。

普通开发者初次接触编码 Agent 时,常常以为只要接入一个大模型、加几个 shell 工具就够了。但实际上跑起来,上下文污染、行为漂移、安全边界模糊这些问题很快就会浮现。Claude Code 提前用工程化手段堵住了这些漏洞,因此使用体验才如此顺畅。

核心结论很明确:Claude Code 的优势不在于任何一段神秘的 prompt,而在于它将提示词、Agent 编排、工具治理和扩展机制整合成了一套可产品化的运行时。这套系统让模型不再是临场发挥,而是按照工程规范一步步执行任务。

Claude Code 的提示词不是一坨固定文字,而是装配框架

首先,要理清提示词装配是什么。它就像搭积木,并非将所有规则一次性塞给模型,而是把不同部分按需组合成最终的系统指令。Claude Code 在 src/constants/prompts.ts 中实现了这个框架。

这个框架先定义身份和开场白,告诉模型它是谁、应该以何种风格回应。接着是基础规则,涵盖如何完成软件工程任务、工具应该如何使用、遇到风险动作是否需要用户确认。最重要的部分,是将工程行为哲学直接写入了规则:不要做用户未要求的功能,不要过度抽象代码,没必要就别重构,别乱加注释或类型定义,先阅读现有代码再提出修改,不要轻易新建文件。如果任务失败,先诊断问题,不要盲目重试。结果必须诚实汇报,没验证过就别说验证过了。这些不是建议,而是硬性要求。

为什么这么做?因为很多编码 Agent 出问题,并非模型不够聪明,而是行为容易漂移。将良好的工程习惯制度化后,模型就能少走弯路。提示词里还专门写明了工具使用规范:读文件优先用 FileRead,改文件优先 FileEdit,新建文件用 FileWrite,搜文件用 Glob,搜内容用 Grep,只有真正需要 shell 时才用 Bash。无依赖的工具调用应尽量并行执行。这套语法让模型知道“应该如何正确地使用工具”,而不仅仅是“有工具可用”。

更高级之处在于它具备 prompt cache boundary(提示词缓存边界)意识。源码中使用了动态边界标记,将稳定部分和会话特定部分分离开。这样一来,哪些内容适合缓存、哪些必须动态注入、如何减少 token 浪费,都考虑周全了。这已经超越了 prompt 手艺活的范畴,属于基础设施级别的工程设计。

假设你在编写一个大型项目,如果模型每次都要重新读取全套规则,会浪费大量 token,还容易导致缓存失效。Claude Code 通过装配框架,将稳定规则做成对缓存友好的前缀,动态部分只注入必要内容,实际使用时响应更快、成本更低。这就是它在长任务中表现特别稳定的原因。普通开发者如果只抄一段 prompt 去做类似工具,很快就会发现上下文膨胀、重复计算等问题,而 Claude Code 提前将这些问题都工程化了。

提示词还进行了分层处理。除了主系统提示,还有独立的 Agent prompt 层。子 Agent 运行在更窄、更实用的协议下:用可用工具完整完成任务,不要半成品,不要过度装饰,完成后给出简洁报告。这层协议确保了子任务不会污染主上下文。整个装配系统把 markdown、metadata 和运行时约束结合在一起,形成了可扩展的产品运行时环境。

Agent 调度不是简单 fork 子任务,而是专业化分工系统

在这里,Agent 不是随便开一个新的聊天窗口。它是一套完整的编排系统。源码中 src/tools/AgentTool/runAgent.ts 及相关文件清晰地描述了这一流程。

先解释 Agent 是什么:它相当于给模型分配一个带有特定角色和专用工具池的工作线程。Claude Code 内置了多种专业 Agent,而不是让一个 Agent 包揽所有工作。General Purpose Agent 负责常规执行,Explore Agent 是纯读模式,Plan Agent 负责规划,Verification Agent 负责验证。这些分工直接写在了 prompt 里,模型知道什么时候该用哪个、如何编写子 Agent 的提示词、理解前台和后台的区别,以及工作树隔离的含义。

Explore Agent 为例。它被严格限制为只读专家:绝对不可以创建、修改、删除文件,不能写临时文件,不能运行改变系统状态的命令。它只能通过搜索、读取文件和受限的 shell 来探索代码库,追求快速回报,并尽量并行调用工具。这不是普通的搜索 Agent,而是被特意裁剪成只做探索、不碰状态的专家。

Plan Agent 也是只读的。它的工作是彻底理解需求、探索代码库、寻找现有模式、设计实现方案、给出分步计划,最后列出关键实现文件。它是架构师,而非执行者。

最有意思的是 Verification Agent。它的任务不是走过场地确认“看起来没问题”,而是被明确指令要求 try to break it。它需要对抗两种常见的失败模式:一是只读代码不运行命令就直接通过;二是被表面成果所迷惑。实际要求是运行构建、测试、代码检查工具,针对改动类型采用不同策略,进行对抗性探测,每个检查都必须给出执行的命令和观察到的输出,最后输出 VERDICT: PASS / FAIL / PARTIAL。这套逻辑将验证做成了对抗性流程,从根本上避免了“自己给自己发毕业证”的情况。

子 Agent 的执行分为两条路径:fork pathnormal pathfork 适合需要继承上下文又不想污染主线程的情况,它尽量保持系统提示词和工具定义一致,以利于提示词缓存命中。normal path 则为指定类型的 Agent 构造隔离的上下文。runAgent 函数是子 Agent 运行时的构造器,它需要初始化 MCP 服务器、合并工具、克隆上下文、管理文件状态缓存、注册钩子、预加载技能、创建 ToolUseContext,并在结束时清理一切。这不是简单的包装器,而是一整套运行时构造流程。

普通开发者第一次构建多 Agent 系统时,最头疼的就是上下文变成信息垃圾场,或者 token 浪费严重。Claude Code 用 fork 机制和缓存优化解决了前者,用专业化分工解决了后者。整个调度链从 AgentTool.call 作为路由控制器开始,解析参数、检查权限、构造提示词,再进入 runAgent 执行。这条管道让 Agent 的行为可预测、可治理。

工具执行、Hook 和扩展机制:把治理做成运行时的一部分

在 Claude Code 中,工具执行不是直接调用函数,而是一条完整的处理管道。toolExecution.ts 描述了整个流程:查找工具、解析 MCP metadata、进行模式验证、执行推测性检查、运行 pre-tool hooks、根据 hook 结果做出权限决策、执行工具、写入遥测数据、执行 post-tool hooks、组装结果。如果失败,还会走 failure hook 流程。

权限模型是整个系统的骨架。它决定了哪些工具能自动运行、哪些需要询问用户、hook 如何参与、后台 Agent 受到什么约束。hook 本身支持 pre-tool-usepost-tool-usepost-failure 等类型,能够发送消息、返回阻塞性错误、改写输入、注入上下文、返回 allow/ask/deny,甚至在某些情况下改写 MCP 输出。但 hook 给出的 allow 指令并不会绕过其他权限规则,运行时仍然会检查设置和交互要求。这正是成熟系统与玩具项目的区别。

技能并非简单的说明文档,而是面向提示词的、模块化的工作流。当模型匹配到某个技能时,它必须先调用 Skill 工具,不能只在对话中提及。技能是按需加载的,不会一开始就把所有内容塞进提示词。插件则更进一步,它通过提供 markdown 命令、暴露 SKILL.md、前端元数据、允许使用的工具约束、shell 声明等,将提示词内容、元数据和运行时约束打包成一个扩展包。

MCP 不只是工具桥接层,还能将指令拼接到系统提示词中,同时扩展模型能做什么、以及该如何理解这些能力。这让扩展同时成为能力桥梁和行为扩展渠道。

钩子与权限的结合,将运行时治理做到了极致。整个工具层还围绕上下文、缓存、遥测、生命周期进行了工程化设计,因此用起来不像一个实验项目,更像一个需要长期维护的软件产品。

Claude Code 把 markdown、metadata 和 runtime constraints 结合起来的 plugin system,让扩展不再是外部漂着的脚本,而是模型能直接感知的行为模块。

假设你在本地运行一个编码助手,普通的工具调用很容易失控:模型乱跑危险命令,或者钩子绕过了安全检查。Claude Code 的管道在每一步都插入了验证和治理点,跳过任何一步都会让行为变得不可控。这就是为什么它能在真实环境中使用,而不仅仅是停留在演示阶段。

操作案例:Verification Agent 在实际任务中的完整流程

以 Verification Agent 为例,看看这套系统如何落地。假设主 Agent 完成了一次代码修改,现在需要进行验证。

第一步,主模型调用 AgentTool,指定 subagent_typeVerification Agent,同时传入描述和提示词。为什么要有这一步?如果不指定类型,就会走普通路径,上下文容易被污染;指定后,系统会构造 Agent 特定的系统提示词和工具限制。

第二步,AgentTool.call 解析参数,检查队友约束、MCP 服务器是否满足、隔离模式,然后分流到 forknormal 路径。这里,如果任务适合继承上下文,就走 fork,保持缓存友好性;否则,就构造隔离的工作上下文。跳过这一步,主线程很快就会被中间验证日志淹没。

第三步,runAgent 进行初始化:合并继承的和本地的 MCP 客户端、克隆上下文消息、管理文件状态缓存、获取系统上下文、对只读 Agent 进行精简、解析工具池、构建 Agent 特定的提示词、注册前端元数据钩子和技能、创建 ToolUseContext、记录执行记录。为什么需要这么多初始化步骤?是为了让这个 Agent 成为一个自包含的运行时包,不依赖于外部状态。

第四步,进入执行循环。Verification Agent 收到指令:try to break it。它先探索代码,运行构建、测试套件、代码检查工具、类型检查,根据改动类型选择策略,进行对抗性探测。每一步都必须输出命令和观察到的输出,最后给出 VERDICT。这一步如果只是读代码而不运行命令,就会触发提示词中的“verification avoidance”警告,直接判定为 FAIL。

第五步,结束时,runAgent 清理 MCP、钩子、shell 任务和内存状态,同时把结果组装成 tool-result block 返回给主线程。为什么要清理?如果不清理,就会积累垃圾上下文,导致下次任务时 token 使用量爆炸。

运行完这一流程,你会看到主 Agent 收到干净的 PASS/FAIL 报告,附带所有命令输出和最终判定。没有中间噪音,权限也全程受到控制。如果是在生产环境,遥测系统还会记录整个过程以供后续分析。

在这个案例中,每一步都服务于“让验证真正有效”这个目标,而不是走形式。普通开发者自己搭建 Agent 时,往往只写个提示词说“去验证一下”,结果模型就随便看两眼说“OK”。而 Claude Code 把对抗逻辑、工具限制、输出格式都硬编码进了运行时,所以验证才可靠。

Claude Code 的这套设计为所有想做编码 Agent 的人指明了一条道路:不要再把希望寄托在“魔法提示词”上。真正能长期成立的,是模块化的提示词装配、可治理的工具运行时、将工作流做成技能资产、Agent 专业化分工、上下文卫生、让扩展对模型可感知、将安全写入运行时。这些才是真正的护城河。

下次使用 Claude Code,或者自己搭建类似工具时,可以先思考它背后的系统设计,而不仅仅是看表面输出。你会发现,优秀的 Agent 产品,从来都不是模型单打独斗,而是将工程思维变成了可执行的代码。如果你想深入研究更多优秀的 Agent 项目设计,可以参考 云栈社区 上的相关讨论和开源实战板块。




上一篇:Claude Code源码分析:其强势代码能力或源于工程架构,非大模型
下一篇:iOS 26.4开放CarPlay AI功能接入:ChatGPT已上车,第三方应用体验如何?
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-4-7 15:53 , Processed in 0.725206 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表