Multi-Agent 就是多个内置提示词吗?从子代理到多智能体系统
在学习 AI Agent 时,我们经常会看到 Planner Agent、Coder Agent、Tester Agent、Reviewer Agent 等不同角色。它们看起来只是分别配置了一段系统提示词,于是很容易产生一个疑问:
Multi-Agent 是不是给同一个大模型换几套提示词,让它分别扮演不同角色?
答案是:提示词是创建子代理的重要部分,但只有提示词,还不能构成完整的 Multi-Agent 系统。
真正的子代理不仅要有独立角色,还要有自己的任务、上下文、工具、执行状态和结果返回机制。Multi-Agent 的核心也不是“有几个提示词”,而是多个可独立执行的 Agent 如何分工、通信、协作和验收。
一、什么是 Agent?
在工程实现中,一个 Agent 通常可以抽象为:
Agent
= LLM
+ System Prompt
+ 当前任务
+ 上下文
+ 工具集合
+ 记忆和状态
+ 执行循环
各部分分别负责:
| 组成部分 | 作用 |
|---|---|
| LLM | 理解任务、推理并生成决策 |
| System Prompt | 定义角色、职责、边界和输出格式 |
| Task | 指定本次需要完成的具体目标 |
| Context | 提供完成任务需要的信息 |
| Tools | 让 Agent 能读取文件、执行命令或访问外部系统 |
| Memory | 保存任务进度、事实和历史结果 |
| Agent Loop | 让 Agent 可以持续观察、决策、执行和验证 |
因此,提示词主要解决“你是谁、你负责什么”,并不能单独解决“你如何执行、可以操作什么、怎样判断任务已经完成”。
二、什么是子代理?
子代理是由主代理或调度器创建、调用和管理的 Agent 实例。
例如,用户提出:
帮我开发一个用户登录功能。
主代理可以将任务拆成:
主代理
├── 架构子代理:设计认证流程和接口
├── 编码子代理:实现登录功能
├── 测试子代理:编写并运行测试
└── 审查子代理:检查安全风险
主代理负责:
- 理解用户的最终目标;
- 把复杂目标拆成子任务;
- 决定创建哪些子代理;
- 给每个子代理提供必要上下文;
- 跟踪任务状态和依赖关系;
- 汇总并验证各子代理的结果。
子代理负责:
- 接收一个边界清楚的任务;
- 在自己的上下文中独立工作;
- 使用被授权的工具;
- 生成约定格式的结果;
- 将结果和证据返回给主代理。
一个简化的 Java 表达如下:
Agent testAgent = new Agent(
"你是一名测试工程师,负责验证功能并报告失败原因。",
List.of(fileReader, shellTool, testRunner),
new AgentMemory()
);
AgentTask task = new AgentTask(
"为登录接口编写测试,并执行测试套件",
Map.of("sourceDir", "src/main/java")
);
AgentResult result = testAgent.run(task);
这里的系统提示词只是 Agent 的一个配置项。让它成为真正子代理的,是完整的任务执行能力和生命周期。
三、只有多个提示词算不算 Multi-Agent?
看下面这段伪代码:
String design = llm.chat(
"你是架构师,请设计登录功能。"
);
String code = llm.chat(
"你是程序员,请根据以下设计生成代码:" + design
);
String review = llm.chat(
"你是审查员,请检查以下代码:" + code
);
它通过不同提示词模拟了三个角色,可以称为一种非常简化的“多角色流水线”。但它还不是一个完整的 Multi-Agent 系统,因为这些角色可能:
- 没有独立的消息历史;
- 没有自己的工具权限;
- 没有任务状态和记忆;
- 不能自主执行多轮操作;
- 不能并行工作;
- 没有失败重试机制;
- 没有标准化的结果回传协议。
这种方式更准确的描述是:
使用同一个 LLM,通过不同角色提示词完成分阶段调用。
它并非没有价值。对于固定、简单的工作流,这种实现成本低、行为容易控制,甚至可能比复杂的 Multi-Agent 更合适。
四、真正的多个子代理有什么不同?
完整的子代理通常具有以下隔离性。
1. 独立角色
每个子代理拥有自己的 system prompt:
Coder Agent:实现功能,不修改测试验收条件。
Tester Agent:独立验证,不默认相信开发者的结论。
Reviewer Agent:只报告有证据的问题,不直接修改代码。
角色提示词用于划分职责和减少目标冲突。
2. 独立任务
主代理不会只告诉子代理“帮忙看看”,而应提供:
{
"taskId": "task-102",
"goal": "验证登录接口在密码错误时返回 401",
"inputs": ["LoginController.java", "AuthService.java"],
"expectedOutput": "测试结果、失败日志和修复建议",
"doneCondition": "测试已实际运行并提供退出状态"
}
任务越明确,子代理越不容易偏离目标。
3. 独立上下文
子代理不需要继承主代理的全部对话历史。测试 Agent 可能只需要接口设计、相关代码和验收标准,不需要看到所有产品讨论。
这样可以:
- 减少 token 消耗;
- 避免无关信息干扰;
- 降低提示注入扩散;
- 防止所有 Agent 形成相同偏见。
4. 独立工具
不同子代理可以拥有不同权限:
Research Agent:联网搜索、读取资料
Coder Agent:读取和修改代码
Tester Agent:执行测试命令
Reviewer Agent:只读代码,不允许写入
工具隔离不仅是职责划分,也是安全边界。
5. 独立执行循环
一个子代理通常会经历:
观察任务
→ 制定局部计划
→ 调用工具
→ 读取执行结果
→ 修正方案
→ 验证完成条件
→ 返回结果
这比“调用一次 LLM 得到一段文本”更接近真正的 Agent。
6. 独立状态
子代理需要记录:
- 已完成步骤;
- 使用过的工具;
- 产生的文件;
- 当前错误;
- 重试次数;
- 最终状态。
常见状态包括:
PENDING
RUNNING
WAITING
SUCCEEDED
FAILED
CANCELLED
主代理依靠这些状态调度后续任务。
五、多个子代理可以共用同一个大模型
不同 Agent 不一定使用不同模型。
Planner Agent ─┐
Coder Agent ─┼── 同一个 LLM API
Tester Agent ─┤
Reviewer Agent ┘
它们之所以是不同 Agent,并不是因为底层模型不同,而是因为它们拥有不同的:
- 身份和提示词;
- 任务目标;
- 消息历史;
- 可用工具;
- 记忆空间;
- 权限范围;
- 执行状态。
当然,也可以根据成本和能力使用不同模型:
规划与疑难分析 → 强推理模型
资料分类 → 轻量模型
代码审查 → 代码能力更强的模型
简单格式转换 → 低成本模型
所以,模型是 Agent 的“大脑”,但 Agent 是模型加上运行环境后的完整执行单元。
六、Multi-Agent 与子代理是什么关系?
两者相关,但并不完全等价。
子代理强调父子层级:
主代理 → 创建子代理 → 分配任务 → 回收结果
Multi-Agent 是更大的概念,多个 Agent 还可以采用:
- 管理者—执行者模式;
- 顺序流水线模式;
- 并行协作模式;
- 辩论与裁判模式;
- 去中心化协商模式。
因此可以近似理解为:
子代理系统是 Multi-Agent 的一种常见实现。
如果系统中只有一个主代理动态调用若干工作 Agent,它属于层级式 Multi-Agent;如果所有 Agent 地位平等、通过消息互相协作,就不一定存在“子代理”关系。
七、Multi-Agent 的运行过程
以“开发博客系统”为例:
第一步:规划
主代理将目标拆成:
- 分析功能需求;
- 设计数据库;
- 开发后端接口;
- 开发前端页面;
- 编写测试;
- 执行集成验证。
第二步:构建依赖关系
需求分析
├── 数据库设计 → 后端开发 ─┐
└── 页面设计 → 前端开发 ─┼→ 集成测试
┘
没有依赖关系的前端和后端任务可以并行,有依赖的任务必须等待前置结果。
第三步:创建子代理
主代理为每个任务配置:
- 角色提示词;
- 输入材料;
- 工具权限;
- 最大执行轮数;
- token 和时间预算;
- 预期输出格式;
- 完成条件。
第四步:执行和通信
Agent 之间最好传递结构化消息:
{
"sender": "backend-agent",
"receiver": "frontend-agent",
"type": "ARTIFACT_READY",
"taskId": "backend-api",
"summary": "文章列表接口已经完成",
"artifacts": ["openapi.yaml"],
"status": "SUCCEEDED"
}
不要把每个 Agent 的全部思考历史广播给其他 Agent。应传递结论、证据、产物和仍未解决的问题。
第五步:验收
子代理说“已经完成”并不代表真的完成。主代理需要检查:
- 文件是否真实存在;
- 代码是否可以编译;
- 测试是否实际运行;
- 输出是否满足格式;
- 是否达到用户要求;
- 是否需要人工审批。
Multi-Agent 的可靠性来自可验证的结果,而不是 Agent 之间互相表示认可。
八、为什么要使用多个子代理?
多个子代理主要有四个价值。
专业分工
每个 Agent 聚焦一个有限领域,可以使用更精确的提示词和工具。
上下文隔离
复杂任务的所有信息不必塞进一个上下文窗口,每个 Agent 只加载必要内容。
并行执行
相互独立的任务可以同时运行,从而缩短总耗时。
交叉验证
开发者和测试者使用独立上下文,可以减少“自己写、自己证明正确”的偏差。
九、多个子代理不是越多越好
创建子代理也有成本:
- 每个 Agent 都会消耗 token;
- 任务交接可能丢失信息;
- 多个 Agent 可能重复工作;
- 并发修改相同文件可能产生冲突;
- 调度、重试和汇总会增加系统复杂度;
- 多个 Agent 可能一直讨论,却没有实际产物。
例如,“修改一个方法名称”通常不需要 Planner、Coder、Tester、Reviewer 四个 Agent。单 Agent 直接修改并运行测试更高效。
适合拆成子代理的任务通常具备至少一个条件:
- 可以拆成边界清楚的独立部分;
- 并行执行能够明显节省时间;
- 需要不同工具或权限;
- 需要独立审查;
- 单一上下文已经过于庞大;
- 子任务具有明确的验收标准。
十、实现时最重要的设计原则
1. 任务边界比角色名称重要
“你是资深工程师”很模糊,“修复登录接口的空指针并运行指定测试”才是可执行任务。
2. 最小化上下文
只给子代理完成任务需要的文件、事实和约束。
3. 限制工具权限
只读任务不应该获得文件写入权限,代码审查 Agent 也不应该默认拥有部署权限。
4. 使用结构化结果
统一返回:
{
"status": "SUCCEEDED",
"summary": "完成了什么",
"artifacts": [],
"evidence": [],
"remainingIssues": []
}
5. 设置结束条件
限制执行轮数、重试次数、token 和时间预算,避免 Agent 无限循环。
6. 验证实际产物
尽量使用编译器、测试工具、格式校验器和真实文件状态,而不是再次询问 LLM“这个结果是否正确”。
总结
多个子代理并不只是多个内置提示词。
提示词决定 Agent 扮演什么角色,但一个真正的子代理还需要:
独立角色
+ 独立任务
+ 独立上下文
+ 独立工具
+ 独立记忆和状态
+ 独立执行循环
+ 与主代理的通信协议
如果只是给同一个模型依次设置“架构师、程序员、测试员”提示词,那更像是多角色调用或固定流水线;如果每个角色能够独立接受任务、调用工具、维护状态、验证结果并向调度器回传产物,才形成了真正的子代理系统。
Multi-Agent 最难的部分从来不是创建多少角色提示词,而是如何拆分任务、控制上下文、分配权限、处理依赖和冲突,以及用可靠证据判断每个 Agent 是否真的完成了工作。