
最近很多开发者开始聊“AI软件工厂”。这个词听起来很酷但如果你真去搭一套很快就会发现一个尴尬的事实让 AI 写单点代码已经不难难的是让十几个 AI 角色像一条流水线一样稳定协作。单点能力强不等于系统能力强。这个问题的本质不是模型不够聪明而是软件开发这件事本身就是一个流水线问题。一个真实项目要经历需求拆解、模块设计、代码生成、代码审查、联调、回归、发布这些环节之间的衔接成本往往比单个环节的耗时更高。传统软件工程用流程、规范、接口和检查点来管理这种衔接到了 AI 时代这些“管理手段”换了个名字叫设计模式。这一期内容围绕“AI 软件工厂设计模式”这个主题展开核心聚焦在多 Agent 协作、主从模式、Subagent 的定位以及一个可以直接跑通的编排骨架。读完这篇文章你应该能回答三个问题AI 软件工厂到底在解决什么为什么设计模式在这个时代重新变得重要以及如果你要搭一个最小的多 Agent 编排系统代码长什么样。1. AI 软件工厂真正要解决的问题先从一个日常场景说起。你有一个不错的大模型 API也试过各种 AI 编程助手。单点功能确实惊艳写一个工具函数、补测试用例、解释报错信息都比以前快很多。但一旦放到真实项目里问题就来了。需求文档散落在各处AI 不知道听谁的代码生成出来了没人审查质量不可控功能改了一个模块其他模块跟着崩回归测试几乎靠人工发布流程还是手动跑一次要半小时。你会发现AI 确实在局部环节加快了速度但整个项目的交付速度没有明显提升。为什么因为软件开发的瓶颈从来不只是“写代码”这一个环节。需求拆解、接口定义、模块边界、评审机制、联调流程这些环节之间的信息传递和协作成本才是真正吃掉时间的地方。单点 AI 工具只优化了流水线上某一台机器的转速没有改变流水线本身。AI 软件工厂要解决的就是这个“流水线本身”的问题。具体来说有三个关键点第一可编排。多个 AI 角色Agent要能按流程协作而不是各干各的。第二可复用。需求拆解、代码审查、任务分配这些能力要能沉淀成标准模块供不同项目重复使用。第三可观测。每个 AI 角色的输出、状态、耗时、失败原因都要能被记录和追踪否则出了问题只能靠猜。从这个角度看AI 软件工厂不是一个新框架也不是某个具体工具而是一种把 AI 能力组织起来的工程方法。它的目标是让 AI 从一个“能写代码的助手”变成一个“稳定可管理的虚拟研发团队”。所以谁最应该关注这件事如果你正在把 AI 嵌入到团队真实的研发流程里比如你是技术负责人、后端架构师或者独立开发者想用 AI 承包一个完整项目那你需要理解这套组织方式。如果你只是偶尔用 AI 写个脚本、做个 PPT那还不需要深入到这里。2. 设计模式在 AI 时代为什么没有过时很多人一听到设计模式第一反应是这是上个世纪的 Java 面试题和 AI 有什么关系其实恰恰相反。设计模式的本质不是某种代码写法而是“识别变化点、封装变化点”的工程经验。这二十多年软件开发的技术栈换了好几轮但设计模式没有消失原因就是它解决的问题一直存在当系统存在变化时如何让改动局部化而不是牵一发动全身。AI 应用是当前变化速度最快的系统。模型在变昨天还在用 A 模型今天可能换了 B 模型的 APIPrompt 在变同一个功能Prompt 调整一点输出质量就完全不同工具在变AI 能调的 API、数据库、代码执行环境越来越多业务流程也在变需求永远在演进。这么多变化点集中在一个系统里如果没有设计模式去隔离变化最后的结果就是所有逻辑写在一个巨大的 Python 文件里换一个模型要改十个地方加一个工具要动全流程。这不是 AI 的问题是架构的问题。经典设计模式在 AI 软件工厂里有非常直接的映射经典设计模式AI 软件工厂中的对应场景工厂模式统一创建 Agent、LLM 客户端、工具实例策略模式根据任务类型选择不同模型或 Prompt 策略状态机模式管理任务的生命周期状态如待处理、运行中、审查中、完成模板方法模式固定整体流程骨架子步骤由具体 Agent 实现责任链模式把请求按顺序经过多个处理器如意图识别、安全过滤、工具调用门面模式对外提供统一接口隐藏底层多个 Agent 协作细节适配器模式适配不同模型厂商的 API 差异观察者模式任务状态变化时通知监控、通知下游流程要注意的是这里说的“映射”不是把教科书上的 UML 图搬过来。AI 软件工厂里的设计模式更多是一种架构思想知道哪里该画边界哪里该留接口哪里该做状态控制。如果你带着“在 AI 项目里用 Java 设计模式”的思路去套反而会陷入形式主义。在后续章节里我会重点讲三个在 AI 软件工厂里最常用的模式主从模式处理多 Agent 协作、策略模式做模型路由、状态机模式管任务生命周期。其中主从模式是当前 AI Agent 工程实践中最值得深入的一个。3. AI 软件工厂的分层架构与模式分布要理解 AI 软件工厂里的设计模式先得有张整体架构图。不依赖具体框架我用分层的方式来描述这套体系。第一层是交互层。它面向用户包括 Web 页面、IDE 插件、聊天窗口。这一层负责收集用户需求展示中间状态和最终结果。技术栈可以是任何前端框架核心要求是能跟编排层通信。第二层是编排层。这是 AI 软件工厂的大脑也是设计模式最密集的一层。它负责把用户请求拆解成子任务决定调用哪个 Agent收集结果判断是否需要重试或终止。主从模式的核心逻辑就落在这里。第三层是 Agent 层。Agent 是执行具体任务的虚拟角色比如代码生成 Agent、代码审查 Agent、测试编写 Agent、文档撰写 Agent。每个 Agent 有自己的角色设定、Prompt 模板、上下文管理策略和输出协议。第四层是工具层。Agent 不能只会聊天它要能执行代码、查数据库、调外部 API、读写文件。工具层把这些能力封装成统一接口让 Agent 可以安全地调用。第五层是知识层。包括项目文档、代码库索引、历史决策记录、规范模板和评测集。这一层主要解决 AI 的“记忆”和“规范跟随”问题可以理解为团队的共享知识库。第六层是可观测层。任务日志、Token 消耗、每一步的耗时、成功率、失败原因都必须在这一层记录。没有可观测性AI 软件工厂就是一辆没有仪表盘的汽车。分层的作用是让每一层的变化被限制在本层内部。换一个大模型Agent 层和编排层基本不用动加一个新工具只动工具层改一个业务流程只动编排层里的流程定义。如果你不分层所有东西全部耦合在一起那 AI 软件工厂就变成了 AI 代码泥潭。从模式分布的角度看编排层最值得投入。因为它是整个系统的控制中枢任务如何分解、结果如何合并、失败如何恢复都在这一层决定。中间件、数据库、缓存这些基础设施反而在 AI 软件工厂里退到了相对次要的位置因为它们已经足够成熟不需要你重新设计。4. 多 Agent 协作的核心主从模式与 Subagent 的定位多 Agent 协作是 AI 软件工厂里最容易失控的环节。如果让几个 Agent 自由对话、互相协调它们很可能聊着聊着就跑题或者在某个问题上反复纠缠不收敛。工程上不追求 Agent 之间“自由而热烈地讨论”追求的是稳定、可控、可预测的输出。这正是主从模式Orchestrator-Worker 模式的价值。一个中心节点 Orchestrator 负责理解任务、拆解子任务、调度执行、汇总结果多个叶子节点 Worker也可以叫 Subagent只负责执行分配给自己的具体任务并把结果返回给中心节点。所有信息流转都通过中心节点不鼓励 Worker 之间直接通信。这个模式听起来简单但它解决了多 Agent 系统里最核心的问题控制权归谁。中心节点掌握全局上下文子 Agent 只看到局部任务这样既避免上下文无限膨胀也让问题可以追溯到具体环节。关于 Subagent有一个值得反复咀嚼的工程观点在编排层面Subagent 本质上可以视为一种 Tool 调用。这个视角很有价值因为从调用方来看不管是调用一个“执行代码”的 Tool还是调用一个“代码审查”的 Subagent都遵循同样的模式传入结构化参数得到结构化结果失败则重试或终止。统一这一层抽象能给系统带来三个实际收益第一是协议统一。所有执行单元都有统一的输入、输出格式编排器不需要区分“这个调用是工具那个调用是 Agent”。第二是恢复统一。无论是工具超时还是 Subagent 异常走同一套重试和告警逻辑。第三是审计统一。每次调用都能记录在案便于排查和优化。当然Subagent 和普通工具之间确实有本质差异。Subagent 有上下文窗口有自身的模型偏好可能产生幻觉Token 成本也更高。说“Subagent 本质上是一种 Tool 调用”强调的是架构抽象而不是否定它的特殊性。在实现时你既要知道它像工具一样可编排也要防住它比普通工具更“不稳定”。主从模式适合什么场景任务可以被清晰拆解、子任务之间相对独立、结果可以被合并汇总的场景比如“写一个功能模块并审查”“对一批代码做静态检查和优化建议”“根据需求文档生成测试用例”。不适合什么场景子任务之间有强依赖、需要不断双向确认的复杂设计工作或者需要多个 Agent 持续辩论才能收敛的开放性问题。这类场景需要另一种架构但当前阶段先把主从模式用好就能覆盖大多数 AI 软件工厂需求。5. 一个可运行的最小编排骨架理论讲完下面给一个可以直接运行的最小示例。这段代码不依赖任何大厂框架用 Python 标准库就能跑通核心目的是让你看到主从模式里 Orchestrator、Worker、Tool 之间是怎么协作的。在这个示例里我不使用真实的 LLM API而是用一个模拟的 LlmClient这样你不需要配置任何 Key 就能理解结构。模拟返回的结果是固定的但整个编排流程是真实可运行的。接入真实验证时你只需要替换 LlmClient 内部实现。# 文件orchestrator_demo.py # 演示目的主从模式 Subagent 与 Tool 统一调度的最小骨架 from abc import ABC, abstractmethod class ExecutableUnit(ABC): 执行单元抽象Subagent 和 Tool 在编排器中都实现同一接口。 abstractmethod def invoke(self, payload: dict, ctx: dict) - dict: pass class LlmClient: 模拟 LLM 客户端真实项目中替换为具体的模型调用。 def plan(self, request: str) - dict: return { steps: [ {unit: code-generator, payload: {requirement: request}}, {unit: code-review, payload: {code: ref:code-generator.code}}, {unit: code-runner, payload: {code: ref:code-review.fixed_code}} ] } def generate(self, requirement: str) - str: return ( def bubble_sort(arr):\n n len(arr)\n for i in range(n):\n for j in range(0, n - i - 1):\n if arr[j] arr[j 1]:\n arr[j], arr[j 1] arr[j 1], arr[j]\n return arr\n ) def review(self, code: str) - dict: return { suggestions: 建议补充类型注解和边界测试, fixed_code: code \n# review: 已补充边界说明\n, score: 88, } def summarize(self, request: str, ctx: dict) - dict: review ctx.get(code-review, {}) return { status: ok, summary: f任务「{request}」完成代码审查得分{review.get(score)}, } class CodeGeneratorWorker(ExecutableUnit): 代码生成 Subagent根据需求生成代码。 def __init__(self, llm: LlmClient): self.llm llm def invoke(self, payload: dict, ctx: dict) - dict: requirement payload.get(requirement, ) code self.llm.generate(requirement) return {status: ok, code: code} class CodeReviewWorker(ExecutableUnit): 代码审查 Subagent审查并返回修复后的代码。 def __init__(self, llm: LlmClient): self.llm llm def invoke(self, payload: dict, ctx: dict) - dict: code payload.get(code, ) review self.llm.review(code) return { status: ok, review: review[suggestions], fixed_code: review[fixed_code], score: review[score], } class CodeExecutorTool(ExecutableUnit): 代码执行 Tool真实项目请放入沙箱环境执行。 def invoke(self, payload: dict, ctx: dict) - dict: code payload.get(code, ) print(f[CodeExecutorTool] 收到代码 {len(code)} 字符) return { status: ok, stdout: 模拟执行成功[5, 3, 8, 1] - [1, 3, 5, 8], } def resolve_payload(payload: dict, ctx: dict) - dict: 解析 payload 中的 ref: 引用从前置步骤的结果里取值。 resolved {} for key, value in payload.items(): if isinstance(value, str) and value.startswith(ref:): path value[4:].split(.) cur ctx for p in path: if not isinstance(cur, dict): cur None break cur cur.get(p) resolved[key] cur else: resolved[key] value return resolved class Orchestrator: 主从模式中的中心节点拆解任务、分派执行、汇总结果。 def __init__(self, llm: LlmClient): self.llm llm self.units {} def register(self, name: str, unit: ExecutableUnit) - None: self.units[name] unit print(f[Orchestrator] 注册执行单元{name}) def handle(self, request: str) - dict: ctx {request: request} plan self.llm.plan(request) print(f[Orchestrator] 任务计划{plan}) for step in plan.get(steps, []): unit_name step[unit] payload resolve_payload(step.get(payload, {}), ctx) print(f[Orchestrator] 调用 {unit_name}payload{payload}) result self.units[unit_name].invoke(payload, ctx) ctx[unit_name] result print(f[Orchestrator] {unit_name} 返回{result}) return self.llm.summarize(request, ctx) if __name__ __main__: llm LlmClient() orch Orchestrator(llm) orch.register(code-generator, CodeGeneratorWorker(llm)) orch.register(code-review, CodeReviewWorker(llm)) orch.register(code-runner, CodeExecutorTool()) final orch.handle(用Python实现冒泡排序) print([Orchestrator] 最终汇总, final)这个示例里最值得注意的设计是 ExecutableUnit 接口。CodeGeneratorWorker、CodeReviewWorker 是 SubagentCodeExecutorTool 是普通工具但它们都实现了同一个 invoke 方法这意味着在 Orchestrator 看来它们没有本质区别。这正好呼应前面那个观点Subagent 在编排层可以当作 Tool 来调度。第二个关键设计是 ctx 上下文。Orchestrator 每执行完一个步骤就把结果写入 ctx下一步的 payload 可以用ref:step-name.field-name的语法引用上一步的输出。这样步骤之间不直接通信所有数据都流经中心节点符合主从模式的控制原则。第三个关键设计是计划与执行分离。LlmClient 的 plan 方法返回任务计划Orchestrator 只负责按计划执行。真实系统中计划生成这一步可以非常复杂比如让主 Agent 根据任务类型动态决定要不要拆解、拆成几步、每一步用哪个子 Agent。在这里为了让代码可读计划是写死的但扩展思路是清晰的。接入真实 LLM 时你只需要重写 LlmClient 里的几个方法plan 方法通过调用大模型生成任务拆解方案generate 和 review 方法通过具体模型 API 完成文本生成summarize 方法把多个结果合并成最终输出。其余代码基本不用动。6. 运行验证与效果评估把上面的代码保存为orchestrator_demo.py然后在命令行执行python orchestrator_demo.py你会看到类似下面的输出[Orchestrator] 注册执行单元code-generator [Orchestrator] 注册执行单元code-review [Orchestrator] 注册执行单元code-runner [Orchestrator] 任务计划{steps: [{unit: code-generator, payload: {requirement: 用Python实现冒泡排序}}, {unit: code-review, payload: {code: ref:code-generator.code}}, {unit: code-runner, payload: {code: ref:code-review.fixed_code}}]} [Orchestrator] 调用 code-generatorpayload{requirement: 用Python实现冒泡排序} [Orchestrator] code-generator 返回{status: ok, code: def bubble_sort(arr):\n n len(arr)\n ...} [Orchestrator] 调用 code-reviewpayload{code: def bubble_sort(arr):\n n len(arr)\n ...} [Orchestrator] code-review 返回{status: ok, review: 建议补充类型注解和边界测试, fixed_code: ..., score: 88} [Orchestrator] 调用 code-runnerpayload{code: ...} [CodeExecutorTool] 收到代码 147 字符 [Orchestrator] code-runner 返回{status: ok, stdout: 模拟执行成功[5, 3, 8, 1] - [1, 3, 5, 8]} [Orchestrator] 最终汇总 {status: ok, summary: 任务「用Python实现冒泡排序」完成代码审查得分88}怎么判断这次运行是成功的两个标准第一每个执行单元都返回了status: ok说明流程没有中断第二最终汇总里拿到了 code-review 的得分说明前序步骤的结果确实通过 ref 引用传给了后续步骤。如果运行失败优先按这个顺序排查先看是否所有类都定义完整Python 报错信息会精确到行号再看resolve_payload里的 ref 路径是否写错比如ref:code-generator.code中字段名必须和上一步返回的字典 key 完全一致最后看llm.plan返回的 steps 里有没有引用未注册的 unit 名称。这里要特别提醒这个示例里的 code-runner 只是模拟执行没有真正运行生成的代码。真实项目中AI 生成的代码放进执行环境是一件高风险操作必须放到沙箱容器里并对资源使用、网络访问、文件系统读写做严格限制。这也是 AI 软件工厂里权限与安全边界的一部分后面会展开讲。7. 除主从模式外另外三个高频设计模式主从模式解决了多 Agent 协作的控制问题但一个完整的 AI 软件工厂还需要处理其他变化点。下面三个设计模式在实践里出现频率很高而且和主从模式天然互补。7.1 策略模式模型路由一个 AI 软件工厂里不太可能只使用一个大模型。简单任务用低成本模型复杂任务用高能力模型代码任务用代码模型对话任务用通用模型这是很常见的诉求。如果没有策略模式模型选择逻辑会散落在各个调用点改一次策略要动很多文件。class ModelRouter: def __init__(self, strategy): self._strategy strategy def set_strategy(self, strategy): self._strategy strategy def route(self, task: dict) - str: return self._strategy.select(task) class CostFirstStrategy: def select(self, task: dict) - str: if task.get(type) code: return fast-code-model return lite-chat-model class QualityFirstStrategy: def select(self, task: dict) - str: if task.get(type) code: return strong-code-model return fast-chat-model使用策略模式之后路由逻辑被封装在策略对象里任务类型变化时只改策略不需要改调用方。7.2 状态机模式任务生命周期管理多 Agent 任务的执行过程不是一条直线。一个任务可能处于待处理、生成中、审查中、执行中、失败、重试、完成等状态。如果这些状态散落在 if/else 里维护成本会快速上升。状态机模式把这些状态和合法迁移集中管理让状态变化可追踪、可校验。from enum import Enum class TaskState(Enum): PENDING pending RUNNING running REVIEWING reviewing DONE done FAILED failed STATE_TRANSITIONS { TaskState.PENDING: {TaskState.RUNNING, TaskState.FAILED}, TaskState.RUNNING: {TaskState.REVIEWING, TaskState.FAILED}, TaskState.REVIEWING: {TaskState.DONE, TaskState.RUNNING, TaskState.FAILED}, } def can_transition(current: TaskState, target: TaskState) - bool: return target in STATE_TRANSITIONS.get(current, set()) def apply_state(current: TaskState, target: TaskState) - TaskState: if not can_transition(current, target): raise ValueError(f非法状态迁移{current} - {target}) return target状态机模式配合主从模式特别好用Orchestrator 每调度一个子任务就更新一次任务状态并落日志。一旦某个环节反复失败系统可以根据状态机定义走到 FAILED 状态再触发补偿或者人工介入。7.3 工厂模式统一创建 Agent 和工具在大型 AI 项目里Agent 和工具的数量可能会非常多。如果每个地方都手动new一个实例配置分散且容易写错。工厂模式把一个 Agent 或工具的创建逻辑收敛到一处配置文件和生产逻辑分离。class AgentFactory: _registry {} classmethod def register(cls, name, builder): cls._registry[name] builder classmethod def create(cls, name, config): if name not in cls._registry: raise ValueError(f未注册的 Agent 类型{name}) return cls._registry[name](config) # 使用示例先把创建器注册到工厂 def build_code_generator(config): return CodeGeneratorWorker(llmLlmClient()) AgentFactory.register(code-generator, build_code_generator) agent AgentFactory.create(code-generator, {model: strong-code-model})再配合一份 YAML 或 JSON 配置文件就能让 Agent 的创建过程参数化agents: code-generator: type: code-generator model: strong-code-model max_tokens: 4096 code-review: type: code-review model: strong-chat-model max_tokens: 2048这种做法的好处是新增一种 Agent 时只需要注册新的创建器业务代码不需要感知细节。8. 常见问题与排查思路在 AI 软件工厂的实际开发中下面这些问题出现频率很高。整理成表格方便你按图索骥。问题现象可能原因排查方式解决方案子 Agent 输出不稳定Prompt 不明确、模型切换对比同任务多次输出固定系统 Prompt加输出格式约束Subagent 上下文溢出子任务过大携带过多历史信息查看每个子任务的 tokens 消耗控制任务粒度精简上下文多个 Agent 互相反复调用没有清晰的调用协议看日志里的调用链坚持主从模式禁止同级乱调流程执行一半失败子 Agent 超时或工具异常查状态机日志和错误信息增加重试和降级策略Token 成本过高任务拆解粒度太粗统计每个 Agent 的 token 消耗用策略模式做模型路由简单任务用低成本模型生成的代码执行报错LLM 幻觉、依赖缺失在沙箱里看完整 stderr增加测试步骤用真实执行结果反馈给 Agent这里重点展开两个问题。第一个是 Subagent 上下文溢出。很多人在设计子任务时习惯把全部需求文档、历史对话、代码库信息塞给子 Agent结果上下文很快耗尽模型输出质量急剧下降。实际上主从模式的价值就在于“信息隔离”。主 Agent 负责全局理解子 Agent 只需要看到完成任务所需的局部信息。如果你的子 Agent 经常超长先检查是不是塞了太多不相关的内容。第二个是多个 Agent 互相反复调用。表面上看Agent 之间动态对话很“智能”但在工程上很难控制。A 让 B 生成代码B 让 C 检查代码C 又把问题抛回给 A最后没人负责收口。这个问题最好的解决方式不是优化模型而是用架构约束所有调用必须经过 Orchestrator子 Agent 之间不允许直接通信。如果某个子 Agent 发现任务需要调整它应该把结论返回中心节点由 Orchestrator 决定下一步而不是自己再拉别的 Agent 进来。9. 工程实践建议代码可以跑通只是第一步。想在生产环境里真正落地一套 AI 软件工厂下面这些工程建议值得认真对待。先跑通最小闭环。不要一上来就设计十个 Agent、二十个工具。选一个真实的小任务比如“根据接口文档生成单元测试”用主从模式搭一个最小闭环验证编排、上下文传递、结果汇总、失败重试这些基础能力再逐步扩展。最小闭环能帮你更早暴露问题而不是在复杂系统里迷失。统一协议是基础。所有 Subagent 和 Tool 的输入输出尽量用 JSON 结构定义清楚。每个执行单元至少返回状态、数据和错误信息三个字段。不要用自然语言作为接口否则后续解析和判断会非常痛苦。统一的输入输出协议也是主从模式稳定性的前提。权限与安全边界要前置。AI 生成的代码要执行必须进沙箱AI 要访问数据库必须最小权限AI 要调外部 API必须走白名单。很多 AI 工具链出事不是因为模型不行而是因为给 AI 开了一扇任意操作的大门。安全边界的落地应该和功能开发同步而不是等系统上线再补。可观测性不只是一份日志。每个 Agent 的调用记录、每个任务的完整状态流转、每一步的耗时和 token 消耗都要有结构化数据。有了这些数据你才能回答“为什么这个任务慢了”“为什么这个 Agent 老是失败”。在 AI 软件工厂里可观测性是优化迭代的地基。Agent 版本要管