
如何写出合法的 CrewAI crewai.flow/v1 声明式 FlowAGENTS.md 编写规范全解析【免费下载链接】crewAIFramework for orchestrating role-playing, autonomous AI agents. By fostering collaborative intelligence, CrewAI empowers agents to work together seamlessly, tackling complex tasks.项目地址: https://gitcode.com/GitHub_Trending/cr/crewAI本篇以 CrewAI CLI 声明式 Flow 项目模板中内置的 AGENTS.md 为核心逐条解析编写合法crewai.flow/v1YAML/JSON 声明的完整规则从状态state建模、方法method编排、三类动作expression / agent / crew选型到 CEL 表达式插值、路由router/emit机制与完整字段级 API 参考。读完本文你既能约束 AI 代理替你自动生成 Flow 声明也能人工写出结构正确、可被crewai run直接执行的声明式 Flow 定义。一、这份 AGENTS.md 是什么、从哪里来AGENTS.md 位于 CLI 的声明式 Flow 项目模板目录 templates/declarative_flow/ 下它不面向人类用户阅读而是一份写给 AI 代理的“作者指令”当用户要求 AI 创建或编辑 CrewAI Flow 时代理必须依据这份文档输出一份单一的、合法的crewai.flow/v1YAML 或 JSON 文档。从源码看执行crewai flow create --declarative入口见 create_flow.py 中的_create_declarative_flow时CLI 会把该模板目录整体复制到新项目根目录。其中root_template_files显式包含.gitignore、AGENTS.md、README.md、pyproject.toml也就是说AGENTS.md 会随每个声明式 Flow 项目一起落地到项目根目录成为该项目后续 AI 协作编辑的常备规范。模板同时生成一个最小可运行的 flow.yamlschema: crewai.flow/v1 name: {{flow_name}} description: A declarative CrewAI Flow. state: type: dict default: topic: AI agents methods: start: start: true do: call: expression expr: state.topic这个起步文件展示了 Flow 的最小骨架schema标识、name、state、以及带start: true的单个方法。而 模板 README 给出的项目操作方式是crewai install # 安装依赖 crewai run # 运行声明式 Flow并可按需在src/folder/crews/可复用 Crew、src/folder/tools/自定义 Python 工具、src/folder/knowledge/共享知识文件中扩展。AGENTS.md 的价值正在于此它把“如何写一个能通过校验、正确接线、正确传数的 flow.yaml”沉淀为可复制的规则覆盖从骨架到路由分支的全部细节。二、输出契约只返回一份合法的声明文档文档开篇即规定了两条硬约束只输出一份合法的crewai.flow/v1Flow 声明不要附带解释性文字除非用户明确要求先照示例掌握形状与格式再用文末 API 参考核对精确字段——示例管“形状”参考管“字段名、必填项、链接类型与允许的 action/state 形状”。同时文档声明了自己的定位“把它当作对你的指令而不是展示给用户的文字”。这正是 AGENTS.md 类文件的典型用法它是给 LLM 的系统级写作约束。三、按固定顺序构建 FlowBuild It In This OrderAGENTS.md 给出的 7 步构建顺序是整份规范的主干也是人工编写 Flow 时可直接套用的检查清单先定义state。使用type: json_schema并把 JSON Schema 内联写入必填输入字段放在state.json_schema.required中。不要指望用state.default让字段变必填——默认值与必填性是两回事恰好一个方法带start: trueCLI 模板变体中是单入口规则后续方法通过listen接入上游每个方法有且仅有一个do动作对象do绝不能是列表用${...}映射从state和已完成的outputs传递数据产出前检查所有listen、emit、outputs.some_method引用是否有效。另有两条全局约定可选字段只在确有必要时设置否则信任 CrewAI 默认值并省略方法名必须匹配正则^[A-Za-z_][A-Za-z0-9_]*$即合法的 Python 标识符形式。四、每个方法只选一种动作且选最简单的文档要求“选择能完成任务的最简单动作”并给出三类动作的选型边界动作适用场景关键写法约束call: expression简单读取、过滤、计算值、确定性路由在expr中写原始 CEL不要用${...}包裹call: agent单个 AI 工作者分类、决策、总结、写作、起草role、goal、backstory、input都放在with下agent 动作没有动作级inputs映射call: crew多 Agent / 多任务协同Crew 定义放在with下运行期值用动作级inputs映射传入这三类动作与仓库中的示例文件 flow_definition_example.yaml 完全对应其中research_brief方法使用call: crewroute_followup与write_followup方法使用call: agent正是“Crew 做协同、Agent 做单点判断/写作”的组合示范。五、显式接线start、listen、router 与 emit这一节规定了 Flow 事件模型的核心规则是声明式 Flow 与 Python 装饰器写法差异最大、也最容易写错的部分state是初始共享数据形状。动作结果不会自动合并回state——这是与直觉最容易冲突的一点跨方法传值必须显式走outputs方法结果通过outputs.method_name读取且必须在该方法可以运行之后listen的目标是方法名或 router 发出的事件名方法绝不能监听自己的方法名——包括listen的值恰好是与其方法名相同的路由标签例如方法create_video上写listen: create_video方法名与发出事件名共享同一个命名空间不要用同一个字符串既当方法名又当listen目标当一个方法要在多个命名分支间选择时用router: trueemitrouter 动作必须恰好返回一个发出事件名字符串不能返回 JSON、列表或解释文字start: true标记唯一入口。对于“用 Agent 当路由”的场景文档给出了可直接复用的 goal 写法Return exactly one bare value: approved, rejected, or needs_review. Do not include explanation.并且明确路由如果能用计算得出优先用call: expression而不是 Agent——确定性路由不该消耗 LLM 调用。六、CEL 与动态值${...} 插值的精确语义CELCommon Expression Language是 Flow 中“读取数据、做小决定”的表达式语言更大的工作或有副作用的操作交给 agent 和 crew。文档对表达式形式的规定可以归纳为一张规则表场景正确写法说明原始 CEL写在expr里不要用${...}包裹原始 CEL映射字符串中读 Flow 数据Ticket: ${state.ticket_id}字面量文本留在${...}外直接插值输入数据state如state.ticket.subject已完成方法结果outputs.step_name如outputs.classify_ticket值本身就是单个${...}domains: ${state.domains}结果保留原始类型数字、布尔、对象、列表字符串里还有其他文本最终值为文本非文本值会被序列化为 JSONnull变成空文本两个标准示例# 混排文本与 Flow 数据 query: News about ${state.topic}# 保留列表 / 数字类型 domains: ${state.domains} limit: ${state.limit}Crew 侧还有一套独立的{name}占位符插值不是 CELCrew 文本用{name}占位符引用 crew inputs例如Research {topic}crew inputs 只有在 agent 或 task 文本中引用了对应{name}占位符时才真正成为提示词的一部分——传了一个没有任何占位符引用的输入等于没有“grounding”事实锚定若 Crew 确实需要某字段就把占位符写进 agent 的goal、task 的description或expected_output。关于取值的具体规则还包括Agent 需要多个字段时写一个带标签和分隔符的文本值例如Ticket ID: ${state.ticket_id}; Message: ${state.message}Crew 动作级inputs才是真正的 Crew kickoff 输入运行期数据用${...}从state/outputs取仅靠inputs不构成 grounding必须配合占位符Crew 输出是对象取文本用${outputs.research_brief.raw}结构化输出用${outputs.research_brief.json_dict.field}或${outputs.research_brief.pydantic.field}不要把整个 Crew 输出塞给 Agent 输入如${outputs.research_brief}是错误的Agent 输出也可能是对象${outputs.classify_ticket.raw}或${outputs.classify_ticket.pydantic.category}with.inputsCrew 定义内只用于静态默认值agent 动作的with.input是该 agent 的单一输入值。七、“Do Not”清单十一条高频错误红线AGENTS.md 用一整节列出禁止项这些基本都对应真实校验失败或行为异常逐条核对价值很高不要发明 Flow 声明形状之外的顶层键不要使用声明 schema 之外的字段不要在一个方法的do下放多个动作不要让do变成列表不要用 CEL 的在动作映射里拼接文本——保持文本字面量动态值各自用${...}插入不要在some_method可以运行之前引用outputs.some_method不要把方法的listen设为自己的方法名含相同的路由标签如方法create_video上listen: create_video不要用同一个字符串同时作为方法的listen目标与方法名不要在没有router: true的情况下使用emit不要指望 crew 动作级inputs单独完成 grounding——没有匹配占位符的输入对提示词而言基本无效不要在精确性重要时让 Agent“自行推断缺失事实”应要求它把缺失的日期、金额、报价、日志或约束标记为 unknown不要在调用方不会消费流式结果时设置config.stream: true——常规生成的 Flow 与 CLI 冒烟测试都应省略它。八、完整示例Crew 研究 路由式跟进文档给出的主示例是一个“Crew 研究评审 路由式跟进”的 Flow展示了 state 建模、crew 动作、router 方法与分支 agent 的完整组合该示例与仓库中 flow_definition_example.yaml 一致schema: crewai.flow/v1 name: ResearchReviewFlow state: type: json_schema json_schema: type: object properties: topic: type: string audience: type: string required: - topic - audience default: topic: AI agent orchestration audience: platform engineering leaders methods: research_brief: start: true do: call: crew with: agents: researcher: role: Research analyst goal: Research {topic} for {audience} backstory: Expert at concise technical research. reviewer: role: Strategy reviewer goal: Decide whether the research needs an executive follow-up backstory: Experienced at reviewing technical briefs for leaders. tasks: - name: research_task description: Research {topic} for {audience}. expected_output: Key findings and tradeoffs. agent: researcher - name: review_task description: Review the research and decide if an executive follow-up is needed. expected_output: A brief review ending with needs_followup: true or needs_followup: false. agent: reviewer inputs: topic: Default topic audience: Default audience inputs: topic: ${state.topic} audience: ${state.audience} route_followup: listen: research_brief router: true emit: - followup - done do: call: agent with: role: Follow-up router goal: Return exactly one bare value: followup or done. Do not include explanation. backstory: Skilled at routing reviewed research briefs. input: Reviewed research: ${outputs.research_brief.raw} write_followup: listen: followup do: call: agent with: role: Executive communications specialist goal: Draft a concise executive follow-up from the reviewed research backstory: Writes crisp follow-ups for technical leaders. input: ${outputs.research_brief.raw}这个示例几乎把前述全部规则串了一遍值得逐行对照state用json_schema内联声明required明确列出topic/audiencedefault仅提供缺省值二者不互相替代research_brief是start: true的唯一入口call: crewCrew 定义内inputs是静态默认而动作级inputs用${state.topic}把运行期值真正注入 kickoff——同时Research {topic} for {audience}中的{name}占位符完成了 groundingroute_followup是router: true方法emit声明了followup/done两个合法分支其 agent 的 goal 严格限定“只返回一个裸值”它读取的是${outputs.research_brief.raw}对象输出的文本视图write_followup监听的是事件名followup而非方法名——这正是“事件与方法共享命名空间、分支方法挂事件名”的标准接法done分支没有后续方法流程自然终止。九、字段级 API 参考这一节按文档附录顺序整理全部字段编写声明时可直接对照。9.1 Flow 顶层定义字段必填说明schema可选默认crewai.flow/v1必须为crewai.flow/v1手写声明应显式包含name必填唯一 Flow 名称用于日志、事件与追踪description可选默认null人类可读的摘要state必填初始状态与执行期更新的状态契约config可选可序列化的 Flow 级执行配置methods必填方法名 → 方法定义的映射9.2 JSON Schema Statestate[typejson_schema]字段必填说明type可选默认json_schema固定为json_schema表示内联 JSON Schema 作为状态契约json_schema必填用于校验和文档化状态的 JSON Schema必填字段用其中的required数组声明default可选默认null初始化 Flow 状态的默认值默认值不等于 schema 必填9.3 Methodmethods.name字段必填说明description可选默认null方法的人类可读摘要do必填方法执行时运行的单个动作对象start可选默认null标记入口使用truelisten可选默认null在某个上游方法或 router 事件之后运行router可选默认false方法输出是否作为下一个事件名router 必须返回单个事件名字符串emit可选默认null该方法可能发出的事件声明列表事件名应唯一且不与方法名冲突9.4 Action按call判别的联合类型允许的三种形状call: crew、call: agent、call: expression。Crew Actionmethods.name.do[callcrew]字段必填说明call必填判别字段固定crewwith必填内联 Crew 定义inputs可选默认null传给 Crew 的运行期输入用${...}插入 Flow 值并在 agent/task 文本中以{name}引用如{topic: ${state.topic}}Crew Definition...do[callcrew].with字段必填说明agents必填按名称索引的内联 agent 映射tasks必填有序任务列表inputs可选静态默认输入作为{name}占位符参与插值运行期值优先用动作级inputsCrew Agent Definition...with.agents.name字段必填说明role/goal/backstory必填三者的插值都使用{name}占位符不是 CELsettings可选透传给 loader 的附加设置如{llm: openai/gpt-4o-mini}llm可选默认null模型字符串或内联 LLM 配置对象如{max_tokens: 4096, model: openai/gpt-4o-mini}planning_config可选默认null计划配置max_attempts限制任务执行前计划修正次数allow_delegation可选默认null允许 agent 之间委派与提问max_iter可选默认null单个 agent 执行任务的最大迭代次数max_rpm可选默认nullagent 执行时每分钟最大请求数max_execution_time可选默认nullagent 执行任务的超时秒数tools可选默认null工具引用或序列化定义字符串引用可用 CrewAI 工具名、custom:name或module:Class全限定引用apps可选默认null平台应用如gmail或slack/send_messagemcps可选默认nullMCP 服务器引用或配置支持 HTTPS URL、集成 slug、#tool_name后缀或内联对象配置LLM Definition字段必填说明model必填模型标识如openai/gpt-4o-minimax_tokens可选默认null输出 token 上限为 null 时由 provider 默认值生效Crew Task Definition...with.tasks[]字段必填说明description必填任务指令支持{name}插值expected_output必填期望输出描述支持{name}插值name可选默认null任务名agent可选默认null承接该任务的 crew agent 名称Agent Actionmethods.name.do[callagent]字段必填说明call必填固定agentwith必填单个 Agent 定义输入放在with.inputagent 动作不支持动作级inputsAgent Definition...do[callagent].with字段集合与 Crew Agent Definition 相同role/goal/backstory必填settings、llm、planning_config、allow_delegation、max_iter、max_rpm、max_execution_time、tools、apps、mcps可选另加一个必填字段字段必填说明input必填Agent 提示词模板用${...}插入 Flow 值如Ticket: ${state.ticket_id}Expression Actionmethods.name.do[callexpression]字段必填说明call必填固定expressionexpr必填针对 state、outputs 与局部上下文求值的 CEL 表达式9.5 Configconfig字段默认说明tracingnull覆盖 Flow 追踪省略时使用执行默认值streamfalse是否发出流式事件仅在调用方会消费流时设置memorynull传给 Flow 执行的可序列化记忆配置input_providernull用于提供初始 state 的 provider 键suppress_flow_eventsfalse为本定义禁用 Flow 事件发出max_method_calls100单次 kickoff 允许的最大方法执行次数defer_trace_finalizationfalse延迟 trace 终结允许调用方稍后完成追踪checkpointnull检查点配置true表示使用默认检查点9.6 跨字段规则Cross-Field Rules每个方法恰好一个do动作对象、一个call判别值listen目标位于“方法名 router 事件名”的同一命名空间中方法不能监听自己的方法名router 方法的结果必须命中一个已声明的emit值Crew 动作级inputs即 Crew kickoff 输入运行期值在那里使用 CEL 包裹字符串Crew agent/task 插值使用来自求值后 crew inputs 的{name}占位符Agent 的with.input必须是文本——用${outputs.method_name.raw}或${outputs.method_name.json_dict.summary}这类文本字段。十、源码纵深CLI 模板是参数化 Skill 模板的“精简变体”把 AGENTS.md 放回仓库语境中看会发现它并不是孤立文本。在 lib/crewai/src/crewai/flow/templates/flow_definition_skill.md.j2 中存在一份 Jinja2 模板内容与 AGENTS.md 同源但通过特性开关参数化——例如include_non_linear_flows允许多入口与非线性listenlisten支持and/or组合、include_tool_actioncall: tool打包确定性工作、include_script_actioncall: script内联可信 Python明确标注“脚本不做沙箱”、include_each_actioncall: each逐项重复子管道、include_hitlhuman_feedback人工检查点等。从源码结构看CLI 项目模板中的 AGENTS.md 正是该参数化模板在“仅 expression / agent / crew 三种动作、单入口”配置下实例化出的保守版本——这也是为什么 CLI 模板写死“恰好一个start: true方法”而参数化版本在非线性 Flow 下会放宽为“至少一个”。声明的加载与执行侧在 run_declarative_flow.py 中load_declarative_flow负责把 flow.yaml/JSON 定义加载为 Flowcrewai run会优先检测当前是否为声明式 Flow 项目环境is_declarative_flow_project_env并走声明式执行路径crewai flow plot则可对定义做可视化。声明解析与校验的库侧实现见 flow_definition.py相关行为有 test_flow_definition.py、test_flow_from_definition.py 等测试覆盖。十一、实践要点小结把 AGENTS.md 的规则浓缩成可执行的写作纪律state 先行json_schema内联、required显式、default只补缺省单动作原则每个方法一个do按“能算则 expression、单点 AI 用 agent、协同用 crew”的梯度选型显式接线outputs.method_name读结果、listen挂上游、router 方法router: trueemit声明分支、分支方法监听事件名两套插值体系不混用Flow 层用${...}CELCrew 层用{name}占位符且后者必须被 agent/task 文本实际引用才生效产出前自检逐个核对listen、emit、outputs.*引用与方法名/事件名命名空间冲突省略可选配置stream、memory等字段除非确有需要否则交给默认值。遵循这套规范写出的crewai.flow/v1声明既能通过 CLI 项目的声明式校验并被crewai run直接执行也能作为 AI 协作编辑 Flow 的稳定契约——这正是 AGENTS.md 在 CrewAI 声明式 Flow 工作流中的定位。【免费下载链接】crewAIFramework for orchestrating role-playing, autonomous AI agents. By fostering collaborative intelligence, CrewAI empowers agents to work together seamlessly, tackling complex tasks.项目地址: https://gitcode.com/GitHub_Trending/cr/crewAI创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考