本节约处在第五章第一站,也是设计纪律的起点。多智能体系统崩,很少崩在语法,而是崩在"边界划错"——两个角色职责重叠、一个 Task 验收标准虚、上下游靠猜传话。我们给三条可操作原则,每条都配反例。
先把"好边界 vs 坏边界"画成对照,建立直觉:

原则一:单一职责。一个 Agent 只干一类事,别让"研究员"又搜又写又审。重叠的职责会让两个角色抢活、产出互相覆盖,错误难归责。下面的反例和正例对比:
# 反例:一个角色啥都干,边界模糊 all_in_one = Agent(role="全能助手", goal="调研并撰写并审核", backstory="什么都会", verbose=True) # 正例:拆成单一职责的三个角色 researcher = Agent(role="研究员", goal="只负责搜资料", backstory="严谨", verbose=True) writer = Agent(role="写手", goal="只负责成文", backstory="连贯", verbose=True) checker = Agent(role="审核", goal="只负责找错", backstory="挑剔", verbose=True)
原则二:可验收。每个 Task 的 expected_output 必须能被程序或人判定"算不算数"。虚的产出("一份报告")没法验收,实的产出("三条要点,每条含现象/原因/建议")才能当接口。这条在 2.2 强调过,这里上升到原则:验收标准写不清的 Task 不进 Crew。
# 不可验收 bad = Task(description="分析数据", expected_output="一份分析", agent=researcher) # 可验收:格式与内容双重约束 good = Task( description="分析 {data} 月度趋势", expected_output="三条,每条:现象一句 / 可能原因一句 / 建议动作一句,换行分隔", agent=researcher, )
原则三:低耦合。角色之间只通过 Task 的 context 传数据,不要在 Agent 的 backstory 里硬编码"等写手给你东西"这类跨角色约定。耦合藏在设定里,重构时找不到;耦合写在 Task 图里,一眼可见。
# 低耦合:依赖显式写在任务图 t_find = Task(description="搜 {topic} 事实", expected_output="要点", agent=researcher) t_write = Task(description="写成文", expected_output="文章", agent=writer, context=[t_find]) # writer = Agent(role="写手", backstory="等待研究员先把事实发你再写", ...)
还有一个工程层面的重要原则:角色数够用即可,别为架构好看堆人。我们见过"研究员/写手/编辑/润色/排版"五角色,结果润色和排版产出几乎不可区分,反而增加 token 与调试面。先用最小三角色跑通,缺哪种能力再加哪种,每次加人都有明确收益对照。
收尾提醒:设计原则不是教条,是降低"协作熵"的手段。边界越清、验收越硬、耦合越低,你的 Crew 越可预测、越可改。带着这三条去审自己的设计,比背 API 更能决定项目成败。下一站讲提示词——把原则落到"约束写在哪里"的具体写法。
我们把多年踩坑收敛成几条可操作的原则,每条都对应一个真实代价:
| 原则 | 做法 | 违反的代价 |
|---|---|---|
| 单一职责 | 一个 Agent 只扮演一种角色 | 人格混杂,产出漂移 |
| 契约优先 | 先写 expected_output 再配 Agent | 下游拿半成品 |
| 最小权限 | 只给完成任务必需的工具 | 工具被误用、超支 |
| 显式依赖 | 用 context 声明依赖 | 链路错乱、数据断流 |
⚠️ 常见坑:把多个职责塞进一个 Agent,比如"又调研又写又审",结果是每样都一般。我们宁可多一个轻量 Agent,也要保住单一职责。
from crewai import Agent, Task # 反例:一个 Agent 身兼三职 all_in_one = Agent(role="全能", goal="调研+写+审", backstory="啥都会", verbose=True) # 正例:拆成三个单一职责 research = Agent(role="研究员", goal="只调研", backstory="严谨", verbose=True) write = Agent(role="写手", goal="只写", backstory="清楚", verbose=True) review = Agent(role="校对", goal="只审", backstory="较真", verbose=True) t_r = Task(description="调研", expected_output="事实清单", agent=research) t_w = Task(description="写稿", expected_output="稿件", agent=write, context=[t_r]) t_v = Task(description="审校", expected_output="修改意见", agent=review, context=[t_w]) print([a.role for a in (research, write, review)])
💡 关键直觉:设计多智能体系统像搭积木——每块形状单一,才能拼出稳固结构。职责越单一,复用与替换越容易;一个 Agent 越"全能",它越像一个谁都替代不了、又谁都不放心的黑盒。
# 最小权限:只挂必要工具 from crewai_tools import SerperDevTool research.tools = [SerperDevTool()] write.tools = [] # 写手不需要搜索 print("研究员工具数:", len(research.tools), "写手工具数:", len(write.tools))
落地前用这张清单自检:每个 Agent 是否只扮演一种角色?每个 Task 是否都有可校验的 expected_output?每个 Agent 是否只挂了必需工具?依赖是否都用 context 显式声明?四条全过,返工概率会大幅下降。
⚠️ 常见坑:清单最后一条最容易被忽略。依赖靠"口头约定"而非 context,系统一改顺序就断流。把依赖写进代码,而不是记在脑子里。