多 Agent:角色、职责与输入输出边界
给多个角色起名字并不等于完成了分工。每个角色需要明确收到什么、交出什么、能使用哪些工具,以及由谁处理冲突。下面先看任务怎样拆得清楚,再讨论独立上下文和并行的价值。
多 Agent 的核心是协调,不是让多个角色自由聊天。拆分必须带来至少一种明确收益:独立上下文、并行处理、专业工具隔离、独立复核或权限隔离。
1. 常见角色
- Planning-only Planner:拆解目标并生成可验证子任务,由独立 Worker 执行。这是一种职责隔离模式;小型系统也可由同一 Agent 规划后执行。
- Executor/Worker:执行限定任务并返回产物和证据。
- Researcher:搜集来源、区分事实与推断。
- Writer:基于给定证据组织内容。
- Reviewer/Critic:按 rubric 找缺陷,不直接改变目标。
- Router:根据请求类型选择执行路径。
- Supervisor:分派任务、汇总状态、处理冲突和停止。
角色名没有价值,清晰契约才有价值。
2. Task Contract
from dataclasses import dataclass
@dataclass(frozen=True)
class DelegatedTask:
task_id: str
parent_task_id: str
objective: str
input_refs: tuple[str, ...]
allowed_tools: tuple[str, ...]
write_scope: tuple[str, ...]
output_schema: "JSONSchema"
acceptance_criteria: tuple["Check", ...]
deadline: str
max_steps: int
struct DelegatedTask {
task_id: String,
parent_task_id: String,
objective: String,
input_refs: Vec<String>,
allowed_tools: Vec<String>,
write_scope: Vec<String>,
output_schema: JsonSchema,
acceptance_criteria: Vec<Check>,
deadline: String,
max_steps: u32,
}
/**
* @typedef {{
* taskId: string,
* parentTaskId: string,
* objective: string,
* inputRefs: string[],
* allowedTools: string[],
* writeScope: string[],
* outputSchema: JSONSchema,
* acceptanceCriteria: Check[],
* deadline: string,
* maxSteps: number
* }} DelegatedTask
*/
type DelegatedTask = {
taskId: string
parentTaskId: string
objective: string
inputRefs: string[]
allowedTools: string[]
writeScope: string[]
outputSchema: JSONSchema
acceptanceCriteria: Check[]
deadline: string
maxSteps: number
}
Worker 返回:
from dataclasses import dataclass
from typing import Any, Literal
@dataclass(frozen=True)
class TaskResult:
task_id: str
status: Literal["completed", "partial", "blocked", "failed"]
output: Any
evidence_refs: tuple[str, ...]
changes: tuple["ChangeSummary", ...]
validation: "ValidationResult"
remaining: tuple[str, ...]
enum TaskStatus {
Completed,
Partial,
Blocked,
Failed,
}
struct TaskResult {
task_id: String,
status: TaskStatus,
output: serde_json::Value,
evidence_refs: Vec<String>,
changes: Vec<ChangeSummary>,
validation: ValidationResult,
remaining: Vec<String>,
}
/**
* @typedef {{
* taskId: string,
* status: 'completed'|'partial'|'blocked'|'failed',
* output: unknown,
* evidenceRefs: string[],
* changes: ChangeSummary[],
* validation: ValidationResult,
* remaining: string[]
* }} TaskResult
*/
type TaskResult = {
taskId: string
status: 'completed' | 'partial' | 'blocked' | 'failed'
output: unknown
evidenceRefs: string[]
changes: ChangeSummary[]
validation: ValidationResult
remaining: string[]
}
3. 职责边界
- 采用 planning-only 模式时,Planner 不直接写文件,以保持计划输出可独立审查;混合 Planner/Executor 则要显式记录它何时从规划切换到执行;
- Writer 只使用 Researcher 提供的 Evidence;
- Reviewer 依据固定 rubric,不凭风格偏好无限扩展;
- Worker 的工具和写入范围是最小集合;
- Supervisor 决定接受、重做、合并或结束。
4. 上下文隔离
子 Agent 不必继承全部历史。应只获得完成任务需要的目标、输入引用、约束、工具和验收标准。隔离能降低 token、减少无关偏见,也降低敏感信息扩散。
5. 何时不拆
- 任务只需少量连续步骤;
- 子任务强依赖同一上下文;
- 协调成本高于并行收益;
- 没有明确输出 schema;
- Reviewer 只是重复主 Agent 的主观判断;
- 工具或资源存在强写冲突。
先测单 Agent 基线,再用相同任务集比较成功率、成本、延迟和故障率。
给子任务一张足够用的任务单
让两个 Worker 分别检查接口和测试时,先写清各自能改哪些文件、输入基线是什么、最后要交什么证据。比如接口 Worker 交接口差异与相关用例,测试 Worker 交失败复现与结果;不要只说“你负责质量”。
Deep Agents 的子 Agent 中间件提供了独立任务调用的实现入口,但上下文分开不意味着文件系统、存储或权限自动分开。共享 backend 时,两个 Worker 仍可能碰到同一份文件。
练习先只允许两个 Worker 阅读,汇总它们引用的路径与结论。确认输出能够合并后,再允许各自修改不同文件,最后串行整合并跑一次完整检查。任务单应写入真实资源边界,不能只依赖角色名字。
本节的核验依据
2026-10-25 查阅。下面的链接支持本节的机制说明;练习场景和选型建议是本教程的教学设计。
