ChatDev Workflow Authoring 指南:基于 YAML 编写与调试 DevAll 多智能体 DAG
2026/9/10 2:58:22 网站建设 项目流程

ChatDev Workflow Authoring 指南:基于 YAML 编写与调试 DevAll 多智能体 DAG

【免费下载链接】ChatDevChatDev 2.0: Dev All through LLM-powered Multi-Agent Collaboration项目地址: https://gitcode.com/GitHub_Trending/ch/ChatDev

导读

本文是 ChatDev 项目中docs/user_guide/en/workflow_authoring.md的深度技术指南,面向需要为 DevAll 多智能体协作系统编写、校验与调试工作流的开发者。文章以 YAML 工作流文件为骨架,完整覆盖顶层结构与变量解析、八种内置节点类型、Provider 与 Agent 配置、边条件与负载处理器、Map/Tree 动态执行、设计模板导出以及 CLI/HTTP 运行路径,并逐项对照entity/runtime/utils/等目录下的源码实现进行佐证。读完本文,你将能够独立编写一份可运行的DesignConfig工作流 YAML,理解占位符解析优先级与节点上下文语义,并掌握用 Schema API、CLI 与 Web UI 快速定位配置错误的方法。

1. 前置准备与阅读地图

编写工作流之前,建议先熟悉以下仓库布局:

  • yaml_instance/:存放可直接运行的示例工作流(如 net_example.yaml、demo_*.yaml系列);
  • yaml_template/design.yaml是由工具导出的最新配置模板,与GraphDefinition数据类保持同步;
  • entity/configs/:全部配置数据类(DesignConfigGraphDefinitionNodeEdgeConfig及各节点配置)的定义所在;
  • entity/config_loader.py:YAML 文件到DesignConfig的加载与校验入口。

如果你依赖前端/IDE 的动态表单,建议同时阅读 field_specs.md(字段目录)与 config_schema_contract.md(Schema API 契约)。另外,本文所属的完整用户指南目录见 index.md,节点级细节可继续阅读 nodes/ 下的分节点文档。

2. YAML 顶层结构:version、vars、graph

每个工作流文件都遵循DesignConfig根结构,且只包含三个顶层键versionvarsgraph。下面的示例改编自 net_example.yaml,可直接运行:

version: 0.4.0 vars: BASE_URL: https://api.example.com/v1 API_KEY: ${API_KEY} graph: id: paper_gen description: Article generation and refinement log_level: INFO is_majority_voting: false initial_instruction: | Provide a word or short phrase and the workflow will draft and polish an article. 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: Review the article. Type ACCEPT to finish; otherwise provide revision notes. edges: - from: Article Writer to: Human Reviewer - from: Human Reviewer to: Article Writer condition: type: keyword config: none: - ACCEPT case_sensitive: false

2.1 version:配置版本

version是可选配置版本号,缺省时默认0.0.0(见 graph.py 中optional_str(mapping, "version", path) or "0.0.0")。每当 graph.py 中的 schema 发生变化、需要模板或迁移更新时,应递增该版本号。

2.2 vars:全局变量与${VAR}占位符解析

vars是根级键值映射,可被文件中任意字符串字段以${VAR}语法引用。常见用途包括:

  • API Keysapi_key: ${API_KEY}
  • 服务地址base_url: ${BASE_URL}
  • 模型名称name: ${MODEL_NAME}

解析机制由 vars_resolver.py 实现:PlaceholderResolver递归遍历整个配置的字符串、列表与映射,对\$\{([A-Za-z0-9_]+)\}占位符进行替换,并支持纯占位符替换与字符串内嵌替换两种形式。解析过程会检测占位符循环引用(如A -> B -> A),一旦发现立即抛出ConfigError

需要注意两点约束:

  • GraphDefinition.from_dict会拒绝嵌套vars(见 graph.py:raise ConfigError("vars are only supported at DesignConfig root", ...)),所以vars只能出现在文件顶部;
  • 加载流程(config_loader.py)会先调用load_dotenv_file()加载项目根目录的.env文件,再执行占位符解析。

环境变量与.env文件解析优先级

系统在解析配置时自动加载项目根目录的.env文件(若存在),变量解析优先级如下:

优先级来源说明
1(最高)vars中显式声明的值直接写在 YAML 文件中的键值对
2系统/Shell 环境变量通过export或系统配置设置的值
3(最低).env文件中的值仅当变量不存在时才生效

[!TIP].env文件不会覆盖已存在的环境变量。这允许你在.env中定义默认值,同时通过export或部署平台配置覆盖它们。

[!WARNING] 如果某个占位符在以上三个来源中均未定义,配置解析时会抛出ConfigError,并精确指出出错路径(对应 vars_resolver.py 的raise ConfigError(f"Unresolved placeholder '${name}'", path))。

2.3 graph:核心图定义

graph是必需块,映射到GraphDefinition数据类(见 graph.py),包含以下内容:

  • 元数据id(必需)、descriptionlog_level(默认DEBUG,见 graph.py)、is_majority_voting(默认false)、initial_instruction,以及可选的organization
  • 执行控制start/end入口列表(系统在开始时执行start中列出的节点)。start支持字符串或字符串列表两种写法(graph.py),end用于收集图的最终输出。注意end有序列表:靠前的节点优先检查,第一个有输出的节点作为图输出(见 graph.py 的字段说明),在子图场景中尤其常用。
  • 校验逻辑GraphDefinition.validate()(graph.py)会检查节点 ID 是否重复、start节点是否真实存在、边是否引用了未知节点,以及每个节点的memories附件是否指向graph.memory中声明的存储——任何一项不满足都会抛出带精确路径的ConfigError
  • 共享资源memory定义可供node.config.memories引用的存储(对应MemoryStoreConfig)。
  • Schema 对照:design.yaml 镜像了最新的GraphDefinition结构。修改配置后运行python -m tools.export_design_template或调用 Schema API 进行校验(详见第 8 节)。

上述示例中,Human Reviewer -> Article Writer边上的keyword条件会让工作流不断循环,直到审查者输入ACCEPT——这正是"人机协作迭代润色"类流程的标准写法。

进一步阅读:field_specs.md(字段目录)、execution_logic.md(运行时执行逻辑)、design.yaml(生成的基线模板)。

3. 节点类型速查表

节点类型在 builtin_nodes.py 中注册,type字段决定节点使用的配置 schema 与执行器。完整速查表如下:

类型描述关键字段详细文档
agent运行 LLM 驱动的智能体,可附加工具、记忆与思考阶段provider,model,prompt_template,tooling,thinking,memoriesagent.md
python执行共享code_workspace/的 Python 脚本/命令entry_script,inline_code,timeout,envpython.md
human在 Web UI 中暂停等待人工输入prompt,timeout,attachmentshuman.md
subgraph内嵌子 DAG 以复用复杂流程graph_path或内联graphsubgraph.md
passthrough透传节点,默认只转发最后一条消息,可配置为转发全部消息;用于上下文过滤与图结构优化only_last_messagepassthrough.md
literal被触发时发射固定文本负载并丢弃输入content,roleuser/assistantliteral.md
loop_counter守卫节点,在达到迭代次数上限前阻塞下游边,达到后释放max_iterations,reset_on_emit,messageloop_counter.md
loop_timer守卫节点,在达到时长上限前阻塞下游边,达到后释放max_duration,duration_unit,reset_on_emit,message,passthroughloop_timer.md

从源码看,Node.from_dict(node.py)会通过get_node_schema(node_type)解析节点类型,遇到未注册类型时抛出ConfigError("unsupported node type ..."),随后把config分发给对应类型的配置类解析。节点还支持几个通用字段:

  • context_window:执行期间可访问的上下文消息数。0表示只保留keep_message=True的消息;-1表示无限制;其他正数表示保留最近 N 条(keep=True的消息始终保留并计入窗口,见 node.py 的clear_input实现)。
  • log_output:是否记录该节点的输出内容(默认true)。

完整的字段 schema 可通过POST /api/config/schema获取,或直接阅读 entity/configs/ 下的数据类。注册类型与执行器的对应关系见 registry.py。

4. Provider 与 Agent 设置

  • 当节点省略provider时,引擎使用globals.default_provider(例如openai)。
  • modelapi_keybase_url等字段都接受${VAR}占位符以提升环境可移植性。
  • 使用多个 Provider 时,可在工作流根部定义globals{ default_provider: ..., retry: {...} },前提是数据类支持)。

Agent 节点配置由 AgentConfig 承载,Provider 的注册与实现位于 runtime/node/agent/providers/(内置openai_provider.pygemini_provider.py等)。各 Provider 的具体能力在 agent.md 中有完整说明。

4.1 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_LOWER

Gemini Provider 支持多模态输入(图片/视频/音频会自动转换为 Parts),并支持通过function_calling_config控制工具执行行为(详见 gemini_provider.py)。

5. 边与条件:控制 DAG 的流向

5.1 基础边与条件边

基础边只需from/to两个字段(注意源码中EdgeConfig的属性名为source/target,YAML 键是from/to,见 edge.py):

- source: plan target: execute

条件边则在边上声明condition。条件支持三种形态的归一化(见 edge_condition.py):

  • 省略或true→ 等价于恒真函数true
  • 布尔值false→ 等价于恒假函数always_false
  • 字符串 → 等价于{type: function, config: {name: <字符串>}}
edges: - source: router target: analyze condition: should_analyze # functions/edge/should_analyze.py

其中should_analyzefunctions/edge/目录下的一个函数文件名。条件类型在运行时注册:内置类型包括functionkeyword(对应 edge/conditions/ 下的function_manager.pykeyword_manager.py)。keyword类型支持anynoneregex三个关键词列表与case_sensitive开关,其中none优先级最高——一旦命中排除关键词即返回False(见 edge_condition.py)。

异常语义:如果condition函数抛出异常,调度器将该分支标记为失败并停止下游执行。

除条件外,边还支持以下控制字段(全部定义于 edge.py 的FIELD_SPECS):

  • trigger(默认true):该边是否可以触发后继节点;
  • carry_data(默认true):是否向目标节点传递数据;
  • keep_message(默认false):该消息在目标节点中是否永远保留、不被上下文清理;
  • clear_context/clear_kept_context(默认false):在传递新负载前是否清空普通上下文 /keep=True上下文。

5.2 边负载处理器(Payload Processors)

当条件满足后,若需要对传递的负载做变换或过滤(例如提取裁决结果、只保留结构化字段、重写文本),可以在边上添加process。其结构与condition一致(type + config),内置类型包括:

  • regex_extract:基于 Python 正则提取内容,支持group(分组名或索引,缺省为整个匹配)、modereplace_contentmetadatadata_block)、multiple(是否收集全部匹配)、以及on_no_matchpass保持原样 /default使用default_value/drop直接丢弃负载)。完整字段见 edge_processor.py 的RegexEdgeProcessorConfig,还额外支持multilinedotalltemplate(用{match}占位符加工提取值)。

  • function:调用functions/edge_processor/下的辅助函数,处理器签名统一为:

    def foo(payload: Message, **kwargs) -> Message | None

    注意:Processor 接口现已标准化,kwargs中包含context: ExecutionContext,允许访问当前执行上下文。函数名会在field_specs中通过get_function_catalog动态枚举(见 edge_processor.py),前端表单会以下拉形式呈现可用的处理器函数。

示例——从审查结果中提取质量评分并写入元数据:

- from: reviewer to: qa process: type: regex_extract config: pattern: "Score\\s*:\\s*(?P<score>\\d+)" group: score mode: metadata metadata_key: quality_score case_sensitive: false on_no_match: default default_value: "0"

从 transformers.py 可以看出,处理器最终返回的是MessageNoneNone表示丢弃该负载,从而实现"条件过滤 + 数据整形"的链式编排。

6. Agent 节点的高级能力

  • Tooling(工具):通过AgentConfig.tooling配置函数工具与 MCP 工具,详见 Tooling 模块 与 mcp.md。工具的加载与执行由 runtime/node/agent/tool/tool_manager.py 负责。
  • Thinking(思考):通过AgentConfig.thinking启用分阶段推理(如 chain-of-thought、self-reflection 等),参数定义参考 entity/configs/node/thinking.py,内置思考策略见 runtime/node/agent/thinking/(含self_reflection.py等)。
  • Memories(记忆):通过AgentConfig.memories挂载MemoryAttachmentConfig,细节见 Memory 模块。图级声明存储后,节点的记忆附件会被 graph.py 的校验逻辑强制指向已声明的 store;运行时执行则依赖 runtime/node/agent/memory/(支持 simple、file、mem0 等存储实现)。

7. 动态执行:Map-Reduce 与 Tree 模式

节点支持兄弟字段dynamic以开启并行处理或 Map-Reduce 模式。需要说明的是,从当前源码看,动态执行配置已经迁移到边级EdgeConfig上的dynamic字段(edge.py)由DynamicEdgeConfig解析(dynamic_edge_config.py),注释也明确"dynamic configuration has been moved to edges"。文中仍按文档口径给出节点级写法,但实际配置时建议将dynamic挂在边上,目标节点会根据切分结果被动态展开。

7.1 核心概念

  • Map 模式type: map):扇出。将列表输入切分为多个单元并行执行,输出List[Message](展平结果)。
  • Tree 模式type: tree):扇出 + 归约。将输入切分后并行执行,再按group_size递归归约结果,直到只剩一个结果(即"摘要的摘要")。
  • Split 策略:定义如何将前一节点的输出或当前输入切分为并行单元。

7.2 配置结构

nodes: - id: Research Agents type: agent # 标准配置(作为并行单元的模板) config: provider: openai model: gpt-4o prompt_template: "Research this topic: {{content}}" # 动态执行配置(注意:当前仓库已迁移至边级 dynamic) dynamic: type: map # 切分策略(仅第一层) split: type: message # 可选: message, regex, json_path # pattern: "..." # regex 模式必填 # json_path: "$.items[*]" # json_path 模式必填 # 模式专属配置 config: max_parallel: 5 # 并发上限

SplitConfig支持三种切分类型:message(按消息切分)、regex(按正则切分文本)、json_path(按 JSONPath 提取列表)。模式专属配置中,max_parallel为并发上限,缺省10(见 dynamic_edge_config.py 的max_parallel属性)。

7.3 Tree 模式示例

适合对长文本做分块摘要:

dynamic: type: tree split: type: regex pattern: "(?s).{1,2000}(?:\\s|$)" # 每约 2000 字符切一块 config: group_size: 3 # 每 3 个结果归约为 1 个 max_parallel: 10

该模式会自动构建多层执行树,直到结果数归约为 1。Tree 模式的切分配置与 Map 模式一致;group_size缺省为3(见 dynamic_edge_config.py)。实际执行由 workflow/executor/dynamic_edge_executor.py 调度,动态执行的整体机制可参考 dynamic_execution.md。

8. 设计模板导出

修改配置数据类或FIELD_SPECS后,需要重新生成模板:

python -m tools.export_design_template \ --output yaml_template/design.yaml \ --mirror frontend/public/design_0.4.0.yaml
  • 脚本会扫描已注册的节点、记忆、工具以及FIELD_SPECS,生成 YAML 模板,同时产出前端镜像文件;
  • 生成的文件需要提交,并通知前端维护者刷新静态资源(脚本实现在 tools/export_design_template.py)。

前端镜像文件对应frontend/public/design_0.4.0.yaml,供 Web IDE 的动态表单使用;字段目录的生成逻辑见 utils/schema_exporter.py 与 utils/function_catalog.py。

9. CLI 与 API 执行路径

  • Web UI:选择 YAML 文件、填写运行参数、开始执行并在仪表盘中监控。推荐路径。详细说明见 web_ui_guide.md。
  • HTTPPOST /api/workflow/execute,请求体包含session_namegraph_pathgraph_contenttask_prompt、可选attachmentslog_level(默认INFO,支持INFODEBUG)。对应路由实现在 server/routes/execute.py,工作流运行服务见 server/services/workflow_run_service.py。
  • CLIpython run.py --path yaml_instance/demo.yaml --name test_run。通过环境变量提供TASK_PROMPT,或直接在 CLI 提示符下输入任务文本(run.py 中的input("Please enter the task prompt: "))。

CLI 还支持--attachment(可重复,向初始用户消息附加文件)、--fn-module(提供边辅助函数模块)与--inspect-schema(输出配置 schema 后退出,见 run.py)。

10. 调试技巧

  • 使用 Web UI 的上下文快照,或检查WareHouse/<session>/context.json以查看节点的输入输出。注意:所有节点的输出现已标准化为List[Message]
  • 借助 Schema API 的面包屑(见 config_schema_contract.md),或运行python run.py --inspect-schema快速查看字段规格(可结合--schema-breadcrumbs指定作用域,例如'[{"node":"DesignConfig","field":"graph"}]')。
  • 缺失的 YAML 占位符会在解析阶段抛出ConfigError,并在 UI 与 CLI 日志中给出精确路径(例如root.graph.nodes[0].config.api_key),据此可快速定位配置问题。

小结

工作流编排的核心要点可概括为三条:顶层只用version/vars/graph三个键、变量一律走${VAR}占位符且遵循vars > 环境变量 > .env的优先级、节点与边的能力通过注册表(node type / edge condition / edge processor / dynamic edge type)动态扩展。从entity/configs/的数据类到runtime/的执行器,整条链路都有精确的校验与错误提示,这使得 ChatDev 的 DevAll DAG 既适合 Web UI 可视化编排,也适合以纯 YAML 方式进行版本化、可移植的工程化维护。进一步深入可阅读 execution_logic.md(执行调度)、dynamic_execution.md(动态执行)与 config_schema_contract.md(Schema 契约)。

【免费下载链接】ChatDevChatDev 2.0: Dev All through LLM-powered Multi-Agent Collaboration项目地址: https://gitcode.com/GitHub_Trending/ch/ChatDev

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询