ChatDev 工作流编排完全指南:YAML 结构、节点、边条件与动态执行实战 ChatDev 工作流编排完全指南YAML 结构、节点、边条件与动态执行实战【免费下载链接】ChatDevChatDev 2.0: Dev All through LLM-powered Multi-Agent Collaboration项目地址: https://gitcode.com/GitHub_Trending/ch/ChatDev本指南基于 ChatDev 2.0 开源仓库的docs/user_guide/zh/workflow_authoring.md展开系统讲解如何通过 YAML 声明式配置构建与调试多 Agent 协作 DAG从DesignConfig顶层结构、变量解析优先级、七类节点类型到 Provider 对接、条件边与 Payload Processor再到 Map/Tree 动态执行、设计模板导出与三种运行方式。读完本文你将能够独立编写一个可运行的多 Agent 工作流文件并能结合源码快速定位配置错误与运行时问题。1. 必备背景与前置知识在开始编写工作流之前建议先熟悉以下仓库结构它们是与工作流编排直接相关的核心区域yaml_instance/存放可直接运行的工作流示例如 net_example.yaml、demo_human.yaml、demo_loop_counter.yaml 等是学习写法的第一手素材。yaml_template/design.yaml由工具自动生成的基准模板实时反映GraphDefinition的全部字段定义是编写配置时最可靠的字段字典。entity/configs/配置 dataclass 的源码定义其中graph.py、node/、edge/与各 YAML 文件一一对应。例如GraphDefinition定义在 entity/configs/graph.py边配置定义在 entity/configs/edge/edge.py。同时需要了解两个机制FIELD_SPECS每种配置 dataclass 内部都带有一份FIELD_SPECS字典见 field_specs.md描述每个字段的名称、类型、默认值、必填性与说明。它是前端动态表单和 Schema API 的数据来源。Schema API前端与 IDE 可通过POST /api/config/schema动态查询任意配置块的字段结构契约详见 config_schema_contract.md也可以在 CLI 中用--inspect-schema快速导出查看见第 9 节。基础节点类型包括model已演进为agent、python、human、subgraph、passthrough、literal以及控制型节点loop_counter第 3 节会逐一展开。2. YAML 顶层结构DesignConfig所有工作流文件都遵循DesignConfig根结构只包含三个顶层键version、vars、graph。该约束在 entity/configs/graph.py 的DesignConfig定义中得到体现其中graph是唯一必填段落。下面是一个精简但可直接运行的示例结构节选自yaml_instance/net_example.yamlversion: 0.4.0 vars: BASE_URL: https://api.example.com/v1 API_KEY: ${API_KEY} graph: id: paper_gen description: 文章生成与润色 log_level: INFO is_majority_voting: false initial_instruction: | 这是一个文章生成与润色流程请输入一个词语或短句作为任务提示。 start: - Article Writer end: - Article Writer nodes: - id: Article Writer type: agent config: provider: openai base_url: ${BASE_URL} api_key: ${API_KEY} name: gpt-4o params: temperature: 0.1 - id: Human Reviewer type: human config: description: 请审阅文章如接受结果请输入 ACCEPT 结束流程否则输入修改意见。 edges: - from: Article Writer to: Human Reviewer - from: Human Reviewer to: Article Writer condition: type: keyword config: none: - ACCEPT case_sensitive: false2.1 version 字段version是配置版本号缺省为0.0.0见 entity/configs/graph.py。当GraphDefinition的 Schema 发生破坏性调整时它用于与前端模板如frontend/public/design_0.4.0.yaml和迁移脚本对齐。日常编写新工作流时一般保持与当前模板一致的版本即可。2.2 vars 字段与 ${VAR} 占位符vars是根级键值对可在任意字符串字段中使用${VAR}占位引用。若占位符在vars中未命中则回退到同名环境变量。底层解析逻辑在 utils/vars_resolver.py 的PlaceholderResolver中实现纯占位符字符串如${API_KEY}会被直接替换为变量值混在普通文本中的占位符如https://api.example.com/${VERSION}/v1会做子串级替换解析器会检测占位符循环引用如A: ${B}、B: ${A}抛出ConfigError。一个重要的约束是vars只能在 DesignConfig 根级声明。GraphDefinition.from_dict会显式拒绝在graph或节点下声明非空vars并抛出错误见 entity/configs/graph.py。2.3 环境变量与 .env 文件系统支持在 YAML 配置中使用${VAR}语法引用变量可用于配置中的任意字符串字段常见用途包括API 密钥api_key: ${API_KEY}服务地址base_url: ${BASE_URL}模型名称name: ${MODEL_NAME}系统在解析配置时会自动加载项目根目录下的.env文件若存在。其实现位于 utils/env_loader.pyload_dotenv_file()每个进程只加载一次.env逐行解析KEYVALUE自动跳过注释#开头与空行关键点是它使用os.environ.setdefault()因此.env中的值不会覆盖已存在的环境变量。变量解析的优先级如下优先级来源说明1最高vars中显式定义的值YAML 文件中直接声明的键值对2系统/Shell 环境变量如通过export设置的值3最低.env文件中的值仅当环境变量尚未存在时生效[!TIP].env文件不会覆盖已存在的环境变量。这意味着您可以在.env中定义默认值同时通过export或部署平台的环境变量配置来覆盖它们。[!WARNING] 若占位符引用的变量在上述三个来源中均未定义配置解析时将抛出ConfigError并指明出错路径。具体地PlaceholderResolver._lookup会抛出Unresolved placeholder ${NAME}并携带精确的配置路径见 utils/vars_resolver.py。2.4 graph 段落graph是唯一必填段落映射到GraphDefinitiondataclassentity/configs/graph.py。它包含基础元信息id必填图形标识符仅允许字母数字、下划线与连字符不能包含空格description对人类可读的工作流目标描述会展示在 UI/模板中log_level运行期日志级别默认DEBUG可选值由LogLevel枚举定义is_majority_voting是否多数投票图默认falseinitial_instruction面向用户的图级初始指令organization可选组织名当前在 FIELD_SPECS 中处于注释状态。执行控制start/end入口与出口节点 ID 列表。系统会在启动时执行start中的节点end用于收集最终图输出它在子图中常见是一个有序列表——前面的节点优先检查第一个有输出的成为图输出否则继续向后查找nodes、edges节点与边列表分别与 entity/configs/node/*.py 与 entity/configs/edge/edge.py 同步。所有 Provider、模型、Tooling 配置都挂在node.config内不再在顶层维护providers表。共享资源memory定义 Memory store 列表供模型节点的config.memories引用。调度器在GraphDefinition.validate()中会校验节点引用是否在graph.memory中声明未声明的引用会抛出ConfigError见 entity/configs/graph.py。GraphDefinition.from_dict在解析时会做多项结构校验entity/configs/graph.py节点 ID 不能重复start中的节点必须存在于nodes中每条边的from/to引用的节点必须存在graph.memory中的 store 名称不能重复。Schema 参考yaml_template/design.yaml会实时反映GraphDefinition字段。建议在修改配置后运行python -m tools.export_design_template或调用 Schema API 校验。进一步阅读field_specs.md字段精细描述、runtime_ops.md运行期可观测性、yaml_template/design.yaml自动生成的基准模板。3. 节点类型速览节点通过type字段选择实现type的合法值由节点注册中心动态决定前端下拉列表与 Schema API 会自动展示对应summary。注册中心的实现见 runtime/node/registry.py其field_specs()会把注册的所有节点类型及其描述注入Node.type的枚举选项中见 entity/configs/node/node.py。下表汇总了七类核心节点类型描述关键字段详细文档agent调用 LLM支持工具、记忆、thinkingprovider,model,prompt_template,tooling,thinking,memoriesagent.mdpython执行 Python 代码脚本或指令共享code_workspace/entry_script,inline_code,timeout,envpython.mdhuman在 Web UI 阻塞等待人工输入prompt,timeout,attachmentshuman.mdsubgraph嵌入子 DAG复用复杂流程graph_path或内联graphsubgraph.mdpassthrough透传节点默认只传递最后一条消息可传递所有信息用于上下文过滤和图结构优化only_last_messagepassthrough.mdliteral被触发时输出固定文本消息忽略输入content,roleuser/assistantliteral.mdloop_counter限制环路执行次数的控制节点max_iterations,reset_on_emit,messageloop_counter.md3.1 Node 通用字段每个节点都继承自Nodedataclassentity/configs/node/node.py除id、type、config三个必填字段外还有以下通用可选字段description节点说明显示在控制台/日志中log_output是否记录该节点的输出内容默认true设false可避免敏感输出落日志context_window节点执行时可访问的上下文消息数。0表示清空除keep_messageTrue之外的所有上下文-1表示不限制其他正整数表示在保留 kept 消息之外保留的上下文条数见 entity/configs/node/node.py 的clear_input实现。详细字段可在前端使用 Schema APIPOST /api/config/schema动态查询也可参照entity/configs/中同名 dataclass。4. Provider 与 Agent 设置Agent 节点的配置对象是AgentConfigentity/configs/node/agent.py核心字段provider已注册 Provider 的名称openai、gemini等决定底层客户端适配器。该字段缺省时使用globals.default_provider如openai。从源码看AgentConfig.field_specs()会动态拉取 provider 注册表生成枚举选项并优先把openai作为默认值entity/configs/node/agent.py。model字段对应配置中的name具体模型名如gpt-4o、gemini-2.0-flash-001必填且不能为空字符串。base_url、api_key支持${VAR}占位便于跨环境复用。base_url留空则使用 Provider 内置端点。role系统提示词System Prompt。params调用参数如temperature、max_tokens、top_p等原样透传给 Provider。input_modemessages默认或prompt。retry自动重试策略AgentRetryConfig见下文。tooling、thinking、memories、skills分别绑定工具、思维链、记忆与技能配置。对接多个 Provider 时可在 workflow 层设置globals{ default_provider: ..., retry: {...} }若 dataclass 支持。4.1 AgentRetryConfig自动重试AgentRetryConfigentity/configs/node/agent.py提供细粒度的自动重试控制字段默认值说明enabledtrue是否启用自动重试max_attempts5总尝试次数首次调用 重试min_wait_seconds/max_wait_seconds1.0/6.0退避等待的上下限retry_on_status_codes[408, 409, 425, 429, 500, 502, 503, 504]触发重试的 HTTP 状态码retry_on_exception_typesRateLimitError、APITimeoutError等 13 类触发重试的异常类型名大小写不敏感non_retry_exception_types[]永不重试的异常类型retry_on_error_substringsrate limit、timeout等异常消息中包含的子串should_retry()会遍历整条异常链含__cause__、__context__与异常组依次按非重试异常类型 → 重试异常类型 → 状态码 → 错误消息子串四层规则决策entity/configs/node/agent.py。max_wait_seconds小于min_wait_seconds时配置解析会直接报错。4.2 Gemini Provider 配置示例以 Gemini 为例展示多模态 Provider 的配置方式model: provider: gemini base_url: https://generativelanguage.googleapis.com api_key: ${GEMINI_API_KEY} name: gemini-2.0-flash-001 input_mode: messages params: response_modalities: [text, image] safety_settings: - category: HARM_CATEGORY_SEXUAL threshold: BLOCK_LOWERGemini Provider 支持多模态输入图片/视频/音频会自动转换为 Part并支持function_calling_config来控制工具调用行为。其客户端适配器实现在 runtime/node/agent/providers/gemini_provider.pyProvider 注册表与适配器基类见 runtime/node/agent/providers/builtin_providers.py 与 runtime/node/agent/providers/base.py。5. 边与条件边由EdgeConfig描述entity/configs/edge/edge.py。YAML 中源/目标字段是from/to源码 dataclass 内部映射为source/target。基本边- source: plan target: execute5.1 边的完整字段除from/to外边还支持以下控制字段字段默认值说明triggertrue该边能否触发后继节点conditiontrue恒真边条件type config结构carry_datatrue是否向后继节点传递数据keep_messagefalse是否在目标节点始终保留这条消息输入而不被清空clear_contextfalse传递新负载前清空所有非 keep 的上下文消息clear_kept_contextfalse传递新负载前清空标记为 keep 的消息processnull条件成立后的 Payload Processor见 5.4 节dynamicnull边级动态执行配置见 7.4 节5.2 条件边function 类型edges: - source: router target: analyze condition: type: function config: name: should_analyze # functions/edge/should_analyze.pycondition.type的合法值由后端注册中心决定。注册函数为register_edge_conditionruntime/edge/conditions/registry.py内置两种类型runtime/edge/conditions/builtin_types.pyfunction调用functions/edge/*.py中注册的 Python 条件函数默认函数名为true恒真keyword无需编写 Python 函数的声明式关键词/正则条件。EdgeConditionConfig.from_dict有很灵活的旧写法兼容逻辑entity/configs/edge/edge_condition.pycondition直接省略 → 等价于{type: function, config: {name: true}}恒真condition: true→ 同上condition: false→ 等价于{name: always_false}恒假condition: some_func字符串→ 等价于{type: function, config: {name: some_func}}即文档提到的直接填写函数名字符串的旧写法。schema 会自动在前端下拉列表中展示每个条件类型的summary描述。错误处理当condition抛错时调度器会记录错误并抛出WorkflowExecutionError导致该分支通常是整个运行终止后继节点不会继续执行。5.3 keyword 条件声明式关键词匹配keyword类型无需写 Python 函数配置类是KeywordEdgeConditionConfigentity/configs/edge/edge_condition.pyedges: - from: review to: finalize condition: type: keyword config: any: [FINAL, APPROVED] none: [RETRY] case_sensitive: false # 默认为 true字段语义any命中任意关键词即返回 Truenone命中任意排除词即返回 False优先级最高regex命中任意正则即返回 Truecase_sensitive是否区分大小写默认truedefault无任何匹配时的返回值默认false。注意any/none/regex三者至少提供一个否则解析报错entity/configs/edge/edge_condition.py。运行时逻辑由 runtime/edge/conditions/keyword_manager.py 执行。5.4 边级 Payload Processor场景当条件成立后希望先处理一下消息例如根据正则提取得分、只保留结构化字段或者调用自定义函数对文本重写。YAML 字段在任意边上新增process结构与condition相同type config目前内置regex_extract基于 Python 正则。支持pattern、group名称或序号、modereplace_content、metadata、data_block、multiple、on_no_matchpass/default/drop等字段。配置类为 entity/configs/edge/edge_processor.py 中的RegexEdgeProcessorConfig除文档提到的字段外还支持template输出模板用{match}占位、multiline、dotall正则标志。function调用functions/edge_processor/*.py中的处理函数。函数签名为def foo(payload: Message, **kwargs) - Message | None。现在 Processor 接口已标准化kwargs中包含了context: ExecutionContext可访问当前执行上下文。运行时行为Processor 在条件通过且carry_datatrue时执行若返回None该边不会触发也不会向后继节点发送输入。日志中会在EDGE_PROCESS事件里显示process_label、process_type便于排查。示例——从 reviewer 输出中正则提取质量评分写入元数据edges: - from: reviewer to: qa process: type: regex_extract config: pattern: Score\\s*:\\s*(?Pscore\\d) group: score mode: metadata metadata_key: quality_score case_sensitive: false on_no_match: default default_value: 0Processor 的注册与分发机制与条件类似register_edge_processorruntime/edge/processors/registry.py内置regex_extract与function两种类型runtime/edge/processors/builtin_types.py。6. 模型节点高级特性Agent 节点在基础 LLM 调用之上还可以叠加三类高级能力Tooling在AgentConfig.tooling中配置支持函数工具Function Tool、MCP 本地/远程工具等详见 Tooling 模块。节点侧的工具汇总逻辑见 entity/configs/node/node.py 的tools属性运行时由 runtime/node/agent/tool/tool_manager.py 管理。Thinking在AgentConfig.thinking中开启如chain-of-thought、reflection详见 entity/configs/thinking.py。运行时的思维链管理见 runtime/node/agent/thinking/。MemoriesAgentConfig.memories绑定MemoryAttachmentConfig引用graph.memory中声明的 store详见 Memory 模块。内置 store 实现见 runtime/node/agent/memory/builtin_stores.pysimple、file、mem0、embedding 等。7. 动态执行Map/Tree节点配置新增同级字段dynamic用于启用并行处理或 Map-Reduce 模式。动态配置的基础类定义在 entity/configs/dynamic_base.py。7.1 核心概念Map 模式type: map扇出Fan-out。将 List 输入拆分为多个单元并行执行输出List[Message]结果打平。Tree 模式type: tree扇出与归约Fan-out Reduce。将输入拆分并行执行后按group_size分组递归归约最终输出单个结果如总结的总结。Split 策略定义如何将上一节点的输出或当前输入拆分为并行单元。7.2 Split 策略的三种内置类型SplitConfigentity/configs/dynamic_base.py支持三种拆分策略split.type说明必填字段message每条输入消息成为一个执行单元默认无额外配置无regex按正则匹配切分内容每个匹配成为一个单元config.patternjson_path从 JSON 数组按点号路径取元素每个元素成为单元config.json_pathregex拆分还支持group捕获组、case_sensitive、multiline、dotall、on_no_matchpass/empty等参数message类型是唯一可以不提供config的拆分方式。7.3 配置结构nodes: - id: Research Agents type: agent # 常规配置作为并行单元的模板 config: provider: openai model: gpt-4o prompt_template: Research this topic: {{content}} # 动态执行配置 dynamic: type: map # 拆分策略 (仅首层有效) split: type: message # 可选: message, regex, json_path # pattern: ... # regex 模式下必填 # json_path: $.items[*] # json_path 模式下必填 # 模式专属配置 config: max_parallel: 5 # 控制并发度MapDynamicConfig.max_parallel默认10TreeDynamicConfig的group_size默认3且必须 ≥ 2否则报错、max_parallel默认10entity/configs/dynamic_base.py。7.4 Tree 模式示例适用于长文本分段摘要等场景dynamic: type: tree split: type: regex pattern: (?s).{1,2000}(?:\\s|$) # 每 2000 字符切分 config: group_size: 3 # 每 3 个结果归约为 1 个 max_parallel: 10该模式会自动构建多层级执行树直到结果数量归约为 1。split 配置与 map 模式一致。7.5 边级动态执行值得注意的演进是在当前仓库中动态执行配置既可以放在节点同级上文写法也可以放在边级EdgeConfig.dynamic见 entity/configs/edge/edge.py。边级dynamic字段同样支持map/tree两种模式当配置在边上时目标节点会根据经过该边的负载拆分结果被动态展开见 entity/configs/edge/dynamic_edge_config.py 的DynamicEdgeConfig。两种位置的动态执行共用同一套SplitConfig、MapDynamicConfig、TreeDynamicConfig基础类避免循环依赖源码注释明确说明这一设计意图。从节点配置源码的注释可以看到节点级 dynamic 已逐步迁移到边级entity/configs/node/node.py编写新工作流时建议优先使用边级写法并以 yaml_template/design.yaml 当前生成的字段为准。8. 设计模板导出任意修改 Config/FIELD_SPECS 后运行python -m tools.export_design_template \ --output yaml_template/design.yaml \ --mirror frontend/public/design_0.4.0.yaml命令会读取注册表节点、memory、tooling 等与FIELD_SPECS自动生成 YAML 模板与前端镜像。实现见 tools/export_design_template.py。更新后请提交模板文件并通知前端刷新静态资源。9. CLI / API 运行方式有三种方式运行工作流官方建议优先使用 Web UIWeb UI访问前端页面 → 选择 YAML → 填写运行参数 → 启动 → 在面板监控。HTTPPOST /api/workflow/executepayload 包含session_name、graph_path或graph_content、task_prompt、可选的attachments以及log_level默认INFO支持INFO或DEBUG。CLIpython run.py --path yaml_instance/demo.yaml --name test_run执行前可设置TASK_PROMPT环境变量或在 CLI 提示中输入。CLI 入口实现见 run.py它支持以下参数参数默认值说明--pathyaml_instance/net_loop_test_included.yaml工作流文件路径--nametest_project项目名称--fn-modulenull提供边条件辅助函数的可选模块--inspect-schemafalse输出配置 Schema 后退出--schema-breadcrumbsnull用 JSON 数组描述 Schema 路径如[{node:DesignConfig,field:graph}]--attachment[]附加到初始用户消息的文件路径可重复运行结果输出在WareHouse/目录下。服务端 HTTP 执行接口的实现见 server/routes/execute.py 与 server/services/workflow_run_service.py。10. 调试建议使用 Web UI 的上下文快照或 WareHouse 中的context.json检查节点输入输出。注意所有节点输出现已统一为List[Message]结构。结合 config_schema_contract.md 的 breadcrumbs 功能用 CLI 快速查看字段定义python run.py --inspect-schema \ --schema-breadcrumbs [{node:DesignConfig,field:graph}]若 YAML 占位符缺失解析阶段会抛出ConfigError在 UI/CLI 中都可看到明确路径。图级校验错误重复节点 ID、start 节点未定义、边引用未知节点、memory 引用未声明等同样会在加载阶段以ConfigError形式暴露并携带精确的配置路径entity/configs/graph.py。边条件异常会在运行时抛出WorkflowExecutionError日志中记录错误与条件类型便于定位具体是哪个边上的判断逻辑出问题。配置的最终字段语义以 yaml_template/design.yaml 为准它是GraphDefinition及各节点/边配置的实时快照。【免费下载链接】ChatDevChatDev 2.0: Dev All through LLM-powered Multi-Agent Collaboration项目地址: https://gitcode.com/GitHub_Trending/ch/ChatDev创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考