
2024年以来,大模型Agent领域的竞争愈发激烈,从基础的对话助手到复杂的自动编码工具,大家都在探索如何让AI具备更稳定、更高效的自主执行能力。而Claude Code源码的意外泄露,给整个技术圈送来了一份"宝藏级"参考资料,它没有藏着什么惊世骇俗的算法,却用一套成熟的设计模式,揭示了生产级AI编码助手的底层逻辑。
很多开发者拿到源码后,第一时间忙着逐行研读代码细节,试图复刻功能。但在我看来,源码背后的设计思路,远比代码本身更有价值。这些设计模式不是Claude Code专属的"黑科技",而是通用的Agent架构智慧,无论你用的是GPT、Claude还是国内的大模型,无论你开发的是编码助手、自动化办公工具还是其他Agent应用,这些模式都能直接复用。
Kubernetes Patterns和Prompt Patterns的作者Bilgin lbryam,从Claude Code源码中梳理出了12个可复用的Agentic Harness设计模式,并将其分为四大类:记忆与上下文、工作流与编排、工具与权限、自动化。这四大类正好对应了Agent开发中最核心的四个痛点:如何让Agent记住关键信息且不浪费资源,如何让复杂任务有序推进,如何控制Agent的操作风险,如何减少重复操作并避免出错。
今天,我们就来深度拆解这12个设计模式,用通俗易懂的语言讲清每个模式的核心逻辑、实现方式、适用场景和权衡点,再结合实际开发场景补充实战建议,让你既能理解原理,又能直接落地到自己的Agent项目中。文章会尽量避免晦涩的技术术语,用生活化的类比降低理解门槛,同时保证内容的专业性和实用性,总字数超过3000字,全程一气呵成,带你彻底吃透生产级Agent的设计精髓。
一、记忆与上下文:让Agent"记得住、记得清、不浪费"
Agent的"记忆"就像人的大脑,既要记住关键信息,又不能杂乱无章,更不能因为记太多东西而"卡顿"。Claude Code中关于记忆与上下文的5个设计模式,本质上是一条逐步演进的优化路径:从最初的固定规则加载,到按范围精准匹配,再到分层管理记忆,最后通过清理和压缩,让记忆始终保持高效可用。
这五个模式层层递进,解决了Agent记忆过程中的核心痛点:重复劳动、规则混乱、资源浪费、记忆臃肿、上下文溢出。无论是开发编码助手,还是其他需要长期交互的Agent,这五个模式都能直接套用,让Agent的"记忆能力"更接近人类的思维逻辑。
1. 持久化指令文件模式(Persistent Instruction File Pattern):告别"每次都从零开始"
在没有这个模式之前,很多Agent的会话都像"鱼的记忆",每次对话都要重新交代规则、约定和边界。比如你开发一个编码助手,每次让它处理同一个代码库,都要反复告诉它构建命令、测试方式、命名规范,甚至有时候,它会犯和第一次对话时一样的错误,因为它根本没有"长期记忆",每次会话都是全新的开始。
这种方式不仅浪费开发者的时间,也会让Agent的输出质量不稳定,毕竟人都会忘记重复的指令,更别说依赖提示词的大模型了。而持久化指令文件模式,就是为了解决这个问题而设计的,它的实现方式非常简单,却能带来质的提升。
这个模式的核心思路是:在项目根目录下,放置一个项目级的配置文件,比如命名为agent\-instructions\.md,里面详细写清楚Agent需要遵守的所有规则,包括构建命令(如npm run build、mvn package)、测试方式(如pytest、jest)、架构规则(如分层架构、微服务规范)、命名约定(如变量命名采用小驼峰、类名采用大驼峰)、代码注释规范等。这个文件会跟着代码仓库一起管理,每次Agent启动会话时,会自动加载这个文件,无需人工重复输入。
举个实际的例子:如果你开发一个针对React项目的编码助手,持久化指令文件里可以这样写:
-
构建命令:npm run dev(开发环境)、npm run build(生产环境);
-
测试命令:npm test(使用Jest进行单元测试);
-
命名规范:组件名采用大驼峰(如UserList),函数名采用小驼峰(如handleClick),常量采用全大写(如MAX_PAGE_SIZE);
-
架构规则:遵循React Hooks规范,禁止在循环、条件语句中使用useState、useEffect;页面组件放在src/pages目录,公共组件放在src/components目录;
-
注释规范:组件必须添加类注释,说明组件功能、props参数;复杂函数必须添加注释,说明输入输出、逻辑流程。
这样一来,每次Agent处理这个React项目时,都会自动加载这些规则,不会再出现"忘记命名规范""用错构建命令"的问题,开发者也不用每次都重复交代这些细节,效率会大大提升。
适用场景:需要在多个会话里反复处理同一个代码库,或者多个开发者共用同一个Agent处理同一个项目。比如团队内部的编码助手、针对特定项目的自动化工具等。
权衡点:这个模式虽然好用,但存在一定的维护成本。持久化指令文件需要跟着项目一起更新,如果项目的构建命令、命名规范发生了变化,而指令文件没有及时更新,就会误导Agent,导致输出错误,反而不如没有这个文件。所以,使用这个模式时,一定要安排专人维护指令文件,确保其与项目实际情况保持一致。
实战建议:可以在指令文件中添加版本号,每次更新后标注更新记录,同时在项目README中说明指令文件的作用和维护方式,避免出现"指令过时"的问题。另外,可以将指令文件拆分成多个子文件,比如命名规范、构建测试、架构规则分别放在不同的文件中,方便维护和更新。
2. 作用域上下文组装模式(Scoped Context Assembly Pattern):解决"规则太多太乱"的难题
持久化指令文件在小项目里非常好用,但当项目规模扩大,比如变成Monorepo项目(一个仓库管理多个子项目)、多语言项目,或者不同目录有不同的代码规范时,单一的指令文件就会出现问题:要么越写越长,几百甚至几千行,没人愿意看也没人愿意维护;要么写得太笼统,对具体的子目录、子项目没有针对性,根本起不到指导作用。
比如一个Monorepo项目,里面包含前端React项目、后端Java项目、移动端Flutter项目,每个项目的编码规范、构建命令、测试方式都不一样。如果把所有规则都写在一个持久化指令文件里,文件会变得异常庞大,而且Agent在处理前端代码时,会加载后端的规则,造成不必要的干扰;处理后端代码时,又会加载前端的规则,同样影响效率。
作用域上下文组装模式,就是为了解决这个问题而设计的。它的核心思路是:将指令拆到不同的作用域中,按照"组织级-用户级-项目根目录-父目录-子目录"的层级划分,Agent会根据当前所在的位置(比如正在处理的文件路径),动态加载对应的规则,实现"全局一致、局部差异"的效果。
具体来说,我们可以在不同的层级放置对应的指令文件,比如:
-
组织级:放置整个团队通用的规则,比如代码提交规范、安全规范,所有项目都需要遵守;
-
用户级:放置单个开发者的个人偏好,比如代码注释风格、常用工具配置,只对当前用户生效;
-
项目根目录:放置当前项目通用的规则,比如项目的整体架构、依赖管理规范;
-
父目录:放置某个子模块通用的规则,比如前端模块的通用规范;
-
子目录:放置具体目录的特殊规则,比如某个组件目录的编码规范。
Agent在处理文件时,会自动识别当前文件的路径,然后从下到上加载所有对应的指令文件,子目录的规则会覆盖父目录的规则,用户级的规则会覆盖组织级的规则,以此实现"局部优先、全局兜底"的效果。另外,通过导入的方式,还可以把大的指令集拆开管理,比如将组织级的安全规范导入到项目根目录的指令文件中,避免重复编写。
举个例子:一个Monorepo项目,根目录下有agent\-instructions\.md(项目通用规则),前端目录(src/frontend)下有agent\-instructions\.md(前端通用规则),前端组件目录(src/frontend/components)下有agent\-instructions\.md(组件特殊规则)。当Agent处理src/frontend/components/Button.jsx文件时,会依次加载组件目录、前端目录、项目根目录、组织级、用户级的指令文件,组件目录的规则会覆盖前端目录的规则,确保指令的针对性。
适用场景:Monorepo项目、多语言项目,或者不同目录有不同规范的代码库。比如大型团队的多模块项目、跨语言的全栈项目等。
权衡点:这个模式虽然解决了规则混乱的问题,但会降低可读性。规则分散在多个文件、多个层级中,很难一眼看清Agent实际加载了哪些规则,不同作用域之间也可能出现规则冲突,比如子目录的规则和父目录的规则不一致,需要额外的冲突处理机制。
实战建议:可以在每个指令文件中添加"作用域说明",明确该文件的适用范围和优先级;同时,建立规则冲突的处理原则,比如"子目录覆盖父目录、用户级覆盖组织级",并在Agent中添加冲突提示功能,当检测到规则冲突时,及时提醒开发者处理。另外,可以开发一个辅助工具,用于查看当前文件实际加载的所有规则,提升可读性。
3. 分层记忆模式(Tiered Memory Pattern):让Agent"记重点、不浪费"
无论是持久化指令文件,还是作用域上下文组装,本质上都是让Agent"记住"规则。但如果一个Agent什么都用同一种方式记住,最后往往什么都记不好。比如,把所有记忆都塞进上下文窗口,每次会话都会浪费大量的token,而且很容易撞上上下文窗口的限制,重要的信息被无关信息淹没,Agent反而无法快速找到关键内容。
举个例子:如果Agent处理一个大型项目,需要记住项目的架构、编码规范、历史对话记录、用户偏好等所有信息,并且把这些信息都塞进上下文窗口,那么上下文很快就会被占满,后续的对话无法继续,而且Agent在处理具体任务时,需要在大量信息中筛选关键内容,效率会非常低。
分层记忆模式,就是为了解决"记忆效率低、资源浪费"的问题。它的核心思路是:将Agent的记忆分层管理,分为"索引层、活跃层、持久层"三个层级,每个层级的记忆有不同的存储方式和使用场景,确保关键信息能快速被获取,同时避免浪费token和上下文资源。
具体来说,三个层级的分工如下:
-
索引层:一个精简的记忆索引,始终放在上下文窗口中,控制在几百行以内,包含最核心、最常用的信息,比如项目的核心架构、关键命令、用户的核心偏好等。Agent在处理任何任务时,都能快速从索引层获取关键信息,无需在大量记忆中筛选。
-
活跃层:与当前任务相关的记忆内容,按需加载到上下文窗口中。比如Agent正在处理某个组件的开发,就会将该组件的相关规则、历史修改记录、依赖信息等加载到活跃层,任务完成后,活跃层的内容会被清理,避免占用上下文资源。
-
持久层:完整的历史记忆记录,存储在磁盘或数据库中,不放入上下文窗口,只有在需要时才会被查询。比如项目的完整历史对话记录、所有的规则文件、历史修改记录等,Agent在需要追溯历史信息时,会从持久层中查询,查询完成后,只将关键结果加载到上下文窗口中。
举个实际的例子:一个编码助手处理一个大型React项目,索引层中会包含项目的核心架构(如src/pages、src/components目录结构)、关键命令(npm run dev、npm test)、用户的核心偏好(如喜欢用函数组件、不使用class组件);当Agent处理Button组件的开发时,会将Button组件的编码规范、依赖信息、历史修改记录加载到活跃层;而项目的所有历史对话记录、完整的规则文件,则存储在持久层中,当需要追溯某个历史问题时,Agent会从持久层中查询相关信息。
这种分层管理的方式,既保证了Agent能快速获取关键信息,又避免了上下文窗口被无关信息占用,节省了token资源,同时也解决了"记忆太多导致混乱"的问题。
适用场景:需要跨多次会话保留偏好、决策或状态的Agent,比如长期使用的编码助手、自动化办公工具、客服Agent等。
权衡点:这个模式的实现会更复杂。需要开发者想清楚,哪些信息应该放在索引层,哪些应该放在活跃层,哪些应该放在持久层;还要设计好信息的上升和下沉机制,比如某个活跃层的信息被频繁使用,就可以上升到索引层;某个索引层的信息长期不被使用,就可以下沉到持久层;同时,还要保证索引层与活跃层、持久层的信息同步,避免出现信息不一致的问题。
实战建议:可以根据信息的"使用频率"和"重要程度"来划分层级,使用频率高、重要程度高的信息放在索引层,使用频率中等、与当前任务相关的信息放在活跃层,使用频率低、重要程度低的信息放在持久层;同时,设计一个自动更新机制,定期统计信息的使用频率,自动调整信息的层级,减少人工维护成本。
4. 记忆整合模式(Dream Consolidation Pattern):给Agent的"记忆"做"垃圾回收"
即使使用了分层记忆模式,Agent的记忆用久了还是会"变乱"。比如,持久层中会积累大量的重复内容,活跃层的信息在任务完成后没有及时清理,索引层的信息会慢慢膨胀,不同层级的信息之间会出现冲突,这些问题都会导致Agent的记忆效率下降,甚至出现错误。
就像人的大脑一样,如果长期不整理,会积累很多无用的记忆,导致思考效率下降,甚至记混重要的信息。Agent的记忆也是如此,长期积累下来,无用的、重复的信息会越来越多,占用大量的存储资源,同时也会影响Agent的判断。
记忆整合模式,就是为了解决"记忆臃肿、混乱"的问题,相当于给Agent的"记忆"做一次定期的"垃圾回收"。它的核心思路是:在Agent空闲时,添加一个后台整理机制,定期对三个层级的记忆进行清理和整合,包括去重、删除无用信息、重组记忆结构、解决信息冲突,让记忆始终保持干净、可用。
Claude Code源码中提到的autoDream功能,本质上就是实现了记忆整合模式。autoDream会在Agent没有任务执行时,自动对记忆进行整理:合并重复的规则和历史记录,删除长期不被使用的无用信息,解决不同层级之间的信息冲突,控制索引层的规模,确保记忆的准确性和高效性。
具体来说,记忆整合的主要操作包括:
-
去重:删除记忆中重复的内容,比如重复的规则、重复的历史对话记录、重复的用户偏好等,减少存储占用;
-
删旧:删除长期不被使用的无用信息,比如超过3个月没有被访问的持久层记录、已经过时的规则等;
-
冲突解决:检测不同层级、不同文件中的规则冲突,按照预设的冲突处理原则(如子目录覆盖父目录)进行解决,确保记忆的一致性;
-
结构重组:优化记忆的存储结构,比如将分散的规则按照类别整理,将历史记录按照时间顺序排序,让Agent能更快速地查询和获取信息;
-
索引优化:控制索引层的规模,将不常用的索引信息下沉到持久层,将常用的持久层信息上升到索引层,确保索引层始终是最核心、最常用的信息。
举个例子:一个编码助手长期处理多个项目,持久层中积累了大量的历史对话记录和规则文件,其中有很多重复的规则(比如不同项目的命名规范有重复部分),还有一些已经过时的规则(比如某个项目已经升级了构建命令,但旧的构建命令还在记忆中)。通过记忆整合模式,后台会自动合并重复的规则,删除过时的规则,将常用的规则上升到索引层,不常用的规则下沉到持久层,让Agent的记忆变得干净、高效。
适用场景:Agent会长期运行、持续积累记忆,而且不方便靠人工去维护的场景,比如企业级的编码助手、长期运行的自动化工具、客服机器人等。
权衡点:记忆整合本身也会消耗token和系统资源,而且整理的准确性不一定能100%保证。如果清理太激进,可能会把有用的信息一起删掉,导致Agent出现记忆丢失的问题;如果清理太保守,又无法解决记忆臃肿的问题。
实战建议:可以设置不同的清理策略,比如对于规则文件,采用"保守清理",只删除明确过时的内容;对于历史对话记录,采用"激进清理",删除超过一定时间且不常用的记录;同时,添加"记忆恢复"功能,当发现有用的信息被误删时,可以从备份中恢复,降低清理风险。另外,可以让用户手动触发记忆整合,当用户发现Agent的记忆出现混乱时,能够手动启动整理流程。
5. 渐进式上下文压缩模式(Progressive Context Compaction Pattern):解决"上下文不够用"的难题
无论是分层记忆还是记忆整合,都无法完全避免上下文窗口不够用的问题。当Agent处理的任务比较复杂,对话轮次较多(比如20~30轮以上)时,上下文窗口很快就会被占满,要么早期的对话内容被挤掉,导致Agent忘记之前的关键信息,要么任务无法继续执行,这两种情况都会严重影响Agent的使用体验。
比如,一个编码助手帮开发者开发一个复杂的功能,需要经过多次对话:需求沟通、方案设计、代码编写、测试修改、优化迭代,每一轮对话都会产生大量的信息,包括需求细节、方案思路、代码片段、测试结果等。随着对话轮次的增加,上下文窗口会越来越满,到最后,早期的需求细节会被挤掉,Agent可能会忘记最初的需求,导致后续的代码修改偏离方向。
渐进式上下文压缩模式,就是为了解决"上下文窗口不足"的问题。它的核心思路是:对上下文内容进行"分层压缩",新的对话内容尽量保留细节,稍旧的内容做轻量总结,再往前的内容逐步压缩,甚至折叠成很短的摘要,越久远的信息,保留得越粗糙,从而在有限的上下文窗口中,保留最关键、最有用的信息。
Claude Code源码中提到的多层压缩机制,就是渐进式上下文压缩模式的具体实现。它将上下文内容分为多个层级,比如:
-
最新层(最近3轮对话):保留完整的对话细节,包括用户的提问、Agent的回复、代码片段、测试结果等,确保Agent能准确获取最新的任务信息;
-
近期层(4~10轮对话):对对话内容进行轻量总结,保留核心信息,比如用户的核心需求、Agent的核心方案、关键的修改意见等,删除冗余的细节;
-
远期层(11轮以上对话):对对话内容进行深度压缩,折叠成简短的摘要,比如"用户要求开发一个登录功能,Agent提供了React组件代码,经过2次修改后达到需求",只保留最核心的任务进展;
-
历史层(更早的对话):如果上下文窗口仍然不够用,就将历史层的内容完全压缩,只保留一个最简洁的摘要,甚至直接删除,只在持久层中保留完整记录,需要时再查询。
这种分层压缩的方式,既能保证Agent能获取最新的任务细节,又能节省上下文空间,避免早期信息被挤掉,同时也能让Agent记住长期的任务进展,不会出现"忘记初心"的问题。
举个例子:一个编码助手帮开发者开发登录功能,对话进行到20轮,上下文窗口已经快满了。此时,最新的3轮对话(18~20轮)保留完整细节,包括用户对登录功能的最后修改要求、Agent的代码回复、测试结果;4~10轮对话(7轮)进行轻量总结,保留用户的核心需求(如支持手机号、密码登录,需要记住密码功能)、Agent的核心方案(如使用React Hook开发,调用后端接口验证);11~17轮对话(7轮)进行深度压缩,折叠成摘要(如"对登录组件进行了3次修改,解决了密码加密、表单验证的问题");更早的对话(1~10轮)只保留一个简洁摘要(如"用户提出开发登录功能,确定需求和技术方案")。这样一来,上下文窗口就能容纳更多的新内容,同时Agent也能记住整个任务的进展。
适用场景:对话轮次比较多(比如20~30轮以上)的任务,比如复杂功能的开发、长期的需求沟通、多阶段的自动化任务等。
权衡点:压缩一定是有损的。信息在一轮轮的总结和压缩中,会丢失一些细节,如果后面的任务又需要这些细节,Agent可能无法准确回忆起来,甚至会"编造"信息,而不是承认不知道。比如,Agent在压缩远期对话时,删除了某个代码片段的细节,后面用户需要修改这个代码片段时,Agent可能会忘记原来的实现方式,导致修改错误。
实战建议:可以根据任务的类型调整压缩策略,比如对于代码开发类任务,核心的代码片段可以保留更久,压缩时尽量不丢失关键代码;对于需求沟通类任务,核心的需求细节可以保留更久;同时,添加"细节回溯"功能,当Agent需要某个被压缩的细节时,能够从持久层中查询完整内容,补充到上下文窗口中,减少信息丢失的影响。另外,可以让用户手动设置压缩层级和保留时间,满足不同任务的需求。
二、工作流与编排:让Agent"有条理、不混乱"
如果说记忆与上下文解决的是Agent"知道什么"的问题,那么工作流与编排解决的就是Agent"怎么做事"的问题。很多开发者在开发Agent时,会把所有操作混在一起:读取文件和写入文件放在同一个步骤,调研信息和修改代码放在同一个上下文,顺序执行和并行执行没有区分,刚开始可能没问题,但当任务变得复杂时,系统就会变得越来越乱,Agent的输出质量也会大幅下降。
Claude Code中关于工作流与编排的3个设计模式,核心就是一个词:分离。将读取和写入分离,将调研和执行分离,将顺序和并行分离,通过合理的流程编排,让Agent的每一步操作都有章可循,即使任务再复杂,也能保持有序高效,避免出现混乱和错误。
6. 探索-规划-行动循环模式(Explore-Plan-Act Loop Pattern):先想清楚,再动手
很多Agent的默认做法是:一收到用户的指令,就立刻动手执行,比如用户让它修改代码,它不先了解代码结构,不先分析需求,直接就开始修改,结果往往是理解不完整,改错文件,漏掉依赖,或者直接忽略现有的实现方式,导致修改后的代码无法运行,甚至破坏原有的功能。
这种"急于动手"的模式,在简单任务中可能不会有太大问题,但在复杂任务中,比如不熟悉的代码库、涉及多个文件的修改,就很容易出问题。而探索-规划-行动循环模式,就是为了解决这个问题,它的核心思路是:将任务流程拆成三步,权限逐步放开,先搞清楚情况,再规划方案,最后动手执行,确保每一步都准确无误。
具体来说,三步流程如下:
第一步:探索(Explore),只读不写,摸清情况。Agent首先以"只读"的权限,读取相关的文件、文档、历史记录,了解项目的架构、代码结构、现有实现方式、相关依赖等,不进行任何修改操作。这一步的目的是让Agent全面了解任务背景,避免因为信息不全而出现错误。比如用户让Agent修改一个接口的逻辑,Agent首先会读取这个接口的代码、相关的调用关系、文档说明,搞清楚这个接口的功能、参数、返回值,以及它与其他模块的依赖关系。
第二步:规划(Plan),沟通对齐,确定方案。Agent在完成探索后,会根据用户的需求和探索到的信息,制定详细的执行方案,包括修改哪些文件、修改哪些内容、执行哪些命令、如何测试等,然后将方案反馈给用户,与用户对齐思路,确认方案的可行性。如果用户有不同的意见,Agent会根据用户的反馈调整方案,直到双方达成一致。这一步的目的是确保Agent的执行方向与用户的需求一致,避免出现"做无用功"的情况。
第三步:行动(Act),动手执行,全程可控。在方案确认后,Agent才会获得"写入"和"执行"的权限,按照规划的方案动手执行,比如修改代码、执行构建命令、运行测试等。在执行过程中,Agent会实时反馈执行进度和结果,如果出现问题,会及时停止执行,反馈给用户,等待用户的指示。这一步的目的是确保执行过程可控,出现问题能及时止损。
举个实际的例子:用户让Agent在一个不熟悉的Java项目中,添加一个"用户积分查询"的接口。Agent会按照以下步骤执行:
-
探索:读取项目的架构文档,了解项目的分层结构(控制层、服务层、数据层);读取用户模块的相关代码,了解用户信息的存储方式、现有接口的实现规范;读取数据库表结构,了解积分相关的字段;读取项目的测试规范,了解接口测试的方式。
-
规划:制定详细的方案,包括在控制层添加积分查询接口(UserPointController),在服务层添加对应的服务实现(UserPointService),在数据层添加查询方法(UserPointMapper);确定接口的参数(用户ID)和返回值(积分数量、积分有效期);制定测试方案,编写单元测试用例,执行接口测试;然后将方案反馈给用户,确认是否符合需求。
-
行动:按照方案,依次修改控制层、服务层、数据层的代码,编写测试用例,执行mvn test命令进行测试,测试通过后,反馈执行结果给用户。如果测试失败,及时停止执行,排查问题,反馈给用户,调整方案后再重新执行。
这种"探索-规划-行动"的循环模式,看似增加了步骤,放慢了速度,但却能大幅提升执行的准确性,避免出现"返工"的情况,反而能节省整体的时间。
适用场景:不熟悉的代码库,或者涉及多个文件的复杂修改,比如新接手的项目、跨模块的功能开发、代码重构等。
权衡点:会比直接执行慢一点。对于一些简单的小任务,比如修改一个变量名、添加一行注释,探索和规划这两步会显得有点"流程过重",浪费时间。
实战建议:可以根据任务的复杂度,动态调整流程的详细程度。对于简单任务,可以简化探索和规划步骤,比如只进行简单的探索,不制定详细的方案,直接执行;对于复杂任务,则严格执行"探索-规划-行动"三步流程。另外,可以在规划阶段,让Agent提供多个方案,供用户选择,提升方案的可行性。
7. 上下文隔离子智能体模式(Context-Isolated Subagents Pattern):避免"信息污染"
当Agent处理长会话、多阶段任务时,很容易出现"上下文污染"的问题。比如,一个任务需要经过调研、规划、代码修改、测试、优化等多个阶段,所有的信息都会堆在同一个上下文窗口中:调研的资料、规划的方案、修改的代码、测试的日志、用户的反馈,全混在一起。当Agent进入下一个阶段时,之前阶段的无关信息会干扰它的判断,导致执行效率下降,甚至出现错误。
比如,Agent在调研阶段收集了大量的资料,这些资料会留在上下文窗口中;进入规划阶段时,这些调研资料会占用大量的上下文空间,而且会干扰Agent的规划思路;进入代码修改阶段时,调研资料和规划方案又会干扰Agent的编码判断,导致Agent写错代码。
上下文隔离子智能体模式,就是为了解决"上下文污染"的问题。它的核心思路是:将任务拆分成多个阶段,每个阶段由一个专门的子Agent负责,每个子Agent都有自己独立的上下文和权限,只处理自己阶段的任务,只接触自己需要的信息,避免被其他阶段的"无关噪声"影响。
具体来说,主Agent会负责任务的拆分和协调,将任务拆分成调研、规划、执行、测试等多个阶段,然后为每个阶段分配一个子Agent,每个子Agent的职责和权限都明确划分:
-
调研子Agent:只负责读取文件、收集资料、分析项目结构,不能进行任何修改操作,它的上下文只包含调研相关的信息,比如项目文档、代码片段、依赖信息等;
-
规划子Agent:只负责根据调研结果和用户需求,制定执行方案,它的上下文只包含调研结果、用户需求、方案相关的信息,不包含具体的代码片段和调研资料;
-
执行子Agent:只负责按照规划方案修改代码、执行命令,它的上下文只包含规划方案、需要修改的代码、执行命令等,不包含调研资料和方案讨论的细节;
-
测试子Agent:只负责执行测试命令、验证执行结果,它的上下文只包含测试用例、测试日志、执行结果等,不包含其他无关信息。
每个子Agent完成自己的任务后,会将核心结果反馈给主Agent,主Agent再将核心结果传递给下一个子Agent,确保信息的传递准确且简洁,避免无关信息进入下一个阶段的上下文。
举个例子:用户让Agent开发一个"商品列表查询"的功能,主Agent将任务拆分成调研、规划、执行、测试四个阶段,分别分配给四个子Agent:
-
调研子Agent:读取项目的商品模块代码、数据库表结构、接口规范,收集商品列表查询需要的字段、依赖的接口、数据来源等信息,然后将核心调研结果(如商品表字段、接口调用方式)反馈给主Agent;
-
规划子Agent:接收主Agent传递的调研结果,结合用户需求(如支持分页、排序、筛选),制定执行方案(如修改商品接口、添加分页参数、编写查询逻辑),将方案反馈给主Agent;
-
执行子Agent:接收主Agent传递的规划方案,修改商品接口代码、添加分页逻辑、调整数据库查询语句,完成后将修改后的代码和执行结果反馈给主Agent;
-
测试子Agent:接收主Agent传递的修改后的代码和方案,编写测试用例,执行测试命令,验证商品列表查询功能是否正常,将测试结果反馈给主Agent。
整个过程中,每个子Agent的上下文都只包含自己需要的信息,不会被其他阶段的无关信息干扰,执行效率和准确性都会大幅提升。
适用场景:长会话、多阶段流程,或者不同阶段对上下文要求差异很大的任务,比如复杂功能开发、项目重构、多步骤自动化任务等。
权衡点:需要额外的协调机制。主Agent需要负责子Agent之间的信息传递,决定每一步传递什么信息、传递多少信息,传少了会丢失关键细节,传多了又会回到上下文污染的问题;同时,子Agent的数量增多,也会增加系统的复杂度和维护成本。
实战建议:主Agent传递信息时,只传递核心内容,比如调研子Agent只传递调研结论,不传递完整的调研资料;规划子Agent只传递最终的方案,不传递方案讨论的过程。另外,可以为每个子Agent设置明确的职责边界,避免子Agent之间出现职责重叠,同时添加子Agent之间的通信机制,当某个子Agent需要补充信息时,能够直接向相关的子Agent请求,减少主Agent的协调压力。
8. 分支-合并并行模式(Fork-Join Parallelism Pattern):让Agent"多线程"干活
很多Agent的默认执行方式是"顺序执行",一次只能处理一件事,即使有些任务可以拆分成多个互不依赖的子任务,也只能排队完成,效率很低。比如,用户让Agent修改10个互不相关的文件,Agent只能一个一个地修改,完成一个再修改下一个,浪费了大量的时间;再比如,用户让Agent同时执行构建命令和测试命令,Agent只能先执行构建命令,再执行测试命令,无法并行执行,延长了任务的总耗时。
分支-合并并行模式,就是为了解决"顺序执行效率低"的问题,它的核心思路是:将一个大任务拆分成多个互不依赖的子任务,每个子任务由一个子Agent在独立的环境中并行处理,互不干扰,等所有子任务都完成后,再将结果合并回来,形成最终的执行结果。
Claude Code中采用的git worktree机制,就是分支-合并并行模式的具体实现。它会为每个子Agent创建一个独立的代码副本(分支),子Agent在自己的代码副本中处理子任务,不会影响其他子Agent的工作,等所有子Agent都完成任务后,再将各个分支的修改合并到主分支,完成整个任务。
具体来说,分支-合并并行模式的流程如下:
-
拆分任务:主Agent将大任务拆分成多个互不依赖的子任务,比如将"修改10个互不相关的文件"拆分成10个子任务,每个子任务对应修改一个文件;
-
分支创建:为主Agent分配一个主分支,为每个子任务分配一个子Agent,并为每个子Agent创建一个独立的分支(代码副本),子Agent在自己的分支中工作,互不干扰;
-
并行执行:所有子Agent同时执行自己的子任务,比如10个子Agent同时修改10个文件,并行执行构建、测试等操作;
-
结果合并:当所有子Agent都完成子任务后,主Agent将各个子分支的修改合并到主分支,解决合并过程中出现的冲突,形成最终的结果;
-
验证测试:主Agent对合并后的结果进行整体测试,确保所有子任务的修改都符合要求,没有出现冲突和错误。
举个实际的例子:用户让Agent对一个React项目进行优化,需要修改5个互不相关的组件(Button、Input、Card、Modal、Dropdown),每个组件的优化逻辑互不依赖。主Agent会将这个任务拆分成5个子任务,每个子任务对应优化一个组件,然后为每个子任务分配一个子Agent,每个子Agent创建一个独立的分支,并行优化对应的组件。比如,子Agent1优化Button组件,子Agent2优化Input组件,子Agent3优化Card组件,同时进行,互不干扰。等所有子Agent都完成优化后,主Agent将5个分支的修改合并到主分支,解决合并过程中可能出现的冲突(比如多个子Agent修改了同一个配置文件),然后执行测试,确保优化后的组件正常运行。
这种并行执行的方式,能大幅缩短任务的总耗时,尤其是当子任务数量较多、每个子任务耗时较长时,效果会非常明显。
适用场景:可以拆成多个互不依赖子任务的场景,比如批量修改文件、多组件优化、并行执行多个命令、跨多个模块的独立修改等。
权衡点:合并过程会更复杂。如果不同的子Agent修改了同一个文件、同一个代码片段,合并时就会出现冲突,而且这种冲突可能比顺序处理时更难解决,因为多个子Agent的修改逻辑可能不同;同时,并行执行也会消耗更多的系统资源,比如内存、CPU等。
实战建议:在拆分任务时,尽量确保子任务之间互不依赖,避免出现大量的合并冲突;对于可能出现冲突的文件(如配置文件),可以指定一个子Agent专门负责修改,其他子Agent不允许修改该文件;同时,添加冲突检测机制,在子Agent执行任务时,实时检测是否修改了可能冲突的文件,及时提醒主Agent和用户;合并冲突时,主Agent可以先尝试自动解决简单的冲突,复杂的冲突反馈给用户,由用户手动解决。
三、工具与权限:让Agent"能做事、不闯祸"
记忆与上下文解决了Agent"知道什么",工作流与编排解决了Agent"怎么做事",而工具与权限则解决了Agent"能做什么"的问题。一个生产级的Agent,不仅要能高效完成任务,还要能控制操作风险,避免因为误操作导致系统故障、数据丢失等问题。
从Claude Code的源码中可以看出,它在工具设计和权限控制上,已经细到了非常具体的粒度,远比现在大多数Agent框架要更严格。这3个设计模式,分别从工具的加载、命令的风险控制、工具的设计三个角度,确保Agent既能使用工具高效完成任务,又能控制操作风险,不"闯祸"。
9. 渐进式工具扩展模式(Progressive Tool Expansion Pattern):按需开放工具,不浪费、不混乱
很多Agent框架的做法是:一开始就把所有的工具都开放给Agent,比如文件操作工具、shell命令工具、搜索工具、数据库操作工具等,不管Agent当前的任务是否需要这些工具。这种做法看似方便,实则会带来很多问题:工具太多,Agent的选择成本变高,很容易选错工具;无关的工具会占用系统资源,影响Agent的执行效率;而且,一些不常用的工具,Agent可能会误用,导致错误。
比如,Agent处理一个简单的代码修改任务,只需要文件读写工具就够了,但如果开放了shell命令工具、数据库操作工具,Agent可能会误执行shell命令,导致系统故障;同时,太多的工具选项,也会让Agent不知道该选择哪个工具,浪费时间。
渐进式工具扩展模式,就是为了解决"工具太多、误用风险高"的问题。它的核心思路是:按需开放工具,一开始只给Agent开放一小部分常用的、低风险的工具,够用就行;随着任务的推进,当Agent需要使用其他工具时,再逐步开放对应的工具,避免无关工具干扰Agent的判断,同时降低误用风险。
具体来说,工具的开放可以分为三个阶段:
-
初始阶段:开放基础工具,比如文件读写工具(读取文件、写入文件)、简单的搜索工具(搜索项目内的文件)、日志输出工具等,这些工具风险低、使用频率高,能够满足大多数简单任务的需求;
-
进阶阶段:当Agent处理的任务变得复杂,需要使用更高级的工具时,再开放对应的工具,比如shell命令工具(执行简单的构建、测试命令)、数据库操作工具(查询、修改数据库)等,同时添加一定的权限限制;
-
高级阶段:当Agent处理一些特殊任务,需要使用高风险工具时,再开放对应的工具,比如系统级命令工具、远程操作工具等,同时添加严格的权限控制和审批机制,确保操作安全。
举个例子:一个编码助手的工具开放流程:
-
初始阶段:开放文件读写工具(如read_file、write_file)、项目内搜索工具(如search_project)、日志输出工具(如log_output),Agent处理简单的代码修改、文件查看任务时,使用这些工具就足够了;
-
进阶阶段:当用户让Agent执行构建、测试任务时,开放shell命令工具(如run_shell),但只允许执行预设的构建、测试命令(如npm run build、pytest),不允许执行高风险命令(如rm -rf、sudo);
-
高级阶段:当用户让Agent部署项目时,开放远程操作工具(如remote_deploy),但需要用户手动审批,Agent才能执行部署操作,同时记录所有的操作日志,便于后续追溯。
这种按需开放工具的方式,既能避免无关工具干扰Agent的判断,降低误用风险,又能节省系统资源,提高Agent的执行效率。
适用场景:工具很多,但大多数任务其实只用到一小部分的场景,比如编码助手、自动化办公工具、企业级Agent等,这些Agent拥有大量的工具,但不同的任务只需要用到其中的一部分。
权衡点:需要额外判断什么时候该开放新工具。如果开放工具的时机太晚,Agent可能已经走了弯路,浪费了一些对话轮次;如果开放得太早,又会回到"工具太多、误用风险高"的问题。
实战建议:可以根据任务的类型和进度,自动判断是否需要开放新工具。比如,当Agent检测到用户的需求是"执行构建命令"时,自动开放shell命令工具,并限制只能执行构建相关的命令;同时,让用户可以手动触发工具开放,当Agent需要使用某个未开放的工具时,用户可以手动批准开放,确保工具开放的及时性和安全性。另外,可以记录工具的使用频率,对于长期不被使用的工具,自动关闭,减少资源占用。
10. 命令风险分类模式(Command Risk Classification Pattern):控制风险,不盲目放行
当Agent拥有shell命令、系统级操作等工具时,会面临一个核心问题:风险控制。如果让Agent随便执行任何命令,风险会非常高,比如Agent误执行rm -rf /命令,会导致系统崩溃、数据丢失;但如果每一步命令都让用户确认,用户很快就会点到麻木,失去耐心,而且会降低Agent的执行效率,失去自动化的意义。
比如,Agent执行npm run build命令,这是一个低风险的命令,不需要用户确认;但如果Agent执行rm -rf src命令,这是一个高风险的命令,必须让用户确认,否则会导致代码丢失。如果所有命令都让用户确认,用户需要确认每一个命令,比如确认npm run build、确认pytest、确认git add,很快就会不耐烦;如果所有命令都不确认,又会面临高风险。
命令风险分类模式,就是为了解决"风险控制与执行效率"的平衡问题。它的核心思路是:在Agent执行命令之前,对命令进行一层"风险判断",根据命令的风险等级,采取不同的处理方式:低风险的命令自动放行,中风险的命令提示用户确认,高风险的命令直接拦截或需要高级审批,既控制风险,又不影响执行效率。
具体来说,命令的风险等级可以分为三类:
-
低风险命令:不会对系统、数据造成任何破坏,执行结果可逆转的命令,比如读取文件(cat、read_file)、查看日志(tail、log_view)、执行构建命令(npm run build、mvn package)、执行测试命令(pytest、jest)等,这类命令自动放行,无需用户确认;
-
中风险命令:可能会对系统、数据造成轻微影响,执行结果可逆转的命令,比如修改配置文件(write_file修改配置)、删除单个文件(rm 单个文件)、提交代码(git commit)等,这类命令提示用户确认,用户确认后再执行;
-
高风险命令:会对系统、数据造成严重破坏,执行结果不可逆转的命令,比如删除目录(rm -rf 目录)、格式化磁盘(mkfs)、修改系统配置(sudo vim /etc/profile)、远程部署(remote_deploy)等,这类命令直接拦截,或者需要用户高级审批(比如输入密码、二次确认)后再执行。
实现上,通常需要对命令进行解析,比如分析命令的操作类型(读取、写入、删除、执行)、带有的参数(如rm命令是否带有-rf参数)、影响范围(如修改单个文件还是整个目录),再结合预设的规则,判断命令的风险等级,然后采取对应的处理方式。
举个例子:Agent执行以下三个命令,会被分为不同的风险等级,采取不同的处理方式:
-
命令:cat src/App.jsx(读取文件),风险等级:低风险,处理方式:自动放行,直接执行;
-
命令:rm src/temp.txt(删除单个文件),风险等级:中风险,处理方式:提示用户"是否确认删除src/temp.txt文件?",用户确认后执行;
-
命令:rm -rf src/components(删除目录),风险等级:高风险,处理方式:直接拦截,提示用户"该命令为高风险命令,禁止执行,请确认命令的正确性",或者需要用户输入密码二次确认后再执行。
这种风险分类的方式,既能避免高风险命令导致的损失,又能减少用户的确认操作,平衡了风险控制和执行效率。
适用场景:Agent能执行shell命令,或者会操作外部系统(如数据库、远程服务器)的场景,比如编码助手、自动化部署工具、系统管理Agent等。
权衡点:风险判断的规则不可能覆盖所有情况,需要不断调整和优化。比如,有些命令在不同的场景下,风险等级不同,比如rm -rf test目录,在测试环境中是低风险,但在生产环境中是高风险;另外,有时候会出现误判,要么放过了高风险命令,要么拦住了本来安全的命令,影响用户体验。
实战建议:首先,建立场景化的风险规则库,区分测试环境、开发环境和生产环境的风险标准,比如在测试环境中,rm -rf test目录可判定为低风险,自动放行;但在生产环境中,即使是删除单个非核心文件,也需提升为中风险,提示用户确认。其次,引入"白名单+黑名单"双重机制,白名单列出所有可自动放行的低风险命令(如npm run build、pytest、cat等),黑名单列出绝对禁止执行的高风险命令(如rm -rf /、mkfs等),不在黑白名单内的命令,根据参数和影响范围动态判定风险等级。
另外,可添加"风险学习"功能,Agent记录每次命令执行的结果和用户的确认行为,比如某条命令被用户多次确认执行且未出现问题,可适当降低其风险等级;若某条命令出现误操作导致问题,可提升其风险等级,并补充到风险规则库中,逐步优化风险判断的准确性。同时,为高风险命令添加"预览功能",比如Agent执行rm -rf src/components命令前,先预览该目录下的所有文件,提示用户删除后会造成的影响,让用户更清晰地判断是否执行,进一步降低误操作风险。
最后,完善操作日志记录,所有命令的执行记录(包括命令内容、风险等级、处理方式、执行结果、用户确认记录等)都需详细留存,便于后续出现问题时追溯根源,同时也能为风险规则库的优化提供数据支撑。对于团队使用的Agent,还可以设置权限分级,普通开发者只能审批中风险命令,高风险命令需由管理员审批,进一步强化风险控制。
11. 工具契约模式(Tool Contract Pattern):让Agent"懂工具、会用工具"
很多Agent在使用工具时,会出现"用不好"的问题:比如调用工具时参数传递错误,导致工具执行失败;不清楚工具的返回格式,无法解析工具的输出结果;不知道工具的使用限制,频繁调用工具导致工具崩溃,这些问题都会影响Agent的执行效率,甚至导致任务失败。
比如,Agent调用文件写入工具时,误将"文件路径"参数传递成"文件名",导致无法找到文件,写入失败;调用数据库查询工具时,不清楚工具的返回格式是JSON还是字符串,无法解析查询结果,无法继续执行后续任务;频繁调用远程接口工具,超过接口的调用频率限制,导致接口被封禁,任务被迫中断。
工具契约模式,就是为了解决"Agent不会用工具"的问题。它的核心思路是:为每个工具定义一份清晰的"契约",明确工具的输入参数、输出格式、使用限制、异常处理方式等信息,Agent在调用工具前,先读取这份契约,明确工具的使用规则,确保调用工具时参数正确、格式无误,同时能正确解析工具的输出结果,应对工具调用过程中的异常情况。
具体来说,工具契约通常包含以下几个核心部分:
-
工具描述:明确工具的功能,比如"文件写入工具,用于向指定路径的文件中写入内容";
-
输入参数:明确工具需要的输入参数,包括参数名称、类型、必填项、格式要求等,比如"file_path(字符串,必填,格式为绝对路径或相对路径)、content(字符串,必填,需要写入的内容)、overwrite(布尔值,可选,默认false,是否覆盖原有文件)";
-
输出格式:明确工具的输出结果格式,包括成功时的输出内容、失败时的错误提示等。
-
使用限制:明确工具的使用限制,比如"文件写入工具单次写入内容不超过10MB,每分钟最多调用10次";
-
异常处理:明确工具调用过程中可能出现的异常情况,以及对应的处理方式,比如"若file_path参数格式错误,返回错误码1001,提示用户检查文件路径;若文件权限不足,返回错误码1002,提示用户提升文件权限"。
Agent在调用工具前,会先加载该工具的契约,根据契约要求准备输入参数,确保参数的类型、格式符合要求;调用工具后,会根据契约中定义的输出格式,解析工具的返回结果,判断工具是否执行成功;若出现异常,会根据契约中的异常处理方式,采取对应的解决措施,比如提示用户检查参数、重试调用等。
举个例子:文件写入工具的契约定义如下:
工具描述:用于向指定路径的文件中写入文本内容,支持覆盖原有文件或追加内容。
输入参数:
-
file_path:字符串,必填,文件的绝对路径或相对路径,格式示例:src/App.jsx、/home/user/test.txt;
-
content:字符串,必填,需要写入的文本内容,单次写入不超过10MB;
-
mode:字符串,可选,默认值为"write","write"表示覆盖原有文件,"append"表示追加到文件末尾;
使用限制:每分钟最多调用10次,单次写入内容不超过10MB;
异常处理:
-
错误码1001:文件路径格式错误,提示用户检查路径;
-
错误码1002:文件权限不足,提示用户执行chmod命令提升权限;
-
错误码1003:写入内容超过10MB,提示用户拆分内容后分次写入。
Agent在调用这个工具时,会先读取这份契约,确保输入的file_path格式正确、content不超过10MB、mode参数符合要求;调用后,根据输出结果的status判断是否成功,若出现错误码1001,会提示用户检查文件路径;若出现错误码1002,会提示用户提升文件权限,确保工具调用的成功率。
适用场景:Agent需要调用多个不同类型的工具,或者工具的参数、输出格式复杂的场景,比如编码助手(需要调用文件操作、shell命令、代码检查等工具)、自动化办公工具(需要调用文档处理、邮件发送、表格操作等工具)等。
权衡点:需要额外维护工具契约。每个工具都需要定义一份契约,当工具的功能、参数、输出格式发生变化时,契约也需要同步更新,否则会导致Agent调用工具失败;同时,契约的定义需要足够详细,否则无法起到指导Agent使用工具的作用,反而会增加Agent的理解成本。
实战建议:可以将所有工具的契约集中管理,建立一个"工具契约库",Agent在启动时自动加载所有工具的契约,便于统一维护和更新;契约的定义尽量简洁明了,避免使用晦涩的术语,同时为每个参数、输出字段添加示例,帮助Agent更好地理解;当工具发生更新时,同步更新契约,并在契约中添加版本号和更新记录,确保Agent使用的是最新的契约;另外,可以为契约添加"校验功能",Agent在调用工具前,先根据契约校验输入参数,提前发现参数错误,减少工具调用失败的概率。
四、自动化:让Agent"少出错、省力气"
无论是记忆与上下文、工作流与编排,还是工具与权限,最终的目标都是让Agent能更自主、更高效地完成任务,减少人工干预。而自动化相关的2个设计模式,正是从"减少重复操作"和"避免低级错误"两个角度,进一步提升Agent的自主性和稳定性,让Agent在执行任务时,能自动处理重复工作,自动规避低级错误,真正实现"省力气、少出错"。
这两个模式看似简单,却能大幅提升Agent的生产效率,减少开发者的人工成本,也是Claude Code能稳定运行的重要保障。很多开发者在开发Agent时,往往忽略了自动化的重要性,导致Agent需要人工干预才能完成任务,无法真正实现自主执行。
12. 自动化重试模式(Automated Retry Pattern):让Agent"自己解决小问题"
Agent在执行任务的过程中,难免会遇到一些临时的小问题:比如网络波动导致工具调用失败、文件暂时被占用无法写入、命令执行超时等。如果这些小问题都需要用户手动干预,比如提示用户"网络异常,请重试""文件被占用,请关闭文件后重试",会大幅降低Agent的执行效率,也会增加用户的操作成本,违背Agent"自动化"的核心目标。
比如,Agent调用远程接口工具时,由于网络波动,接口调用失败;或者执行npm run build命令时,由于依赖包下载超时,命令执行失败。此时,如果Agent直接提示用户"执行失败,请重试",用户需要手动触发重试,不仅麻烦,而且如果这类小问题频繁出现,用户会失去耐心。
自动化重试模式,就是为了解决"临时小问题需要人工干预"的问题。它的核心思路是:为Agent的每一步操作设置"重试机制",当操作失败时,Agent自动判断失败原因,如果是临时的、可恢复的错误(如网络波动、文件暂时被占用、超时等),就自动重试,无需用户干预;如果是不可恢复的错误(如文件不存在、权限不足、命令错误等),再提示用户干预,既减少用户的操作成本,又提升任务的执行成功率。
具体来说,自动化重试模式的实现的核心是"失败原因判断+重试策略":
-
失败原因判断:Agent在操作失败后,会解析失败信息(如错误码、错误提示),判断失败原因是否可恢复。可恢复的错误通常包括:网络波动导致的工具调用失败、文件暂时被占用无法读写、命令执行超时、依赖包下载超时等;不可恢复的错误通常包括:文件不存在、路径错误、权限不足、命令错误、工具未开放等。
-
重试策略:针对可恢复的错误,设置合理的重试策略,包括重试次数、重试间隔、重试条件等。比如,网络波动导致的接口调用失败,设置重试3次,每次重试间隔2秒;文件被占用导致的写入失败,设置重试5次,每次重试间隔3秒,若5次都失败,再提示用户干预。
同时,为了避免"无限重试",需要设置重试上限,当重试次数达到上限后,即使错误仍然可恢复,也停止重试,提示用户干预;另外,对于不同类型的操作,设置不同的重试策略,比如工具调用的重试次数可以多一些,命令执行的重试次数可以少一些,根据操作的特性调整。
举个实际的例子:Agent调用远程接口工具获取数据,由于网络波动,接口调用失败,错误提示为"网络超时"。Agent解析失败原因后,判断这是可恢复的错误,按照预设的重试策略,自动重试3次,每次间隔2秒。第一次重试失败,第二次重试失败,第三次重试成功,Agent继续执行后续任务,无需用户干预。如果第三次重试仍然失败,Agent就会提示用户"网络持续异常,接口调用失败,请检查网络连接后重试"。
再比如,Agent执行文件写入操作时,提示"文件被占用,无法写入",Agent判断这是可恢复的错误,自动重试5次,每次间隔3秒。如果在第3次重试时,文件被释放,写入成功,Agent继续执行后续任务;如果5次重试都失败,提示用户"文件长时间被占用,无法写入,请关闭占用文件后重试"。
这种自动化重试的方式,能让Agent自动解决很多临时的小问题,减少用户的人工干预,提升任务的执行成功率和效率。
适用场景:Agent执行的操作可能出现临时可恢复错误的场景,比如需要调用远程接口、读写文件、执行命令、下载依赖等操作的Agent,比如编码助手、自动化部署工具、数据采集Agent等。
权衡点:重试策略设置不当,可能会浪费系统资源,甚至加重问题。比如,对于不可恢复的错误,若设置了重试,会导致Agent反复执行无效操作,浪费CPU和内存资源;若重试间隔太短,可能会导致接口被频繁调用,触发接口的频率限制;若重试次数太多,可能会导致任务执行时间过长。
实战建议:首先,为不同类型的操作设置差异化的重试策略,比如远程接口调用的重试次数为3-5次,间隔2-3秒;文件读写操作的重试次数为5-10次,间隔3-5秒;命令执行的重试次数为2-3次,间隔5秒。其次,完善失败原因的判断逻辑,通过错误码、错误提示等多维度判断错误是否可恢复,避免对不可恢复的错误进行重试。
另外,添加"重试日志"功能,记录每次重试的时间、失败原因、重试结果,便于后续分析问题,优化重试策略;同时,允许用户手动调整重试策略,比如用户可以根据实际情况,修改重试次数和重试间隔,满足不同场景的需求。对于一些关键操作,比如远程部署、数据修改等,重试前可以提示用户,避免因为重试导致重复操作,造成不必要的损失。
13. 操作护栏模式(Operation Guardrails Pattern):给Agent"划红线、避坑"
即使Agent有了完善的工作流、权限控制和自动化重试机制,仍然可能出现一些低级错误,比如误删除核心文件、修改错误的配置、执行错误的命令等。这些低级错误虽然看似简单,但可能会导致严重的后果,比如系统崩溃、数据丢失、项目无法运行等。
比如,Agent在执行删除命令时,误将核心目录(如src、lib)当成临时目录删除;在修改配置文件时,误将关键参数(如数据库地址、端口号)修改错误;在执行shell命令时,误将"npm run build"写成"npm run build:prod",导致构建出生产环境的代码,影响开发进度。
操作护栏模式,就是为了避免Agent出现这类低级错误,给Agent的操作"划红线",设置一系列的"护栏",当Agent的操作触碰红线时,自动拦截,提示用户确认,避免错误执行。它的核心思路是:预设一系列的操作限制规则,Agent在执行操作前,先检查操作是否符合规则,若符合规则,正常执行;若触碰规则红线,自动拦截,提示用户确认,确保操作的安全性。
具体来说,操作护栏可以分为三类,覆盖Agent执行任务的全流程:
-
路径护栏:设置禁止操作的路径和文件,比如核心目录(src、lib、config)、关键文件(package.json、database.json),Agent在执行删除、修改操作时,若涉及这些路径和文件,自动拦截,提示用户确认;同时,设置允许操作的路径,比如临时目录(temp、log),Agent在这些路径下执行操作时,无需拦截,提升效率。
-
命令护栏:设置禁止执行的命令和允许执行的命令,比如禁止执行rm -rf /、sudo等高危命令,允许执行npm run build、pytest等低风险命令;同时,对命令的参数进行限制,比如rm命令不允许带有-rf参数,避免误删除目录。
-
内容护栏:设置禁止修改的内容和修改限制,比如配置文件中的数据库地址、端口号等关键参数,Agent在修改这些内容时,自动拦截,提示用户确认;同时,对修改的内容进行校验,比如修改配置文件时,校验参数格式是否正确,避免修改后配置文件失效。
举个例子:一个编码助手的操作护栏设置如下:
路径护栏:禁止操作的路径包括src、lib、config、package.json、database.json;允许操作的路径包括temp、log、src/components/Button.jsx(指定组件文件);
命令护栏:禁止执行的命令包括rm -rf、sudo、mkfs;允许执行的命令包括npm run build、npm test、pytest、cat、read_file、write_file;rm命令禁止带有-rf参数;
内容护栏:禁止修改package.json中的name、version、dependencies字段;修改database.json中的数据库地址、端口号时,需提示用户确认;修改配置文件时,校验参数格式,若格式错误,自动拦截。
当Agent试图删除src目录时,路径护栏会自动拦截,提示用户"该路径为核心目录,禁止删除,请确认操作的正确性";当Agent试图执行rm -rf temp命令时,命令护栏会自动拦截,提示用户"禁止使用rm -rf命令,请使用rm命令删除单个文件";当Agent试图修改package.json中的version字段时,内容护栏会自动拦截,提示用户"该字段禁止修改,请确认需求"。
通过这些护栏设置,能有效避免Agent出现低级错误,减少不必要的损失,同时也能让用户更放心地使用Agent,减少人工监督的成本。
适用场景:所有生产级Agent,尤其是需要执行删除、修改、命令执行等高危操作的Agent,比如编码助手、自动化部署工具、系统管理Agent等。
权衡点:护栏设置太严格,会影响Agent的执行效率,比如一些合理的操作也会被拦截,需要用户频繁确认;设置太宽松,又无法起到"避坑"的作用,无法避免低级错误。
实战建议:首先,根据Agent的使用场景和任务类型,合理设置护栏规则,区分"绝对禁止"和"需要确认"的操作,比如核心目录的删除属于绝对禁止,非核心目录的删除属于需要确认;关键参数的修改属于需要确认,普通参数的修改属于正常执行。其次,允许用户自定义护栏规则,比如用户可以根据自己的项目需求,添加禁止操作的路径、命令和内容,让护栏更贴合实际使用场景。
另外,添加"护栏例外"机制,对于一些特殊任务,用户可以临时关闭部分护栏,比如用户需要重构核心目录,可临时关闭路径护栏,执行删除和修改操作,任务完成后自动恢复护栏,兼顾安全性和灵活性;同时,记录护栏的拦截记录,包括被拦截的操作、拦截原因、用户处理方式等,便于后续分析Agent的操作行为,优化护栏规则。
总结:13个设计模式的核心价值与落地建议
Claude Code源码泄露带来的12个Agentic Harness设计模式,并非孤立存在,而是相互配合、层层递进,共同构成了生产级Agent的底层架构体系。记忆与上下文类模式解决了Agent"记得住、记得清、不浪费"的问题,为Agent的自主执行提供了基础;工作流与编排类模式解决了Agent"有条理、不混乱"的问题,让复杂任务能有序推进;工具与权限类模式解决了Agent"能做事、不闯祸"的问题,控制了操作风险;自动化类模式解决了Agent"少出错、省力气"的问题,提升了执行效率和自主性。
这12个模式的核心价值,不在于"技术多先进",而在于"落地性强"------它们没有依赖任何惊世骇俗的算法,而是从实际生产场景出发,解决了Agent开发中最常见、最棘手的痛点,无论是新手开发者还是资深工程师,都能将这些模式直接复用在自己的Agent项目中,大幅降低开发成本,提升Agent的稳定性和实用性。
对于正在做Agent应用的开发者,这里给出几点整体的落地建议:
第一,循序渐进,不要盲目追求"大而全"。可以先从记忆与上下文类模式入手,实现持久化指令文件、分层记忆等基础功能,让Agent具备基本的"记忆能力";再逐步引入工作流与编排类模式,优化任务执行流程;最后添加工具与权限、自动化类模式,完善Agent的稳定性和自主性。
第二,结合自身场景,灵活调整模式细节。这12个模式是通用的,但并非适用于所有场景,比如小型项目不需要复杂的作用域上下文组装模式,简单的Agent不需要上下文隔离子智能体模式。开发者需要根据自己的项目规模、任务类型、使用场景,调整模式的实现细节,让模式更贴合实际需求。
第三,重视测试与优化,持续迭代。Agent的设计模式不是一成不变的,需要在实际使用中不断测试,收集用户反馈,优化模式的细节,比如调整分层记忆的层级划分、优化命令风险分类的规则、调整自动化重试的策略等,让Agent越来越贴合用户需求,越来越稳定高效。
第四,关注安全性与可维护性。生产级Agent的核心需求是"稳定、安全、可维护",在落地这些设计模式时,要重视权限控制、风险防范、日志记录等功能,确保Agent的操作安全;同时,要注重代码的可维护性,比如将指令文件、工具契约、护栏规则集中管理,便于后续的更新和维护。
大模型技术在快速迭代,Agent的工具和框架也在不断更新,但这些底层的设计模式,是经过生产级场景验证的核心智慧,不会轻易过时。Claude Code的泄露,给了我们一个难得的机会,去学习生产级Agent的设计思路,而这些思路,终将帮助我们开发出更稳定、更高效、更实用的Agent应用,真正让AI成为开发者的得力助手。