ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

AI软件工厂设计模式:主从模式将SubAgent工具化,Agent协作拐点已至

AI软件工厂设计模式:主从模式将SubAgent工具化,Agent协作拐点已至 AI软件工厂设计模式直播第71期当“主从模式”把SubAgent变成ToolAgent系统的工程化拐点到了如果你关注最近一年的AI应用开发大概率会发现一个趋势单点的大模型调用已经不再是瓶颈瓶颈变成了“多个模型、多个工具、多个人如何在一个系统里有序协作”。从各团队的落地情况来看靠一个巨大的Prompt把需求写清楚的做法正在失效取而代之的是把任务拆给不同Agent、让它们按固定工序协作的“软件工厂”模式。“AI软件工厂设计模式”这个系列直播能连续办到第71期本身就是一个信号。一个技术话题能持续几十期仍有讨论热度说明它背后不是一条技巧就能解决的问题而是一整套需要沉淀的方法论。所谓AI软件工厂并不是让大模型自动写代码那么简单而是把软件开发中的需求分析、架构设计、编码、评审、测试、发布拆成标准化工序由Agent和人工协同完成最终像工业流水线一样稳定产出软件。这篇文章的核心判断是AI软件工厂能不能跑得稳关键不在于多好的模型而在于你是否定义清楚了Agent之间的协作模式。而设计模式恰恰是这个阶段最值得被复用的工程资产。1. AI软件工厂到底在解决什么问题很多团队在上了AI编程工具之后发现效率提升并没有想象中明显。工具确实能生成代码但生成的代码能不能用、合不合规范、会不会把错误的设计带进主干这些问题依然需要人处理。于是大家开始意识到AI真正要改变的并不是“写代码”这一个动作而是整个软件的产出流程。AI软件工厂的提法就是针对这个流程而来的。它借鉴了传统制造业工厂的概念一条流水线有很多工位每个工位做固定的事有标准的输入输出有质量检测点任何工序出问题都能快速定位。AI软件工厂把软件开发也拆成这样一条流水线只不过工位上的工人变成了不同职责的Agent它们对应需求分析、架构设计、编码实现、代码评审、单元测试、文档生成等环节。这和“让AI帮我写个函数”完全是两个层次。对比项单点AI辅助AI软件工厂关注范围单次生成、单段代码全流程、多个工序质量保障依赖人工检查标准化工序 自动检查可回退性生成失败重新生成每个工序有产物、可追溯多Agent协作基本没有必须依靠设计模式工程复用低高模式可沉淀为什么不能把所有需求丢给一个Agent做因为大模型的输出天然带有不确定性。同一个需求换一种表达方式结果可能完全不同同一个Agent连续调用两次输出的代码风格可能不一致。在单点辅助场景下这没什么问题但放到流水线里前一步的输出是后一步的输入不确定性的累积会导致整个流程越来越难控制。所以AI软件工厂真正解决的核心问题是把不可控的大模型输出通过工程手段约束成相对可控的交付产物。而设计模式就是这个约束体系里最直接可复用的部分。2. 从经典设计模式到AI Agent设计模式提到设计模式大部分后端同学第一反应是GoF那23种经典模式单例、工厂、观察者、策略、模板方法等。这些模式解决的是面向对象设计里反复出现的类与对象协作问题。它们沉淀了三十多年依然是Java、C、Python等语言项目里最常见的代码组织方式。但Agent系统和传统面向对象系统有个根本区别传统系统里的对象是确定的方法调用是确定的而Agent系统里的核心组件是LLM它的行为是概率性的。同一个Agent同样的输入两次调用不一定完全一样。这意味着经典设计模式中“对象怎么创建、类之间怎么继承、方法怎么调用”这一套抽象并不能直接套用到Agent的编排上。从当前社区和企业的实践看AI Agent设计模式正在形成自己的一套分类它们关注的不是代码级别的复用而是任务编排方式的复用、上下文传递方式的复用、以及Agent之间协作关系的复用。维度经典面向对象设计模式AI Agent设计模式关注对象类、接口、继承关系任务、上下文、工具调用核心假设对象行为可控、可预测LLM行为概率性、不可完全预测典型问题解耦、扩展、复用任务拆分、状态同步、错误恢复常用手段继承、组合、接口定义Prompt模板、状态机、工具注册表代表模式工厂、观察者、策略主从模式、路由模式、记忆共享模式这里也引出了一个很多AI应用开发者容易忽略的问题对抗不确定性的不是更好的Prompt而是明确的结构。Prompt适合约束单次输出的风格和格式但当流程跨多个Agent时真正起约束作用的是系统的结构设计谁在什么条件调用谁、结果存到哪里、失败后怎么恢复。这些结构一旦频繁复用就会沉淀成模式。智能体设计模式这个词也越来越多出现在各种技术文档里。目前行业对它还没有一个绝对统一的分类但从各团队公开的实践中能看出主从模式、路由模式、状态机模式、共享记忆模式是出现频率最高的几类。下面重点拆解和我们标题最相关的主从模式。3. 主从模式SubAgent本质上就是另一种Tool第71期相关热词里有一句话很值得琢磨“本质上将SubAgent视作另类的Tool进行调用”。这句话看着简单其实直接点破了主从模式的核心抽象。所谓主从模式就是一个主Agent负责任务的整体拆解、调度和结果汇总多个子Agent各自负责一个具体的子任务。按传统直觉可能会把子Agent设计成“独立的对话角色”每个子Agent都有自己的Prompt、自己的记忆、自己的任务描述主Agent负责把任务发出去再收回来。但如果实现得过重子Agent之间容易互相干扰上下文也会爆炸。而是“SubAgent即Tool”的思路是把子Agent完全按照工具的标准来封装。主Agent视角下子Agent和一个普通的Function Tool没有本质区别它有一个名字、一段功能描述、一组输入参数调用后返回一个结构化的结果。这样做有三个明显好处。第一统一了调用路径。主Agent不需要区分“我是在调用一个工具还是在调用另一个Agent”两者都走同一个工具注册和调用机制代码上可以共用一套逻辑。这也让Agent框架的实现简单很多。第二隔离了上下文。工具调用天然不共享记忆每个子Agent只接收主Agent传入的参数只返回结构化的输出。这样你不需要设计复杂的记忆同步机制上下文自然就被切开了。第三方便了错误处理。子Agent失败时可以像工具超时一样被捕获转换成错误信号交给主Agent重新规划。如果子Agent被设计成平等的对话对象失败处理就会模糊甚至可能出现两个Agent互相推诿的情况。下面用一段Python伪代码演示“SubAgent即Tool”的主从架构核心逻辑。这里不依赖任何特定框架重点是抽象方式。# -*- coding: utf-8 -*- 主从架构示例主Agent将子Agent注册为Tool进行调用 说明此为架构演示代码函数内部请根据实际Agent框架实现 import json from typing import Any, Callable, Dict class ToolRegistry: 工具注册表无论是普通工具还是子Agent统一注册与管理 def __init__(self): self._tools: Dict[str, Dict[str, Any]] {} def register(self, name: str, description: str, handler: Callable): self._tools[name] { description: description, handler: handler, } def describe(self) - str: 生成供主Agent理解的工具清单 return json.dumps( {name: info[description] for name, info in self._tools.items()}, ensure_asciiFalse, ) def call(self, name: str, **kwargs): if name not in self._tools: raise ValueError(funknown tool: {name}) try: return {ok: True, result: self._tools[name][handler](**kwargs)} except Exception as e: # 子Agent异常统一包装为工具错误 return {ok: False, error: str(e)} class CodeGeneratorAgent: 子Agent A负责代码生成 def run(self, spec: str) - str: # 实际开发中这里会调用一个配置好Prompt的LLM return fgenerated_code_for: {spec} class CodeReviewAgent: 子Agent B负责代码审查 def run(self, code: str) - str: # 实际开发中这里会调用一个代码审查专用Agent return freview_results: {len(code)} chars reviewed def setup_registry() - ToolRegistry: registry ToolRegistry() registry.register( code_generator, 根据需求规格生成代码输入spec字段输出代码字符串, CodeGeneratorAgent().run, ) registry.register( code_reviewer, 对已有代码进行审查输入code字段输出审查意见, CodeReviewAgent().run, ) return registry class MainAgent: 主Agent负责任务分解与调度 def __init__(self, registry: ToolRegistry): self.registry registry def execute(self, task: str): # 实际开发中主Agent通过LLM决定调用哪个tool # 这里用规则分支模拟决策过程 if 生成 in task: return self.registry.call(code_generator, spectask) if 审查 in task: code def add(a, b): return a b return self.registry.call(code_reviewer, codecode) raise ValueError(无法识别的任务类型) if __name__ __main__: registry setup_registry() main_agent MainAgent(registry) print(main_agent.execute(生成一个用户注册接口)) print(main_agent.execute(审查这段代码))运行这段代码会输出两个结构化的调用结果。虽然这只是演示但能看出架构上的关键差异主Agent手里只有一份工具清单它不直接管理子Agent的状态所有子Agent的执行都是入参、调用、返参的闭环。从工程实践看这种设计的可扩展性比“为每个子Agent维护一个会话”高很多。新增一个Agent只需要在注册表里多注册一条主Agent通过工具描述就能知道这个Agent能干什么。如果未来要换掉某个子Agent的实现只要保持接口不变主链路完全不受影响。4. 状态机在Agent工作流中的关键作用热词里“状态机设计模式”出现的频率也很高。一个成熟的Agent系统里状态机往往藏在最底层但作用可能比Prompt模板还大。为什么状态机对Agent这么重要因为多Agent流程是一个长期运行的异步过程它不像单次调用那样发出请求就能立刻拿到结果。一个Agent可能在等待另一个Agent返回可能在等待人工确认可能在某个步骤反复重试。如果这些状态没有明确管理系统一旦抖动整个流程就会卡死或者乱序。状态机模型天然适合表达这种流程控制每个步骤是一个状态状态之间的跳转由事件触发。事件可以是“子Agent返回成功”“子Agent返回失败”“超时”“人工确认通过”等。这样整个Agent工作流就像一段确定性的流程编排而不是一连串盲目的LLM调用。下面是一个代码审查Agent的状态机配置示例。这里用JSON描述状态和跳转方便在配置中心统一管理{ workflow_id: code_review_agent, initial_state: idle, states: { idle: { events: { start: analyzing } }, analyzing: { timeout_seconds: 30, on_timeout: idle, events: { analysis_done: reviewing, analysis_failed: retry } }, reviewing: { events: { review_done: finished, review_failed: retry } }, retry: { max_retries: 3, events: { retry_done: reviewing, retry_exhausted: failed } }, finished: { terminal: true }, failed: { terminal: true } } }这个配置表达了一个非常常见的需求审查Agent启动后进入分析状态分析成功进入评审状态评审完成正常结束任何一步失败进入重试状态最多重试3次如果一直失败则整体标记为失败。超时也会把流程拉回初始状态避免流程卡死。从这些实践里能总结出一个重要原则Agent的状态迁移逻辑要尽量配置化不要硬编码在业务代码里。因为状态数量和触发条件变化很快配置化之后调整一个重试策略、改一个超时时间不需要重新发布整个Agent服务。同时也要注意状态机不意味着把Agent的业务逻辑全部固定死。状态机只负责“什么时候该做什么”真正“怎么做”依然交给LLM。这样划分等于把流程的确定性交给代码把内容生成的灵活性交给模型各司其职。5. 从单一Agent到多Agent协作的架构模型如果把设计模式当成一套可选的架构方案那么在一个实际项目里到底该选哪种这里非常有必要先梳理一下当前多Agent协作的主流架构模型。从各团队公开的实践来看大致有五类。直连模式用户直接与单个Agent对话Agent内部串行调用多个工具。实现最简单但能力上限低适合需求明确的单任务场景。主从模式一个主Agent负责任务分解和调度多个子Agent各自完成任务。前面已经详细说过这是当前最实用的模式。路由模式请求先经过一个路由Agent由它判断请求应该转发给哪个专业Agent。更擅长做意图分发比如客户支持系统。共享记忆模式多个Agent共享一段上下文或一个记忆库每个Agent都能读取和写入。适合需要协同推理的场景但需要处理并发和一致性问题。分层模式把Agent分成多个层级上层Agent负责战略规划下层Agent负责具体执行层级之间通过明确的协议通信。适合复杂项目但实现成本高。用表格对比会更直观架构模型优点缺点适用场景直连模式实现快、调试容易无法并行、复杂度受限简单任务、原型验证主从模式职责清晰、扩展性强主Agent易成瓶颈软件工厂流水线、需求拆解路由模式意图分发清晰路由判断本身有误差客服机器人、多业务入口共享记忆模式信息传递自然上下文一致性难保证团队推理、复杂分析分层模式战略与执行分离工程复杂度高大型系统、长期任务从软件工厂的视角看主从模式是性价比最高的起步选择。原因有三一是它不要求所有Agent在同一进程内甚至可以跨服务部署二是它的调用模型和现有Function Calling体系天然兼容三是它最容易做故障隔离一个子Agent挂了不影响主链路降级。另外提醒一句不同的模式并不是互斥的。实际项目中常见做法是先有主从模式然后在某个子Agent内部再用路由模式或状态机模式组合。设计模式解决的是一个层级上的问题一个真实系统往往是多层级组合的结果。6. 一个最小的AI软件工厂流水线示例讲了这么多概念还是需要用一个最简示例把整个流程串起来。下面用Python写一个极简的AI软件工厂流水线骨架。这个示例不接入真实模型只展示流水线的结构和可扩展点。# workflow.py # 最简AI软件工厂流水线需求解析 - 方案设计 - 编码 - 审查 - 测试 - 人工确认 import json import time STEPS { requirement: 需求解析Agent, design: 架构设计Agent, coding: 编码Agent, review: 代码审查Agent, test: 测试Agent, confirm: 人工确认, } class Artifact: 流水线产物每个工序产出一个Artifact def __init__(self, name, content): self.name name self.content content self.timestamp time.time() class Pipeline: def __init__(self, steps): self.steps steps self.artifacts {} def run(self, requirement: str) - dict: print(f收到需求: {requirement}) current_input {requirement: requirement} for step in self.steps: print(f[{time.strftime(%H:%M:%S)}] 当前工序: {STEPS[step]}) # 每个工序都会读取上一工序的产物产出本工序的Artifact artifact self._execute_step(step, current_input) self.artifacts[step] artifact current_input[step] artifact.content # 输出所有工序产物概要 return {step: artifact.content for step, artifact in self.artifacts.items()} def _execute_step(self, step: str, input_data: dict) - Artifact: # 实际开发中这里会根据step分发到不同Agent # - requirement - 调用需求分析Agent # - design - 调用架构设计Agent # - coding - 调用编码Agent # - review - 调用代码审查Agent # - test - 调用测试Agent可自动或人工 # 本示例用规则模拟各工序结果 content f{step}_artifact:{len(json.dumps(input_data, ensure_asciiFalse))} return Artifact(step, content) if __name__ __main__: pipeline Pipeline( [requirement, design, coding, review, test, confirm] ) result pipeline.run(开发一个支持多租户的待办事项API) print(\n流水线执行结果) for step, content in result.items(): print(f {step}: {content})运行这段代码后输出会显示每个工序按顺序执行并且每道工序都会消费前一道工序的产物。这看起来简单但它是软件工厂最核心的骨架每个工序之间有明确的产物契约。实际落地时你需要把_execute_step方法替换成真实的Agent调用。每个Agent负责一个工序输入和输出都遵循预先定义好的数据格式。比如需求分析Agent输入原始需求文本输出用户故事和验收标准架构设计Agent输入用户故事输出技术方案编码Agent输入技术方案输出代码和自测说明。这样流水线里的每个环节都是可替换、可升级的。这里有一个容易踩坑的地方不要试图让一个Agent同时完成多个工序。某道工序的Agent能力不足可以换更大的模型或更精细的Prompt但如果你把一个Agent既当设计又当编码用出了问题你很难判断是哪个环节导致的质量下降。7. AI软件工厂设计中的常见问题与排查多Agent系统调试难度比单体应用高因为问题可能出在模型理解、Prompt设计、状态流转、工具接口等多个层面。下面是AI软件工厂实施里最常见的几类问题。问题现象可能原因排查方式解决方案子Agent之间互相调用形成循环主Agent决策里缺少终止条件查看Agent调用日志和调用链在状态机里增加最大调用深度和终止状态主Agent上下文越来越长响应变慢子Agent返回值被完整塞入主上下文检查主Agent输入中tool返回的token量子Agent返回结构化摘要而非完整结果子Agent相互冲突输出结果不一致职责边界模糊多个子Agent覆盖同一块逻辑检查工具清单里各子Agent的描述明确每个Agent的唯一职责域流水线一步失败后续全部卡住缺少失败重试或降级策略查看状态机事件流为重试和超时配置明确的事件转移Agent生成的代码在集成时频繁出错编码Agent没有接收架构约束检查设计产物到编码产物的传递内容在编码Agent的Prompt中注入技术选型和接口规范人工确认环节被跳过流程设计里确认节点不是强制状态检查流程配置是否包含confirm节点人工确认必须作为明确状态节点存在默认不可跳过从这些表格里可以看到大部分问题都不是模型能力不够而是流程结构设计不到位。这再次验证了前面的判断AI软件工厂的质量上限首先取决于系统设计其次才是模型能力。如果在实践中遇到Agent表现不稳定第一步不是改Prompt而是先看调用链日志。确认一次请求经过哪些Agent、每个Agent的输入输出是什么、哪一步和预期不一致。多Agent系统必须把日志当成一等公民来设计否则后面排查问题会非常痛苦。8. 最佳实践与工程建议结合前面所有内容这里总结AI软件工厂落地时的工程建议。这些建议不是某个特定框架的做法而是从多个实践案例中提炼出来的通用原则。8.1 先画模式图再写代码在开始搭建Agent系统之前先画出整体协作图有哪些Agent、谁调用谁、调用失败怎么处理、哪些状态需要人工介入。这个步骤很多人嫌麻烦直接跳过但它在后期能省下大量调试时间。画图时的最小要求是每个Agent有明确的输入、输出、失败处理。8.2 用工具抽象统一Agent调用统一所有Agent的调用入口。无论子Agent内部逻辑多复杂对外都暴露成“名称 描述 入参 出参”四要素。这样主Agent不需要感知子Agent内部的模型和Prompt细节替换、升级、回滚都不会影响主链路。8.3 状态必须显式配置不能靠模型临场发挥流程的状态迁移不要交给LLM自己判断。LLM适合处理的是内容生成和方案决策不适合处理严格的流程控制。超时、重试次数、终止条件这类逻辑要用状态机明确写出来用代码保障确定性。8.4 上下文的传递要有“契约”每个工序产出的数据格式必须固定。哪怕最开始只有一种简单格式也要通过接口定义约束下来。否则流水线跑到后期前后产物格式各种不兼容改起来成本极高。一个比较好的做法是每个Agent的产物定义成JSON结构包含字段名、类型、约束说明。8.5 安全检查点不能省涉及写库、删数据、发布、支付等敏感操作流程中必须有明确的人工确认节点。自动执行到这一步时系统应该停下来等待人工授权。这不是效率问题而是责任边界问题。在真实项目里这条原则甚至比技术性能更优先。8.6 版本管理和可回滚每个Agent的Prompt和模型配置都应该纳入版本管理。流水线执行时最好记录每个工序使用的模型版本和Prompt版本。这样一旦某个Agent升级后质量下降可以精准定位到是哪一次改动导致的并能快速回滚到上一个稳定版本。8.7 从小处试点从简单工序开始一个完整的AI软件工厂不需要第一天就覆盖所有开发环节。建议先选最成熟、最封闭的工序切入比如单元测试生成或代码注释补全。把一条流水线跑顺形成自己的模式库再逐步扩展其他工序。脱离具体场景谈平台化的成本是很高的。9. 总结与后续学习方向回到“AI软件工厂设计模式直播第71期”这个主题。一期直播能办到71期说明这个领域仍然在快速演化而且每次实践都会带来新的认知。从目前的情况看AI软件工厂的核心已经不是“用哪家大模型”而是如何把LLM嵌入到一套有设计、有约束、有质量保障的工程体系里。从技术路径上看设计模式是这套体系的骨架。主从模式解决的是“谁指挥谁执行”的问题状态机模式解决的是“流程怎么控”的问题工具化抽象解决的是“Agent之间怎么协作”的问题。这些模式本身不复杂但把它们组合成一个真实可运转的软件工厂需要大量的工程实践和反复调试。如果你打算在项目中尝试落地建议按照这样的顺序先从一个最小流水线开始把需求解析、编码、审查这三道工序跑通然后用状态机把失败重试和人工确认加上再逐步补充测试、发布等更多工序。每加一个工序就沉淀一个模式。遇到问题优先回看流程设计和调用链日志而不是急着换模型。下一步值得继续深入的方向包括Agent输出质量的可观测性和量化评估、多Agent系统的成本控制在对应业务模型下的优化方式、以及Agent框架底层如何统一处理模型调用与工具调用。这些都是AI软件工厂走向生产环境绕不开的话题也大概率会在后续的直播和技术文章里被反复讨论。
返回列表