第三周:CrewAI 的 Crews、Flows 与 YAML
把 agent 和任务写进 YAML,把代码执行关进 Docker。这一周最值钱的不是框架 API,是它逼你回答「这个 agent 的角色边界到底在哪」。
第二周的 SDK 很轻,你写多少它做多少。CrewAI 走的是另一头:它有主张。
Crew 和 Flow:两种形状
CrewAI 里有两个东西容易混:
- Crew —— 一群有角色的 agent 协作完成一个目标,过程由框架编排
- Flow —— 显式的流程控制,你来定谁先谁后
按四层栈的说法,Crew 更靠近 agent 那一侧(把编排交出去),Flow 更靠近 workflow(自己控制路径)。
框架给你两个都提供,本身就是在承认:没有一种形状适合所有任务。
用 YAML 定义 agent 和 task
CrewAI 的一个鲜明选择是把 agent 和 task 写进 YAML:
researcher: role: 资深财务研究员 goal: 找出 {company} 最近一个季度的关键财务信号 backstory: 你读过十年的财报,习惯先看现金流再看利润 llm: gpt-5这个设计的好处和坏处一样明显。
好处:角色定义和代码分开了。 改一个 agent 的职责不用动 Python,而且 diff 里能一眼看出改了什么。
坏处:YAML 里塞的是提示词,而提示词是请求不是约束。 role 和 backstory 写得再漂亮,模型照做与否没有任何东西拦得住。真正的约束得写在工具和校验里。
结构化输出、记忆、层级流程
第三周的股票挑选项目会同时用上三样:
Pydantic 结构化输出 —— 让 crew 的产出能被程序读。这一步几乎是所有多 agent 项目的必经之路,因为下一个 agent 的输入必须是结构化的,否则误差会沿着链路放大。
记忆 —— CrewAI 有短期、长期、实体几种记忆。这里要小心一条:共享记忆的代价是一次误判被固化成事实,后面所有 agent 都会跟着错。 所以进记忆最好有门槛(被独立观察到几次才算数),出记忆最好有期限。
层级流程(hierarchical) —— 有一个 manager agent 决定派谁去干。这就越过了 workflow / agent 的分界线:控制权交给了模型。
Docker 沙箱:这一周最该抄的一条
编码 agent 那一节的做法是:让 agent 生成代码,但在 Docker 里执行。
这条值得单独强调,因为它是结构性的安全,不是靠提示词求来的:
- 模型生成什么代码都行,它跑在一个可以随时扔掉的容器里
- 容器崩了不是灾难,只是一次工具调用返回了错误
- 更重要的是凭据不在那个容器里
最后一条是关键。Anthropic 在拆分 brain/hands 的时候点名过这个问题:原来的设计里 agent 生成的任何不可信代码和凭据跑在同一个容器里,把执行环境分出去之后,提示词注入就拿不到 token 了。
「牲口不是宠物」 —— 执行环境随时可以被换掉,这是让 agent 能安全动手的前提。
四个 agent 的工程团队
这一周的收尾项目是一个四角色团队:设计、写代码、写测试、管理。
它值得注意的地方不是「多 agent 很酷」,是角色划分的判据:
好的划分: 每个 agent 有独立的输入和可判定的产出。写测试的那个,产出是测试文件,跑不跑得过是客观的。
坏的划分: 按「阶段」硬切,结果每个 agent 都需要上一个的全部上下文 —— 那还不如一个 agent 干完。
而这里有一条更硬的:写代码的和写测试的必须分开。让同一个 agent 既写实现又写测试,它写出来的测试会精确地覆盖它已经想到的那些情况 —— 测试通过只证明它自洽,不证明它对。
不过审查这一格有个反方向的坑,是我自己踩出来的。我给产出加了一道形式检查当拒收门,第一轮跑完 7 条里 7 条被拒,而我人工看了一遍,那七条全都是可用的。道理上那道门讲得通,战绩上它一条都没拦对。我的判断是:一道门能不能拒收,看的是它的战绩,不是它的道理 —— 所以我把它降级成了警告,只留下另一道真正拦住过错误的当拒收门。
边界与代价
opinionated 框架的代价是它的意见可能不是你的。 YAML、角色、backstory 这套在「模拟一个团队」的任务上很顺;在「一条确定的流水线」上就是绕路。
多 agent 的调试成本是超线性的。 一个 agent 出错你看它的输出;四个 agent 出错你得先定位是谁、再看它拿到的输入对不对 —— 而它的输入是上一个的输出。交接处必须有可校验的契约,否则错误会 100% 传染到下游。
Docker 沙箱不等于安全。 它挡住了「代码搞坏你的机器」,没挡住「agent 通过合法的工具做了不该做的事」。不可逆动作仍然需要一道显式的门。