chore: import upstream snapshot with attribution
Validate YAML Workflows / Validate YAML Configuration Files (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:37:51 +08:00
commit d0e4308def
614 changed files with 74458 additions and 0 deletions
+84
View File
@@ -0,0 +1,84 @@
# 附件与工件 API 指南
**说明**:此文档面向高级用户,一般场景下无需直接调用附件/工件 API,前端会自行处理。
附件(Attachment)是 Session 生命周期内可上传、下载、由节点注册的文件;工件(Artifact)是对附件事件的抽象,用于实时监听。本文档汇总 REST/WS 接口及存储策略,填补旧版 `frontend_attachment_api.md` 的缺口。
## 1. 上传与列举
### 1.1 上传文件
`POST /api/uploads/{session_id}`
- **Headers**`Content-Type: multipart/form-data`
- **Form 字段**`file`(单个文件)。
- **响应**
```json
{
"attachment_id": "att_bxabcd",
"name": "spec.md",
"mime": "text/markdown",
"size": 12345
}
```
- 文件保存到 `WareHouse/<session>/code_workspace/attachments/`,并记录在 `attachments_manifest.json`。
### 1.2 列举附件
`GET /api/uploads/{session_id}`
- 返回该 Session 当前所有附件的元数据(ID、文件名、mime、大小、来源)。
### 1.3 在执行请求中引用
- `POST /api/workflow/execute` 或 WebSocket `human_input` 消息中可带 `attachments: ["att_xxx"]`,并必须同时提供 `task_prompt`(即便只想上传文件)。
## 2. 工件事件与下载
### 2.1 实时事件
`GET /api/sessions/{session_id}/artifact-events`
- Query`after`, `wait_seconds`, `include_mime`, `include_ext`, `max_size`, `limit`。
- 响应含 `events[]`, `next_cursor`, `has_more`, `timed_out`。
- 每条事件:
```json
{
"artifact_id": "art_123",
"attachment_id": "att_456",
"node_id": "python_runner",
"path": "code_workspace/result.json",
"size": 2048,
"mime": "application/json",
"hash": "sha256:...",
"timestamp": 1732699900
}
```
- WebSocket 会镜像此事件(类型 `artifact_created`),前端可直接订阅。
### 2.2 下载单个工件
`GET /api/sessions/{session_id}/artifacts/{artifact_id}`
- Query`mode=meta|stream`, `download=true|false`。
- **meta**:仅返回元数据。
- **stream**:返回文件内容;`download=true` 时附带 `Content-Disposition`。
- 小文件可选择 `data_uri` 内联(若服务器启用)。
### 2.3 打包下载 Session
`GET /api/sessions/{session_id}/download`
- 将 `WareHouse/<session>/` 打包为 zip,供一次性下载。
## 3. 文件生命周期
1. 上传:写入 `code_workspace/attachments/`manifest 记录 `source`、`workspace_path`、`storage` 等字段。
2. Python 节点或工具可调用 `AttachmentStore.register_file()` 把 workspace 文件注册为附件;`WorkspaceArtifactHook` 会将其同步到事件流。
3. 默认保留所有附件,便于运行结束后下载。如果希望自动清理,设置 `MAC_AUTO_CLEAN_ATTACHMENTS=1`(只在 Session 完成后删除 `attachments/` 目录)。
4. WareHouse 打包下载不会删除原文件,需要额外策略(cron/job)做归档或清空。
## 4. 大小与安全建议
- **大小限制**:后端未硬编码,可在反向代理设置 `client_max_body_size`、`max_request_body_size`,或在自定义分支的 `AttachmentService.save_upload_file` 中添加校验。
- **文件类型**:基于 MIME 推断 `MessageBlockType`image/audio/video/file);可结合 `include_mime` 过滤。
- **病毒/敏感信息**:上传前由客户端自查;必要时在保存后触发扫描服务。
- **权限**Attachment API 依赖 Session ID;生产部署应在代理层或 JWT 内部校验调用者身份,避免越权下载。
## 5. 常见问题
| 问题 | 排查步骤 |
| --- | --- |
| 上传 413/413 Payload Too Large | 调整反向代理或 FastAPI `client_max_size`,确认磁盘配额 |
| 下载链接 404 | 确认 `session_id` 拼写(仅允许字母/数字/`_-`),检查 Session 是否已被清理 |
| 工件事件缺失 | 确认 WebSocket 是否连接,或在 REST 事件接口中使用 `after` 游标重拉 |
| 附件未在 Python 节点可见 | 检查 `code_workspace/attachments/` 是否被清理、或 `_context['python_workspace_root']` 是否正确 |
## 6. 客户端实现建议
- Web UI:使用 `artifact-events` 长轮询或 WebSocket,实时刷新附件列表;在节点成功后提供“下载全部”按钮。
- CLI/自动化:在运行结束后调用 `/download` 拉取 zip;若仅需部分文件,可结合 `artifact-events` 的 `include_ext` 精准过滤。
- 测试环境:可通过脚本模拟上传/下载流程,确保反向代理和 CORS 配置正确。
+95
View File
@@ -0,0 +1,95 @@
# 配置 Schema API 契约
本参考说明 `/api/config/schema``/api/config/schema/validate` 如何暴露 DevAll 的动态配置元数据,便于前端表单、IDE/CLI 通过 breadcrumbs(路径面包屑)按需获取局部 Schema。
## 1. 接口
| 方法 | 作用 |
| --- | --- |
| `POST /api/config/schema` | 根据 breadcrumbs 返回对应配置节点的字段定义。 |
| `POST /api/config/schema/validate` | 校验一份 YAML/JSON 文档,并可回传局部 Schema。 |
### 1.1 请求体(公共字段)
```json
{
"breadcrumbs": [
{"node": "DesignConfig", "field": "graph"},
{"node": "GraphConfig", "field": "nodes"},
{"node": "NodeConfig", "value": "model"}
]
}
```
- `node`(必填):当前所处的类名(如 `DesignConfig``GraphConfig``NodeConfig`)。
- `field`(可选):要下钻的子字段名;缺省表示仅断言仍在该 `node`
- `value`(可选):当子类由判别字段决定时填写(如节点 `type`)。值与 YAML 中保持一致。
- `index`(可选 int):预留用于列表遍历,当前以 `field`/`value` 为主。
### 1.2 `/schema` 响应示例
```json
{
"schemaVersion": "0.1.0",
"node": "NodeConfig",
"fields": [
{"name": "id", "typeHint": "str", "required": true, "description": "Unique node identifier"},
{"name": "type", "typeHint": "str", "required": true,
"enum": ["model","python","agent"],
"enumOptions": [{"value":"model","label":"LLM Node","description":"Runs provider-backed models"}]
}
],
"constraints": [...],
"breadcrumbs": [...],
"cacheKey": "f90d..."
}
```
- `fields`:序列化的 `ConfigFieldSpec`;若有子配置,会包含 `childRoutes`
- `constraints`:由 `collect_schema()` 生成的互斥/组合约束。
- `cacheKey`:基于 `{node, breadcrumbs}` 的 SHA-1,可用于客户端缓存。
### 1.3 `/schema/validate` 额外字段
请求体在 breadcrumbs 旁加入 `document`
```json
{
"breadcrumbs": [{"node": "DesignConfig"}],
"document": "name: demo\nversion: 0.4.0\nworkflow:\n nodes: []\n edges: []\n"
}
```
响应:
- 通过:`{ "valid": true, "schema": { ... } }`
- 配置错误:
```json
{
"valid": false,
"error": "field 'nodes' must not be empty",
"path": ["workflow","nodes"],
"schema": { ... }
}
```
- YAML 解析失败:HTTP 400payload `{ "message": "invalid_yaml", "error": "..." }`
## 2. Breadcrumb 使用提示
- 起点:`{ "node": "DesignConfig" }`。
- 每一步的 `node` 必须与当前位置的类匹配,否则返回 422。
- 用 `field` 进入子配置(graph → nodes → config 等)。
- 判别式子类(如节点 `type`、tooling `type`)需填写 `value`。
- 不可导航的字段会返回 `field '<name>' on <node> is not navigable`。
## 3. CLI 辅助
```bash
python run.py --inspect-schema --schema-breadcrumbs '[{"node":"DesignConfig","field":"graph"}]'
```
输出与 `/schema` 相同,便于在导出模板前调试 `FIELD_SPECS` 或注册表。
## 4. 前端调用范式
1. 以 `[{node:'DesignConfig', field:'graph'}]` 拉取基础表单。
2. 用户展开子配置(节点、tooling 等)时,附加相应 breadcrumbs 再取一次 Schema。
3. 用 `cacheKey + breadcrumbs` 做客户端缓存。
4. 保存前调用 `/schema/validate`,将 `error` + `path` 显示在表单中。
## 5. 错误参考
| HTTP | 场景 | Payload |
| --- | --- | --- |
| 400 | YAML 解析失败 | `{ "message": "invalid_yaml", "error": "..." }` |
| 422 | Breadcrumb 解析失败 | `{ "message": "breadcrumb node 'X'..." }` |
| 200 + `valid=false` | 后端 `ConfigError` | `{ "error": "...", "path": ["workflow", ...] }` |
| 200 + `valid=true` | 文档有效 | 返回所请求的 Schema,便于表单渲染。 |
搭配 `FIELD_SPECS` 使用,可在前端/IDE 构建无需硬编码的配置体验。
+276
View File
@@ -0,0 +1,276 @@
# Dynamic 执行模式指南
Dynamic 执行模式允许在边级别定义并行处理行为,支持 Map(扇出)和 Tree(扇出+归约)两种模式。当消息通过配置了 `dynamic` 的边传递时,目标节点会根据拆分结果动态扩展为多个并行实例。
## 1. 概述
| 模式 | 描述 | 输出 | 适用场景 |
|------|------|------|----------|
| **Map** | 扇出执行,将消息拆分为多个单元并行处理 | `List[Message]`(打平结果) | 批量处理、并行查询 |
| **Tree** | 扇出+归约,并行处理后按组递归合并 | 单个 `Message` | 长文本摘要、层级聚合 |
## 2. 配置结构
Dynamic 配置定义在**边**上,而非节点:
```yaml
edges:
- from: Source Node
to: Target Node
trigger: true
carry_data: true
dynamic: # 边级动态执行配置
type: map # map 或 tree
split: # 消息拆分策略
type: message # message | regex | json_path
# pattern: "..." # regex 模式必填
# json_path: "..." # json_path 模式必填
config: # 模式特定配置
max_parallel: 5 # 最大并发数
```
### 2.1 核心概念
- **动态边**:配置了 `dynamic` 的边,其传递的消息会触发目标节点的动态扩展
- **静态边**:未配置 `dynamic` 的边,其传递的消息会**复制**到所有动态扩展实例
- **目标节点扩展**:目标节点根据 split 结果被"虚拟"扩展为多个并行实例
### 2.2 多入边一致性规则
> [!IMPORTANT]
> 当一个节点有多条入边配置了 `dynamic` 时,所有动态边的配置**必须完全一致**(type、split、config),否则执行时会报错。
## 3. Split 拆分策略
Split 定义如何将通过边的消息拆分为并行执行单元。
### 3.1 message 模式(默认)
每条通过边的消息作为独立执行单元。这是最常用的模式。
```yaml
split:
type: message
```
**执行行为**
- 源节点输出 4 条消息通过动态边
- 拆分为 4 个并行单元,目标节点执行 4 次
### 3.2 regex 模式
使用正则表达式从文本内容中提取匹配项。
```yaml
split:
type: regex
pattern: "(?s).{1,2000}(?:\\s|$)" # 每 2000 字符切分
```
**典型用例**
- 按段落拆分:`pattern: "\\n\\n"`
- 按行拆分:`pattern: ".+"`
- 按固定长度:`pattern: "(?s).{1,N}"`
### 3.3 json_path 模式
从 JSON 格式输出中按路径提取数组元素。
```yaml
split:
type: json_path
json_path: "$.items[*]" # JSONPath 表达式
```
## 4. Map 模式详解
Map 模式将消息拆分后并行执行目标节点,输出结果打平为 `List[Message]`
### 4.1 配置项
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `max_parallel` | int | 10 | 最大并发执行数 |
### 4.2 执行流程
```mermaid
flowchart LR
Source["源节点输出"] --> Edge["动态边 (map)"]
Edge --> Split["拆分"]
Split --> U1["单元 1"]
Split --> U2["单元 2"]
Split --> U3["单元 N"]
U1 --> P1["目标节点 #1"]
U2 --> P2["目标节点 #2"]
U3 --> P3["目标节点 #N"]
P1 --> Merge["合并结果"]
P2 --> Merge
P3 --> Merge
Merge --> Output["List[Message]"]
```
## 5. Tree 模式详解
Tree 模式在 Map 基础上增加归约层,将并行结果按组递归合并,最终输出单个结果。
### 5.1 配置项
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `group_size` | int | 3 | 每组归约的元素数量,最小为 2 |
| `max_parallel` | int | 10 | 每层最大并发执行数 |
### 5.2 执行流程
```mermaid
flowchart TB
subgraph Layer1["第一层:并行执行"]
I1["单元 1"] --> R1["结果 1"]
I2["单元 2"] --> R2["结果 2"]
I3["单元 3"] --> R3["结果 3"]
I4["单元 4"] --> R4["结果 4"]
I5["单元 5"] --> R5["结果 5"]
I6["单元 6"] --> R6["结果 6"]
end
subgraph Layer2["第二层:分组归约 (group_size=3)"]
R1 & R2 & R3 --> G1["归约组 1"]
R4 & R5 & R6 --> G2["归约组 2"]
end
subgraph Layer3["第三层:最终归约"]
G1 & G2 --> Final["最终结果"]
end
```
## 6. 静态边消息复制
当目标节点同时有动态入边和静态入边时:
- **动态边消息**:按 split 策略拆分,每个单元执行一次目标节点
- **静态边消息**:**复制**到每个动态扩展实例
```yaml
nodes:
- id: Task Generator
type: passthrough
config: ...
- id: Extra Requirement
type: literal
config:
content: "请使用简洁的语言"
- id: Processor
type: agent
config:
name: gpt-4o
role: 处理任务
edges:
- from: Task Generator
to: Processor
dynamic: # 动态边:4 条任务 → 4 个并行单元
type: map
split:
type: message
config:
max_parallel: 10
- from: Extra Requirement
to: Processor # 静态边:复制到所有 4 个实例
trigger: true
carry_data: true
```
**执行结果**Processor 执行 4 次,每次收到 1 条任务 + "请使用简洁的语言"
## 7. 完整示例
### 7.1 旅行规划(Map + Tree 组合)
```yaml
graph:
nodes:
- id: Eat Planner
type: literal
config:
content: 请规划在上海吃什么
role: user
- id: Play Planner
type: literal
config:
content: 请规划在上海玩什么
role: user
- id: Stay Planner
type: literal
config:
content: 请规划在上海住哪里
role: user
- id: Collector
type: passthrough
config:
only_last_message: false
- id: Travel Executor
type: agent
config:
name: gpt-4o
role: 你是旅行规划师,请按照用户请求进行规划
- id: Final Aggregator
type: agent
config:
name: gpt-4o
role: 请将输入的内容整合成一份完整的旅行计划
edges:
- from: Eat Planner
to: Collector
- from: Play Planner
to: Collector
- from: Stay Planner
to: Collector
- from: Collector
to: Travel Executor
dynamic: # Map 扇出:3 个规划请求 → 3 个并行执行
type: map
split:
type: message
config:
max_parallel: 10
- from: Travel Executor
to: Final Aggregator
dynamic: # Tree 归约:3 个结果 → 1 个最终计划
type: tree
split:
type: message
config:
group_size: 2
max_parallel: 10
```
### 7.2 长文档摘要(Tree 模式)
```yaml
edges:
- from: Document Source
to: Summarizer
dynamic:
type: tree
split:
type: regex
pattern: "(?s).{1,2000}(?:\\s|$)" # 2000 字符切分
config:
group_size: 3
max_parallel: 10
```
## 8. 性能建议
- **控制并发**:设置合理的 `max_parallel` 避免触发 API 限流
- **优化拆分粒度**:过细的拆分增加开销,过粗则无法充分并行
- **Tree 组大小**`group_size=2-4` 通常是较好的选择
- **监控成本**Dynamic 模式会显著增加 API 调用次数
## 9. 相关文档
- [边配置指南](../edges.md)
- [工作流编排指南](../workflow_authoring.md)
- [Agent 节点配置](../nodes/agent.md)
+229
View File
@@ -0,0 +1,229 @@
# 图执行逻辑
> 版本:2025-12-16
本文档详细说明 DevAll 后端如何解析和执行工作流图,特别是对于包含循环结构的复杂图的处理机制。
## 1. 执行引擎概述
DevAll 工作流执行引擎支持两类图结构:
| 图类型 | 特征 | 执行策略 |
|--------|------|----------|
| **DAG(有向无环图)** | 节点间无循环依赖 | 拓扑排序 + 同层并发执行 |
| **含环有向图** | 存在一个或多个循环结构 | 递归式超级节点调度 |
执行引擎会自动检测图结构,选择合适的执行策略。
## 2. DAG 执行流程
对于不包含循环的工作流图,执行引擎采用标准的 DAG 调度策略:
1. **构建前驱/后继关系**:解析边定义,为每个节点建立 `predecessors``successors` 列表
2. **计算入度**:统计每个节点的前驱数量
3. **拓扑排序**:将入度为 0 的节点放入第一层,执行后将后继节点入度减 1,新的入度为 0 节点进入下一层
4. **同层并发**:同一层内的节点无依赖关系,可以并行执行
```mermaid
flowchart LR
subgraph Layer1["执行层 1"]
A["节点 A"]
B["节点 B"]
end
subgraph Layer2["执行层 2"]
C["节点 C"]
end
subgraph Layer3["执行层 3"]
D["节点 D"]
end
A --> C
B --> C
C --> D
```
## 3. 循环图执行流程
### 3.1 Tarjan 强连通分量检测
当图中存在循环结构时,执行引擎首先使用 **Tarjan 算法** 检测所有强连通分量(Strongly Connected Components, SCC)。Tarjan 算法通过深度优先搜索,在 O(|V|+|E|) 时间复杂度内识别图中的所有环路。
包含多于一个节点的 SCC 即为环路结构。
### 3.2 超级节点构建
检测到环路后,执行引擎将每个环路抽象为一个"超级节点"Super Node):
- 环路内部的所有节点被封装在超级节点中
- 超级节点之间的依赖关系来源于原始节点间的跨环边
- 封装后的超级节点图一定是 DAG,可以进行拓扑排序
```mermaid
flowchart TB
subgraph Original["原始图"]
direction TB
A1["A"] --> B1["B"]
B1 --> C1["C"]
C1 --> B1
C1 --> D1["D"]
end
subgraph Abstracted["超级节点图"]
direction TB
A2["节点 A"] --> S1["超级节点<br/>(B, C 环路)"]
S1 --> D2["节点 D"]
end
Original -.->|"抽象"| Abstracted
```
### 3.3 递归式环路执行策略
对于环路超级节点,系统采用递归式执行策略:
#### 步骤 1:唯一初始节点识别
分析环路边界,识别当前被唯一触发的入口节点作为"初始节点"。该节点必须满足:
- 被环路外部的前驱节点通过满足条件的边触发
- 有且仅有一个节点满足此条件
#### 步骤 2:构建作用域子图
以当前环路的所有节点为作用域,**逻辑上移除初始节点的所有入边**。这一操作打破外层环的边界,使后续的环路检测仅针对环内部的嵌套结构进行。
#### 步骤 3:嵌套环路检测
对构建的子图再次应用 Tarjan 算法,检测作用域内的嵌套环路。由于初始节点的入边已被移除,检测到的强连通分量仅为真正的内层嵌套环。
#### 步骤 4:内层超级节点构建与拓扑排序
若检测到嵌套环路:
- 将每个内层环路抽象为超级节点
- 构建作用域内的超级节点依赖图
- 对该超级节点图执行拓扑排序
若未检测到嵌套环路,则直接进行 DAG 拓扑排序。
#### 步骤 5:分层执行
按拓扑排序得到的执行层次依次执行:
- **普通节点**:检查触发状态后执行,首轮迭代时初始节点强制执行
- **内层环路超级节点**:**递归调用步骤 1-6**,形成嵌套执行结构
#### 步骤 6:退出条件检查
每完成一轮环内执行后,系统检查以下退出条件:
- **出口边触发**:若任一环内节点触发了环外节点的边,则退出环路
- **最大迭代次数**:若达到配置的最大迭代次数(默认 100),强制终止
- **初始节点未被重触发**:若初始节点未被环内前驱节点重新触发,环路自然终止
若条件均不满足,则返回步骤 2 开始下一轮迭代。
### 3.4 环路执行流程图
```mermaid
flowchart TB
A["环路超级节点被调度"] --> B["识别唯一触发的初始节点"]
B --> C{"是否有有效初始节点?"}
C -->|"无"| D["跳过该环路"]
C -->|"有多个"| E["报告配置错误"]
C -->|"唯一"| F["构建作用域子图<br/>移除初始节点入边"]
F --> G["Tarjan算法检测嵌套环路"]
G --> H{"存在内层嵌套环?"}
H -->|"否"| I["DAG拓扑排序"]
H -->|"是"| J["构建内层超级节点<br/>执行拓扑排序"]
I --> K["分层执行"]
J --> K
K --> L["执行普通节点"]
K --> M["递归执行内层环路"]
L --> N{"检查退出条件"}
M --> N
N -->|"出口边被触发"| O["退出环路"]
N -->|"达到最大迭代次数"| O
N -->|"初始节点未被重触发"| O
N -->|"继续迭代"| F
```
## 4. 边条件与触发机制
### 4.1 边触发(trigger
每条边有一个 `trigger` 属性,决定该边是否参与执行顺序计算:
| trigger 值 | 行为 |
|------------|------|
| `true`(默认) | 该边参与拓扑排序,目标节点等待源节点完成 |
| `false` | 该边不参与拓扑排序,仅用于数据传递 |
### 4.2 边条件(condition
边条件决定数据是否沿该边流动:
- `true`(默认):总是传递
- `keyword`:检查上游输出是否包含/不包含特定关键词
- `function`:调用自定义函数判断
- 其他自定义条件类型
只有当条件满足时,目标节点才会被触发执行。
## 5. 典型循环场景示例
### 5.1 人工审阅循环
```yaml
nodes:
- id: Writer
type: agent
config:
name: gpt-4o
role: 你是一位专业的技术作家
- id: Reviewer
type: human
config:
description: 请审阅文章,满意请输入 ACCEPT
edges:
- from: Writer
to: Reviewer
- from: Reviewer
to: Writer
condition:
type: keyword
config:
none: [ACCEPT] # 不包含 ACCEPT 时继续循环
```
执行流程:
1. Writer 生成文章
2. Reviewer 人工审阅
3. 若输入不包含 "ACCEPT",返回 Writer 修改
4. 若输入包含 "ACCEPT",退出循环
### 5.2 嵌套循环
系统支持任意深度的嵌套循环。例如,一个外层"审阅-修订"循环内部可以包含一个"生成-验证"循环:
```
外层循环 (Writer -> Reviewer -> Writer)
└── 内层循环 (Generator -> Validator -> Generator)
```
递归式执行策略会自动处理这种嵌套结构。
## 6. 关键代码模块
| 模块 | 功能 |
|------|------|
| `workflow/cycle_manager.py` | Tarjan 算法实现、环路信息管理 |
| `workflow/topology_builder.py` | 超级节点图构建、拓扑排序 |
| `workflow/executor/cycle_executor.py` | 递归式环路执行器 |
| `workflow/graph.py` | 图执行主入口 |
## 7. 变更记录
- **2025-12-16**:新增图执行逻辑文档,详细说明 DAG 与循环图的执行策略。
+61
View File
@@ -0,0 +1,61 @@
# FIELD_SPECS 定义指南
本文档解释如何在新增配置(Config)时正确编写 `FIELD_SPECS`,以便 Web UI 表单和 `python -m tools.export_design_template` 命令自动生成可视化表单与 YAML 模板。本指南适用于所有继承 `BaseConfig` 的配置类,例如节点、Memory、Thinking、Tooling 等。
## 1. 为什么需要 FIELD_SPECS
- UI 表单依赖 `FIELD_SPECS` 生成输入控件、默认值、提示文案。
- 设计模板导出脚本会读取 `FIELD_SPECS`,将字段元数据写入 `yaml_template/design*.yaml` 以及 `frontend/public/` 镜像文件。
- 没有 `FIELD_SPECS` 的字段在前端无法展示,也不会出现在导出的模板中。
## 2. 基本结构
`FIELD_SPECS` 是一个 `{字段名: ConfigFieldSpec}` 的字典,通常定义在 Config 类内:
```python
FIELD_SPECS = {
"interpreter": ConfigFieldSpec(
name="interpreter",
display_name="解释器",
type_hint="str",
required=False,
default="python3",
description="Python 可执行文件路径",
),
...
}
```
核心字段说明:
- `name`:与 YAML 字段一致。
- `display_name`:可选的用户展示名称,前端表单优先显示;缺省时自动回退到 `name`
- `type_hint`:供 UI/文档展示的类型描述,例如 `str``list[str]``dict[str, Any]`
- `required`:是否必填;若有默认值通常设为 False。
- `default`:默认值(标量或 JSON 可序列化对象)。
- `description`:表单提示与文档说明。
- `enum`:可选值列表(字符串数组)。
- `enumOptions`:为枚举提供 label/description 等附加提示,推荐搭配 `enum` 一起返回,提升表单友好度。
- `child`:嵌套子配置类(引用另一个 `BaseConfig` 子类)。
## 3. 编写流程
1. **实现 `from_dict` 校验**:在解析 YAML 时确保类型正确、提供清晰错误(抛 `ConfigError`,见 `entity/configs/python_runner.py`)。
2. **定义 `FIELD_SPECS`**:覆盖所有公开字段,提供类型、描述、默认值等信息。
3. **动态字段处理**:若字段依赖注册表或目录扫描结果,重写 `field_specs()` 并使用 `replace()` 注入实时 `enum`/`description`(示例:`FunctionToolEntryConfig.field_specs()` 自动列出函数目录)。
4. **导出设计模板**:完成修改后运行:
```bash
python -m tools.export_design_template --output yaml_template/design.yaml --mirror frontend/public/design.yaml
```
该命令会根据最新的 `FIELD_SPECS` 生成 YAML 模板和前端镜像文件,无需手动编辑。
## 4. 常见模式示例
- **简单标量字段**`entity/configs/python_runner.py` 中的 `timeout_seconds`,展示如何设置整数默认值和校验。
- **嵌套列表字段**`entity/configs/memory.py` 的 `file_sources` 使用 `child=FileSourceConfig`UI 自动渲染可重复子表单。
- **动态枚举**`entity/configs/node.py:304` 的 `Node.field_specs()` 使用节点注册表填充 `type` 选项并附带 `enumOptions` 描述;`FunctionToolEntryConfig.field_specs()` 从函数目录生成带说明的枚举列表。
- **注册驱动描述**:调用 `register_node_type`/`register_memory_store`/`register_thinking_mode`/`register_tooling_type` 时提供的 `summary/description` 会自动写入 `enumOptions`,务必填写,避免前端看到没有含义的值。
- **可选区块**:通过 `required=False` + `default=...` 表示可选配置,`from_dict` 中需妥善处理。
## 5. 最佳实践
- 描述保持用户友好,明确单位(例如“超时时间(秒)”)。
- 默认值应与 `from_dict` 行为一致,避免 UI 默认与后端解析不符。
- 对嵌套配置提供精简示例或引用,以免 UI 难以理解字段含义。
- 修改或新增 `FIELD_SPECS` 后,记得同步导出设计模板。
如需更多例子,可查阅 `entity/configs/model.py`、`entity/configs/tooling.py` 等文件,或参考已有节点/Memory/Thinking 配置的实现。
+45
View File
@@ -0,0 +1,45 @@
# DevAll 后端用户文档
本目录作为导航页,面向需要部署、编排或扩展 DevAll 后端的读者。详尽步骤与示例请在下表中找到目标子文档。
## 1. 文档地图
| 主题 | 内容提要 |
| --- |-----------------------------------------------------------|
| [Web UI 快速入门](web_ui_guide.md) | 前端界面操作、工作流执行、人工审阅、故障排查 |
| [工作流编排](workflow_authoring.md) | YAML 结构、节点类型、Provider/边条件、设计模板导出、CLI 运行 |
| [图执行逻辑](execution_logic.md) | DAG/循环图执行策略、Tarjan 环路检测、超级节点构建、递归式环路执行 |
| [Dynamic 并行执行](dynamic_execution.md) | Map/Tree 模式、Split 拆分策略、并行处理与层级归约 |
| [Memory 模块](modules/memory.md) | Memory 列表架构、内置 `simple`/`file`/`blackboard` 行为、嵌入配置、排障 |
| [Thinking 模块](modules/thinking.md) | 思考增强机制、自我反思模式、扩展自定义思考模式 |
| [Tooling 模块](modules/tooling/README.md) | Function / MCP 模式、上下文注入、内置函数清单、MCP 启动方式 |
| [节点类型详解](nodes/) | Agent、Python、Human、Subgraph、Passthrough、Literal、Loop Counter 等节点配置 |
| [附件与工件 API](attachments.md) | 上传/列举/下载接口、manifest 结构、清理策略、安全限制 |
| [FIELD_SPECS 规范](field_specs.md) | UI 表单与模板导出的字段元数据标准(如果您希望自定义模块,请务必阅读此文档) |
| [配置 Schema API 契约](config_schema_contract.md) | `/api/config/schema(*)` 请求示例、breadcrumbs 协议(用户可忽略) |
## 2. 产品概览(后端视角)
- **工作流调度引擎**:解析 YAML DAG,在统一上下文中协调 `model``python``tooling``human` 等节点,并把节点输出写入 `WareHouse/<session>/`
- **多 Provider 抽象**`runtime/node/agent/providers/` 层封装 OpenAI、Gemini 等 API,可在节点级别切换模型与鉴权,亦支持额外 `thinking``memories` 配置。
- **实时可观测性**FastAPI + WebSocket 将节点状态、stdout/stderr、工件事件推送至 Web UI;结构化日志写入 `logs/`,便于集中收集。
- **运行资产管理**:每次运行创建独立 Session,附件、Python workspace、context snapshot、输出摘要等均可下载。
## 3. 架构与运行流概览
1. **入口**Web UI 与 CLI 调用 `server_main.py` 暴露的 FastAPI(如 `/api/workflow/execute`)。
2. **验证/入队**`WorkflowRunService` 校验 YAML、创建 Session、准备 `code_workspace/attachments/`,随后调度器在 `workflow/` 中运行 DAG。
3. **执行阶段**:节点执行器负责依赖解析、上下文传递、工具调用、memory 检索;`MemoryManager``ToolingConfig``ThinkingManager` 会在模型节点内按需触发。
4. **可观测性**WebSocket 推送状态、日志、artifact 事件;`logs/` 存储 JSON 日志,`WareHouse/` 保存运行资产。
5. **清理与下载**:Session 结束后可选择打包下载或通过附件 API 逐项获取;保留策略由部署者自定。
## 4. 角色导航
- **解决方案工程师/Prompt 工程师**:从 [工作流编排](workflow_authoring.md) 入手,若需要上下文记忆或工具扩展,分别阅读 Memory 与 Tooling 模块文档。
- **扩展开发者**:结合 [FIELD_SPECS](field_specs.md) 与 [Tooling 模块](modules/tooling/README.md) 了解注册流程,必要时参照 [配置 Schema API 契约](config_schema_contract.md) 调试 UI 交互(英文版见 `docs/en/config_schema_contract.md`)。
## 5. 常用术语
- **Session**:一次完整运行的 ID(由时间戳+名称组成),贯穿 Web UI、后端和 `WareHouse/`
- **code_workspace**Python 节点共享的目录,位于 `WareHouse/<session>/code_workspace/`,包含自动同步的附件。
- **Attachment**:用户上传或运行期间注册的文件,通过 REST/WS API 可查询/下载。
- **Memory Store / Attachment**Memory Store 定义存储实现;Memory Attachment 是模型节点引用 Memory Store 的规则(检索阶段、读写策略等)。
- **Tooling**:模型节点绑定的工具执行环境(Function 或 MCP)。
如发现内容缺失或过时,请在仓库提交 Issue/PR,或在 docs 目录内直接补充并同步至前端模板。
+141
View File
@@ -0,0 +1,141 @@
# Memory 模块指南
本文档解释 DevAll 的 Memory 体系:memory 列表配置、内置存储实现、Agent 节点如何引用记忆,以及排障建议。代码主要位于 `entity/configs/memory.py``node/agent/memory/*.py`
## 1. 体系结构
1. **Memory Store**:在 YAML `memory[]` 中声明,包含 `name``type``config``type``register_memory_store()` 注册,并映射到具体实现。
2. **Memory Attachment**:在 Agent 节点(`AgentConfig.memories`)中引用 `MemoryAttachmentConfig`,指定读取/写入策略及检索阶段。
3. **MemoryManager**:运行期根据 Attachment+Store 构建 Memory 实例,负责 `load()``retrieve()``update()``save()`
4. **Embedding**`SimpleMemoryConfig``FileMemoryConfig` 可内嵌 `EmbeddingConfig`,由 `EmbeddingFactory` 创建 OpenAI 或本地向量模型。
## 2. Memory 配置示例
```yaml
memory:
- name: convo_cache
type: simple
config:
memory_path: WareHouse/shared/simple.json
embedding:
provider: openai
model: text-embedding-3-small
api_key: ${API_KEY}
- name: project_docs
type: file
config:
index_path: WareHouse/index/project_docs.json
file_sources:
- path: docs/
file_types: [".md", ".mdx"]
recursive: true
embedding:
provider: openai
model: text-embedding-3-small
```
### Mem0 Memory 配置
```yaml
memory:
- name: agent_memory
type: mem0
config:
api_key: ${MEM0_API_KEY}
agent_id: my-agent
```
## 3. 内置 Memory Store 对比
| 类型 | 路径 | 特点 | 适用场景 |
| --- | --- | --- | --- |
| `simple` | `node/agent/memory/simple_memory.py` | 运行结束后可选择落盘(JSON);使用向量搜索(FAISS)+语义重打分;支持读写 | 小规模对话记忆、快速原型 |
| `file` | `node/agent/memory/file_memory.py` | 将指定文件/目录切片为向量索引,只读;自动检测文件变更并更新索引 | 知识库、文档问答 |
| `blackboard` | `node/agent/memory/blackboard_memory.py` | 轻量附加日志,按时间/条数裁剪;不依赖向量检索 | 简易广播板、流水线调试 |
| `mem0` | `node/agent/memory/mem0_memory.py` | 由 Mem0 云端托管;支持语义搜索 + 图关系;无需本地 embedding 或持久化。需安装 `mem0ai` 包。 | 生产级记忆、跨会话持久化、多 Agent 记忆共享 |
> 所有内置 store 都会在 `register_memory_store()` 中注册,摘要可通过 `MemoryStoreConfig.field_specs()` 在 UI 中展示。
## 4. MemoryAttachmentConfig 说明
| 字段 | 说明 |
| --- | --- |
| `name` | 引用的 Memory Store 名称(需在 `stores[]` 中存在且唯一)。|
| `retrieve_stage` | 可选数组,限制检索发生的阶段(`AgentExecFlowStage``pre`, `plan`, `gen`, `critique` 等)。缺省表示所有阶段。|
| `top_k` | 每次检索返回的条数,默认 3。|
| `similarity_threshold` | 过滤相似度下限(-1 表示不限制)。|
| `read` / `write` | 是否允许在该节点读取/写回此记忆。|
Agent 节点示例:
```yaml
nodes:
- id: answer
type: agent
config:
provider: openai
model: gpt-4o-mini
prompt_template: answer_user
memories:
- name: convo_cache
retrieve_stage: ["gen"]
top_k: 5
read: true
write: true
- name: project_docs
read: true
write: false
```
执行顺序:
1. `MemoryManager` 在节点进入 `gen` 阶段时,遍历 Attachments。
2. 满足阶段与 `read=true` 的 Attachment 调用对应 Memory Store 的 `retrieve()`
3. 结果格式化并拼接为“===== 相关记忆 =====”文本写入 Agent 输入上下文。
4. 节点完成后,`write=true` 的 Attachment 将调用 `update()` 并在必要时 `save()`
## 5. Store 细节
所有 Memory Store 都持久化统一的 `MemoryItem` 结构:
- `content_summary`:用于检索的精简文本;
- `input_snapshot` / `output_snapshot`:序列化的消息块(含 base64 附件),确保多模态上下文不会丢失;
- `metadata`:记录角色、输入预览、附件 ID 等附加信息。
这使得 Memory 与 Thinking 模块可以共享多模态内容,无需额外适配。
### 5.1 SimpleMemory
- **路径**`SimpleMemoryConfig.memory_path`(可为 `auto`),缺省仅驻留内存。
- **检索**
1. 以 prompt 构建查询文本并做裁剪。
2. 调用 Embedding 生成向量 → FAISS `IndexFlatIP` 检索 → 语义重打分(Jaccard/LCS)。
- **写入**`update()` 根据输入/输出生成 `MemoryContentSnapshot`,计算摘要哈希去重,再写入 embedding + snapshot + 附件元信息。
- **适配建议**:控制 `max_content_length` 避免爆 context;结合 `top_k`/`similarity_threshold` 防止无关内容。
### 5.2 FileMemory
- **配置**:至少一个 `file_sources`(路径、后缀过滤、递归、编码)。`index_path` 必填,方便增量更新。
- **索引流程**:扫描文件 → 切片(默认 500 字符、重叠 50)→ Embedding → 写入 JSON(包括 `file_metadata`)。
- **检索**:同样使用 FAISS 余弦相似度,只读,不支持 `update()`
- **维护**`load()` 时校验文件哈希,必要时重建索引;建议将 `index_path` 放在持久卷。
### 5.3 BlackboardMemory
- **配置**`memory_path`(可 `auto`)、`max_items`。若路径不存在则在 Session 目录内创建。
- **检索**:直接返回最近 `top_k` 条,按时间排序。
- **写入**`update()` 以 append 方式存储最新的输入/输出 snapshot(文本 + 块 + 附件信息),不生成向量,适合事件流或人工批注。
### 5.4 Mem0Memory
- **配置**:必须提供 `api_key`(从 [app.mem0.ai](https://app.mem0.ai) 获取)。可选参数 `user_id``agent_id``org_id``project_id` 用于记忆范围控制。
- **实体范围**`user_id``agent_id` 是独立的维度,可在 `add()``search()` 调用中同时使用。若同时配置,检索时使用 OR 过滤器(`{"OR": [{"user_id": ...}, {"agent_id": ...}]}`)在一次 API 调用中搜索两个范围。写入时两个 ID 同时包含。
- **检索**:使用 Mem0 服务端语义搜索。通过 `MemoryAttachmentConfig` 中的 `top_k``similarity_threshold` 控制。
- **写入**`update()` 仅将用户输入(`role: "user"` 消息)发送至 Mem0。不包含 Agent 输出,以避免 LLM 响应中的内容被提取为噪声记忆。
- **持久化**:完全由云端托管。`load()``save()` 为空操作(no-op)。记忆在不同运行和会话间自动持久化。
- **依赖**:需安装 `mem0ai` 包(`pip install mem0ai`)。
## 6. EmbeddingConfig 提示
- 字段:`provider`, `model`, `api_key`, `base_url`, `params`
- `provider=openai` 时使用 `openai.OpenAI` 客户端,可配置 `base_url` 以兼容兼容层。
- `params` 支持 `use_chunking`, `chunk_strategy`, `max_length` 等自定义键。
- `provider=local` 时需提供 `params.model_path`,依赖 `sentence-transformers`
## 7. 排错与最佳实践
- **重复命名**:内存列表会校验 `memory[]` 名称唯一;重复时抛出 `ConfigError`
- **缺少 embedding**`SimpleMemory`/`FileMemory` 若未提供 embedding,则仅能以追加方式工作(SimpleMemory)或抛出错误(FileMemory)。
- **权限**:确保 `memory_path`/`index_path` 所在目录可写;容器化部署应挂载卷。
- **性能**
- 大型 FileMemory 建议离线构建索引并缓存。
- 通过 `retrieve_stage` 控制检索次数,减少模型输入冗余。
- 调整 `top_k``similarity_threshold` 以平衡召回与 token 成本。
## 8. 扩展自定义 Memory
1. 新建 Config + Store(继承 `MemoryBase`)。
2.`node/agent/memory/registry.py` 中调用 `register_memory_store("my_store", config_cls=..., factory=..., summary="用途")`
3. 补充 `FIELD_SPECS`,运行 `python -m tools.export_design_template ...` 以让前端获取新枚举。
4. 更新本指南或附带 README,说明新 store 的配置项与边界条件。
+108
View File
@@ -0,0 +1,108 @@
# Thinking 模块指南
Thinking 模块为 Agent 节点提供思考增强能力,使模型能够在生成结果前或后进行额外的推理过程。本文档介绍 Thinking 模块的架构、内置模式及配置方法。
## 1. 体系结构
1. **ThinkingConfig**:在 YAML `nodes[].config.thinking` 中声明,包含 `type``config` 两个字段。
2. **ThinkingManagerBase**:抽象基类,定义 `_before_gen_think``_after_gen_think` 两个时机的思考逻辑。
3. **注册中心**:通过 `register_thinking_mode()` 注册新的思考模式,Schema API 会自动展示可用选项。
## 2. 配置示例
```yaml
nodes:
- id: Thoughtful Agent
type: agent
config:
provider: openai
name: gpt-4o
api_key: ${API_KEY}
thinking:
type: reflection
config:
reflection_prompt: |
请仔细审视你的回答,考虑以下方面:
1. 逻辑是否严密
2. 有无事实错误
3. 表达是否清晰
然后给出改进后的回答。
```
## 3. 内置思考模式
| 类型 | 描述 | 触发时机 | 配置字段 |
|------|------|----------|----------|
| `reflection` | 模型生成后进行自我反思并优化输出 | 生成后 (`after_gen`) | `reflection_prompt` |
### 3.1 Reflection 模式
Self-Reflection 模式让模型在初次生成后对自己的输出进行反思和改进。实现流程:
1. Agent 节点正常调用模型生成初始回答
2. ThinkingManager 将对话历史(系统角色、用户输入、模型输出)拼接为反思上下文
3. 结合 `reflection_prompt` 再次调用模型生成反思结果
4. 反思结果替换原始输出作为节点最终输出
#### 配置项
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `reflection_prompt` | string | 是 | 引导模型反思的提示词,可指定反思维度和期望改进方向 |
#### 适用场景
- **写作润色**:让模型自我审阅并修正语法、逻辑问题
- **代码审查**:生成代码后自动进行安全和质量检查
- **复杂推理**:对多步骤推理结果进行验证和修正
## 4. 执行时机
ThinkingManager 支持两种执行时机:
| 时机 | 属性 | 说明 |
|------|------|------|
| 生成前 (`before_gen`) | `before_gen_think_enabled` | 在模型调用前执行思考,可预处理输入 |
| 生成后 (`after_gen`) | `after_gen_think_enabled` | 在模型输出后执行思考,可后处理或优化输出 |
内置的 `reflection` 模式仅启用生成后思考。扩展开发者可根据需求实现生成前思考。
## 5. 与 Memory 的交互
Thinking 模块可访问 Memory 上下文:
- `ThinkingPayload.text`:当前阶段的文本内容
- `ThinkingPayload.blocks`:多模态内容块(图片、附件等)
- `ThinkingPayload.metadata`:附加元数据
Memory 检索结果会通过 `memory` 参数传入思考函数,允许反思时参考历史记忆。
## 6. 扩展自定义思考模式
1. **创建配置类**:继承 `BaseConfig`,定义所需配置字段
2. **实现 ThinkingManager**:继承 `ThinkingManagerBase`,实现 `_before_gen_think``_after_gen_think`
3. **注册模式**
```python
from runtime.node.agent.thinking.registry import register_thinking_mode
register_thinking_mode(
"my_thinking",
config_cls=MyThinkingConfig,
manager_cls=MyThinkingManager,
summary="自定义思考模式描述",
)
```
4. **导出模板**:运行 `python -m tools.export_design_template` 更新前端选项
## 7. 最佳实践
- **控制反思轮次**:当前反思为单轮,若需多轮可在 `reflection_prompt` 中明确迭代要求
- **简洁提示词**:过长的 `reflection_prompt` 会增加 token 消耗,建议聚焦关键改进点
- **配合 Memory**:将重要反思结果存入 Memory,供后续节点参考
- **监控成本**:反思会额外调用模型,注意 token 用量
## 8. 相关文档
- [Agent 节点配置](../nodes/agent.md)
- [Memory 模块](memory.md)
- [工作流编排指南](../workflow_authoring.md)
+47
View File
@@ -0,0 +1,47 @@
# Tooling 模块总览
DevAll 目前支持两类工具绑定到 Agent 节点:
1. **Function Tooling**:调用仓库内的 Python 函数(`functions/function_calling/`),通过 JSON Schema 自动生成工具签名。
2. **MCP Tooling**:连接符合 Model Context Protocol 的外部服务,可直接复用 FastMCP、Claude Desktop 等工具生态。
所有 Tooling 配置都挂载在 `AgentConfig.tooling`
```yaml
nodes:
- id: solve
type: agent
config:
provider: openai
model: gpt-4o-mini
prompt_template: solver
tooling:
type: function
config:
tools:
- name: describe_available_files
- name: load_file
auto_load: true
timeout: 20
```
## 1. 生命周期
1. 解析阶段:`ToolingConfig` 根据 `type` 选择 `FunctionToolConfig``McpRemoteConfig``McpLocalConfig`,字段定义来自 `entity/configs/tooling.py`
2. 运行阶段:Agent 节点根据响应启用工具调用;当 LLM 选择某工具时,执行器会将 `_context`(附件仓库、workspace 路径等)注入函数或通过 MCP 发送请求。
3. 结束阶段:工具输出写入 Agent 消息流,必要时注册为附件(如 `load_file`)。
## 2. 文档结构
- [function.md](function.md)Function Tooling 配置、上下文注入、最佳实践。
- [function_catalog.md](function_catalog.md):仓库内置函数清单与示例。
- [mcp.md](mcp.md):MCP 工具配置、自动启动、FastMCP 示例、安全提示。
## 3. 快速对比
| 维度 | Function | MCP |
| --- | --- | --- |
| 部署 | 同进程调用本地 Python 函数 | Remote:直连 HTTP 服务;Local:拉起本地进程并通过 stdio 连接 |
| Schemas | 自动从类型注解 + `ParamMeta` 生成 | 由 MCP JSON Schema 提供 |
| 上下文 | 自动注入 `_context`(附件/workspace | 取决于 MCP 服务器实现 |
| 典型用途 | 文件操作、本地脚本、内部 API | 第三方工具合集、浏览器、数据库代理 |
## 4. 安全提示
- Function Tooling 运行在后端进程中,应确保函数遵循最小权限原则;不要在函数中执行不受控的命令。
- MCP Tooling 分为 **Remote (HTTP)****Local (stdio)**。Remote 仅配置已有服务器地址;Local 会拉起进程,请使用受控脚本并限制环境变量,必要时通过 `wait_for_log` 等字段判断进程是否就绪。
- 若工具可能修改附件或 workspace,请结合 [附件指南](../../attachments.md) 了解生命周期与清理策略。
+80
View File
@@ -0,0 +1,80 @@
# Function Tooling 配置指南
`FunctionToolConfig` 允许 Agent 节点调用仓库中的 Python 函数。相关代码位于 `entity/configs/tooling.py``utils/function_catalog.py` 以及 `functions/function_calling/`
## 1. 配置字段
| 字段 | 说明 |
| --- | --- |
| `tools` | 列表,元素为 `FunctionToolEntryConfig`。每个条目至少包含 `name`。|
| `timeout` | 单次工具执行的超时时间(秒)。|
`FunctionToolEntryConfig` 字段:
- `name`:函数名,来自 `functions/function_calling/` 文件的顶级函数。
### 函数列表展示与 `module_name:All`
- UI 下拉列表会将每个函数展示为 `module_name:function_name``module_name` 等于函数文件相对于 `functions/function_calling/` 的路径(去掉 `.py`,子目录使用 `/` 连接),便于快速定位语义相关模块。
- 每个模块顶部都会自动插入 `module_name:All` 选项,并且所有模块的 `All` 条目按照字典序排在列表最前。选择该项时会在解析阶段展开为该模块下的所有函数,顺序同样遵循字典序。
- `module_name:All` 只能批量引入函数,禁止同时填写 `description``parameters``auto_fill` 等覆盖字段;若需要自定义,请展开后针对具体函数单独配置。
- 函数与模块都采用全局字典序排列,使长列表更易检索;YAML 中仍然以真实函数名落盘,`module_name:All` 仅作为输入辅助。
## 2. 函数目录要求
- 路径:`functions/function_calling/`(可通过 `MAC_FUNCTIONS_DIR` 覆盖)。
- 每个函数:
- 必须位于模块顶层。
- 使用 Python 类型注解;若需枚举或描述,可使用 `typing.Annotated[..., ParamMeta(...)]`
- 不允许以 `_` 开头的参数暴露给 Agent`*_args``**kwargs` 会被过滤。
- 可以通过 docstring 的首段提供描述(自动截断为 600 字符)。
- `utils/function_catalog.py` 会在启动时生成 JSON Schema,并向前端/CLI 暴露。
## 3. 上下文注入
执行器会对被调用的函数提供 `_context` 关键字参数,包含:
| 键 | 值 |
| --- | --- |
| `attachment_store` | `utils.attachments.AttachmentStore` 实例,可查询/注册附件。|
| `python_workspace_root` | 当前 Session 的 `code_workspace/`。|
| `graph_directory` | Session 根目录,可推导相对路径。|
| `human_prompt` | `utils.human_prompt.HumanPromptService`,可调用 `request()` 触发人工反馈。|
| 其他 | 视运行环境扩展,例如 `session_id``node_id`。|
函数可声明 `_context: dict | None = None` 并自行解析(参考 `functions/function_calling/file.py` 中的 `FileToolContext`,还可参考 `functions/function_calling/user.py`)。
## 4. 示例:文件读取工具
```python
from typing import Annotated
from utils.function_catalog import ParamMeta
def read_text_file(
path: Annotated[str, ParamMeta(description="workspace 相对路径")],
*,
encoding: str = "utf-8",
_context: dict | None = None,
) -> str:
ctx = FileToolContext(_context)
target = ctx.resolve_under_workspace(path)
return target.read_text(encoding=encoding)
```
在 YAML 中引用:
```yaml
nodes:
- id: summarize
type: agent
config:
tooling:
type: function
config:
tools:
- name: describe_available_files
- name: read_text_file
```
## 5. 扩展流程
1.`functions/function_calling/` 新建模块或函数。
2. 使用类型注解 + `ParamMeta` 描述参数;如需禁止自动 Schema,可设置 `auto_fill: false` 并提供手写 `parameters`
3. 若函数依赖额外第三方库,可在仓库 `requirements.txt`/`pyproject.toml` 中声明,或在函数内调用 `install_python_packages`(同目录提供)动态安装。
4. 运行 `python -m tools.export_design_template ...` 以刷新前端枚举。
## 6. 调试与排错
- 若前端/CLI 报告 “function 'xxx' not found”,检查函数名称与文件是否位于 `MAC_FUNCTIONS_DIR`(默认 `functions/function_calling/`)。
- `function_catalog` 加载失败时,`FunctionToolEntryConfig.field_specs()` 会在描述中提示错误,请先修复函数语法或依赖。
- 工具运行超时会向 Agent 返回异常文本;可通过 `timeout` 扩大限额,或在函数内部自行捕获并返回友好错误。
+168
View File
@@ -0,0 +1,168 @@
# 内置 Function 工具目录
本文档列出 `functions/function_calling/` 目录中预置的所有工具,供 Agent 节点通过 Function Tooling 调用。
## 快速导入
在 YAML 中可通过以下方式引用:
```yaml
tooling:
- type: function
config:
tools:
- name: file:All # 导入整个模块
- name: save_file # 导入单个函数
- name: deep_research:All
```
---
## 文件操作 (file.py)
文件与目录操作工具集,用于在 `code_workspace/` 中进行文件管理。
| 函数 | 说明 |
|------|------|
| `describe_available_files` | 列出附件仓库和 code_workspace 中的可用文件 |
| `list_directory` | 列出指定目录内容 |
| `create_folder` | 创建文件夹(支持多级目录) |
| `delete_path` | 删除文件或目录 |
| `load_file` | 加载文件并注册为附件,支持多模态(文本/图片/音频) |
| `save_file` | 保存文本内容到文件 |
| `read_text_file_snippet` | 读取文本片段(offset + limit),适合大文件 |
| `read_file_segment` | 按行范围读取文件,支持行号元数据 |
| `apply_text_edits` | 应用多处文本编辑,保留换行符和编码 |
| `rename_path` | 重命名文件或目录 |
| `copy_path` | 复制文件或目录树 |
| `move_path` | 移动文件或目录 |
| `search_in_files` | 在工作区文件中搜索文本或正则模式 |
**示例 YAML**[ChatDev_v1.yaml](../../../../../yaml_instance/ChatDev_v1.yaml)、[file_tool_use_case.yaml](../../../../../yaml_instance/file_tool_use_case.yaml)
---
## Python 环境管理 (uv_related.py)
使用 uv 管理 Python 环境和依赖。
| 函数 | 说明 |
|------|------|
| `install_python_packages` | 使用 `uv add` 安装 Python 包 |
| `init_python_env` | 初始化 Python 环境(uv lock + venv |
| `uv_run` | 在工作区内执行 uv run,运行模块或脚本 |
**示例 YAML**[ChatDev_v1.yaml](../../../../../yaml_instance/ChatDev_v1.yaml)
---
## 深度研究 (deep_research.py)
搜索结果管理与报告生成工具,适用于自动化研究场景。
### 搜索结果管理
| 函数 | 说明 |
|------|------|
| `search_save_result` | 保存或更新搜索结果(URL、标题、摘要、详情) |
| `search_load_all` | 加载所有已保存的搜索结果 |
| `search_load_by_url` | 按 URL 加载特定搜索结果 |
| `search_high_light_key` | 为搜索结果保存高亮关键词 |
### 报告管理
| 函数 | 说明 |
|------|------|
| `report_read` | 读取报告完整内容 |
| `report_read_chapter` | 读取特定章节(支持多级路径如 `Intro/Background` |
| `report_outline` | 获取报告大纲(标题层级结构) |
| `report_create_chapter` | 创建新章节 |
| `report_rewrite_chapter` | 重写章节内容 |
| `report_continue_chapter` | 追加内容到现有章节 |
| `report_reorder_chapters` | 重新排序章节 |
| `report_del_chapter` | 删除章节 |
| `report_export_pdf` | 导出报告为 PDF |
**示例 YAML**[deep_research_v1.yaml](../../../../../yaml_instance/deep_research_v1.yaml)
---
## 网络工具 (web.py)
网络搜索与网页内容获取。
| 函数 | 说明 |
|------|------|
| `web_search` | 使用 Serper.dev 执行网络搜索,支持分页和多语言 |
| `read_webpage_content` | 使用 Jina Reader 读取网页内容,支持速率限制 |
**环境变量**
- `SERPER_DEV_API_KEY`Serper.dev API 密钥
- `JINA_API_KEY`:Jina API 密钥(可选,无密钥时自动限速 20 RPM)
**示例 YAML**[deep_research_v1.yaml](../../../../../yaml_instance/deep_research_v1.yaml)
---
## 视频工具 (video.py)
Manim 动画渲染与视频处理。
| 函数 | 说明 |
|------|------|
| `render_manim` | 渲染 Manim 脚本,自动检测场景类并输出视频 |
| `concat_videos` | 使用 FFmpeg 拼接多个视频文件 |
**示例 YAML**[teach_video.yaml](../../../../../yaml_instance/teach_video.yaml)、[teach_video.yaml](../../../../../yaml_instance/teach_video.yaml)
---
## 代码执行 (code_executor.py)
| 函数 | 说明 |
|------|------|
| `execute_code` | 执行 Python 代码字符串,返回 stdout 和 stderr |
> ⚠️ **安全提示**:此工具具有高权限,应仅在可信工作流内使用。
---
## 用户交互 (user.py)
| 函数 | 说明 |
|------|------|
| `call_user` | 向用户发送指令并获取响应,用于需要人工输入的场景 |
---
## 天气查询 (weather.py)
示例工具,用于演示 Function Calling 流程。
| 函数 | 说明 |
|------|------|
| `get_city_num` | 返回城市编号(硬编码示例) |
| `get_weather` | 根据城市编号返回天气信息(硬编码示例) |
---
## 添加自定义工具
1.`functions/function_calling/` 目录下创建 Python 文件
2. 使用类型注解定义参数:
```python
from typing import Annotated
from utils.function_catalog import ParamMeta
def my_tool(
param1: Annotated[str, ParamMeta(description="参数描述")],
*,
_context: dict | None = None, # 可选,系统自动注入
) -> str:
"""函数描述(会显示给 LLM"""
return "result"
```
3. 重启后端服务器
4. 在 Agent 节点中通过 `name: my_tool``name: my_module:All` 引用
+92
View File
@@ -0,0 +1,92 @@
# MCP Tooling 指南
MCP 工具被明确拆分为 **Remote (HTTP)****Local (stdio)** 两种模式,对应 `tooling.type: mcp_remote``tooling.type: mcp_local`。旧的 `type: mcp` schema 已下线,请在 YAML 与文档中全部迁移。
## 1. 配置模式概览
| 模式 | Tooling type | 适用场景 | 关键字段 |
| --- | --- | --- | --- |
| Remote | `mcp_remote` | 已部署的 HTTP(S) MCP 服务器(如 FastMCP、Claude Desktop Connector、自建代理) | `server``headers``timeout` |
| Local | `mcp_local` | 通过 stdio 握手的本地可执行脚本(Blender MCP、CLI 工具等) | `command``args``cwd``env` 等进程字段 |
## 2. `McpRemoteConfig` 字段
| 字段 | 说明 |
| --- | --- |
| `server` | 必填,MCP HTTP(S) 端点,例如 `https://api.example.com/mcp`。 |
| `headers` | 可选,附加 HTTP 头(如 `Authorization`)。 |
| `timeout` | 可选,单次工具调用超时时间(秒)。 |
**YAML 示例:**
```yaml
nodes:
- id: remote_mcp
type: agent
config:
tooling:
type: mcp_remote
config:
server: https://mcp.mycompany.com/mcp
headers:
Authorization: Bearer ${MY_MCP_TOKEN}
timeout: 15
```
DevAll 会在列举/调用工具时连接该 URL,并携带 `headers`。若服务器不可达,将直接抛出错误,不再尝试本地回退。
## 3. `McpLocalConfig` 字段
`mcp_local` 直接在 `config` 下声明进程参数:
- `command` / `args`:可执行文件与参数(如 `uvx blender-mcp`)。
- `cwd`:可选工作目录。
- `env` / `inherit_env`:定制子进程环境;默认继承父进程后再覆盖。
- `startup_timeout`:等待 `wait_for_log` 命中的最长秒数。
- `wait_for_log`:stdout 正则,用于判定“就绪”。
**YAML 示例:**
```yaml
nodes:
- id: local_mcp
type: agent
config:
tooling:
type: mcp_local
config:
command: uvx
args:
- blender-mcp
cwd: ${REPO_ROOT}
wait_for_log: "MCP ready"
startup_timeout: 8
```
运行期间 DevAll 会保持该进程常驻,并通过 stdio 传输 MCP 数据帧。
## 4. FastMCP 示例服务器
`mcp_example/mcp_server.py`
```python
from fastmcp import FastMCP
import random
mcp = FastMCP("Company Simple MCP Server", debug=True)
@mcp.tool
def rand_num(a: int, b: int) -> int:
return random.randint(a, b)
if __name__ == "__main__":
mcp.run()
```
启动:
```bash
uv run fastmcp run mcp_example/mcp_server.py --transport streamable-http --port 8010
```
- 若以 Remote 模式使用,只需将 `server` 指向 `http://127.0.0.1:8010/mcp`
- 若以 Local 模式使用,可将 `command` 设置为 `uv run fastmcp run ...` 并保持 `transport=stdio`
## 5. 安全与运维
- **网络暴露**Remote 模式建议置于 HTTPS 反向代理之后,并结合 API Key/ACL;Local 模式进程仍可访问宿主机文件,请限制其权限。
- **资源回收**Local 模式由 DevAll 负责终止子进程,确保脚本可以正确处理 SIGTERM/SIGKILL。
- **日志定位**:为 `wait_for_log` 输出清晰的“ready”日志,便于在超时时排查。
- **鉴权**Remote 模式通过 `headers` 传递 TokenLocal 模式可在 `env` 中注入密钥,注意不要写入仓库。
- **多会话**:MCP 服务若不支持多客户端,可在模型或工具层设置 `max_concurrency=1` 并在 YAML 中复用同一配置。
## 6. 调试步骤
1. Remote:使用 curl 或 `fastmcp client` 测试 HTTP 端点;Local:先单独运行并确认 stdout 中有 `wait_for_log` 匹配的文本。
2. 启动 DevAll(可加 `--reload`),观察后端日志是否打印工具清单。
3. 若调用失败,查看 Web UI 中的工具请求/响应,或在 `logs/` 中搜索对应 session 的结构化日志。
+186
View File
@@ -0,0 +1,186 @@
# Agent 节点
Agent 节点是 DevAll 平台中最核心的节点类型,用于调用大语言模型 (LLM) 完成文本生成、对话、推理等任务。它支持多种模型提供商(OpenAI、Gemini 等),并可配置工具调用、思维链、记忆等高级功能。
## 配置项
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| `provider` | string | 是 | `openai` | 模型提供商名称,如 `openai``gemini` |
| `name` | string | 是 | - | 模型名称,如 `gpt-4o``gemini-2.0-flash-001` |
| `role` | text | 否 | - | 系统提示词 (System Prompt) |
| `base_url` | string | 否 | 提供商默认 | API 端点 URL,支持 `${VAR}` 占位符 |
| `api_key` | string | 否 | - | API 密钥,建议使用环境变量 `${API_KEY}` |
| `params` | dict | 否 | `{}` | 模型调用参数(temperature、top_p 等) |
| `tooling` | object | 否 | - | 工具调用配置,详见 [Tooling 模块](../modules/tooling/README.md) |
| `thinking` | object | 否 | - | 思维链配置,如 chain-of-thought、reflection |
| `memories` | list | 否 | `[]` | 记忆绑定配置,详见 [Memory 模块](../modules/memory.md) |
| `skills` | object | 否 | - | Agent Skills 发现配置,以及内置的技能激活/文件读取工具 |
| `retry` | object | 否 | - | 自动重试策略配置 |
### 重试策略配置 (retry)
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `enabled` | bool | `true` | 是否启用自动重试 |
| `max_attempts` | int | `5` | 最大尝试次数(含首次) |
| `min_wait_seconds` | float | `1.0` | 最小退避等待时间 |
| `max_wait_seconds` | float | `6.0` | 最大退避等待时间 |
| `retry_on_status_codes` | list[int] | `[408,409,425,429,500,502,503,504]` | 触发重试的 HTTP 状态码 |
### Agent Skills 配置 (skills)
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `enabled` | bool | `false` | 是否为该节点启用 Agent Skills |
| `allow` | list[object] | `[]` | 可选的技能白名单,来源于项目级 `.agents/skills/` 目录;每个条目使用 `name` |
### Agent Skills 说明
- 技能统一从固定的项目级 `.agents/skills/` 目录中发现。
- 运行时会暴露两个内置技能工具:`activate_skill``read_skill_file`
- `read_skill_file` 只有在对应技能已经激活后才可用。
- 技能 `SKILL.md` 的 frontmatter 可以包含可选的 `allowed-tools`,格式遵循 Agent Skills 规范,例如 `allowed-tools: execute_code`
- 如果某个已选择技能依赖的工具没有绑定到当前节点,该技能会在运行时被跳过。
- 如果最终没有任何兼容技能可用,Agent 会被明确告知不要声称自己使用了技能。
## 何时使用
- **文本生成**:写作、翻译、摘要、问答等
- **智能对话**:多轮对话、客服机器人
- **工具调用**:让模型调用外部 API 或执行函数
- **复杂推理**:配合 thinking 配置进行深度思考
- **知识检索**:配合 memories 实现 RAG 模式
## 示例
### 基础配置
```yaml
nodes:
- id: Writer
type: agent
config:
provider: openai
base_url: ${BASE_URL}
api_key: ${API_KEY}
name: gpt-4o
role: |
你是一位专业的技术文档撰写者,请用清晰简洁的语言回答问题。
params:
temperature: 0.7
max_tokens: 2000
```
### 配置工具调用
```yaml
nodes:
- id: Assistant
type: agent
config:
provider: openai
name: gpt-4o
api_key: ${API_KEY}
tooling:
type: function # 工具类型:function, mcp_remote, mcp_local
config:
tools: # 函数工具列表,来自 functions/function_calling/ 目录
- name: describe_available_files
- name: load_file
timeout: 20 # 可选:执行超时(秒)
```
### 配置 MCP 工具(Remote HTTP
```yaml
nodes:
- id: MCP Agent
type: agent
config:
provider: openai
name: gpt-4o
api_key: ${API_KEY}
tooling:
type: mcp_remote
config:
server: http://localhost:8080/mcp # MCP 服务器端点
headers: # 可选:自定义请求头
Authorization: Bearer ${MCP_TOKEN}
timeout: 30 # 可选:请求超时(秒)
```
### 配置 MCP 工具(Local stdio
```yaml
nodes:
- id: Local MCP Agent
type: agent
config:
provider: openai
name: gpt-4o
api_key: ${API_KEY}
tooling:
type: mcp_local
config:
command: uvx # 启动命令
args: ["mcp-server-sqlite", "--db-path", "data.db"]
cwd: ${WORKSPACE} # 可选,一般不需要配置
env: # 可选,一般不需要配置
DEBUG: "true"
startup_timeout: 10 # 可选:启动超时(秒)
```
### Gemini 多模态配置
```yaml
nodes:
- id: Vision Agent
type: agent
config:
provider: gemini
base_url: https://generativelanguage.googleapis.com
api_key: ${GEMINI_API_KEY}
name: gemini-2.5-flash-image
role: 你需要根据用户的输入,生成相应的图像内容。
```
### 配置重试策略
```yaml
nodes:
- id: Robust Agent
type: agent
config:
provider: openai
name: gpt-4o
api_key: ${API_KEY}
retry: # retry 默认启用,可以自己配置
enabled: true
max_attempts: 3
min_wait_seconds: 2.0
max_wait_seconds: 10.0
```
### 配置 Agent Skills
```yaml
nodes:
- id: Skilled Agent
type: agent
config:
provider: openai
name: gpt-4o
api_key: ${API_KEY}
skills:
enabled: true
allow:
- name: python-scratchpad
- name: rest-api-caller
```
## 相关文档
- [Tooling 模块配置](../modules/tooling/README.md)
- [Memory 模块配置](../modules/memory.md)
- [工作流编排指南](../workflow_authoring.md)
+114
View File
@@ -0,0 +1,114 @@
# Human 节点
Human 节点用于在工作流执行过程中引入人工交互,允许用户在 Web UI 中查看当前状态并提供输入。这种节点会阻塞工作流执行,直到用户提交响应。
## 配置项
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| `description` | text | 否 | - | 显示给用户的任务描述,说明需要人工完成的操作 |
## 核心概念
### 阻塞等待机制
当工作流执行到 Human 节点时:
1. 工作流暂停,等待人工输入
2. Web UI 显示当前上下文和任务描述
3. 用户在界面中输入响应
4. 工作流继续执行,将用户输入传递给下游节点
### 与 Web UI 交互
- Human 节点在 Launch 界面以对话形式呈现
- 用户可以查看之前的执行历史
- 支持附件上传(如文件、图片)
## 何时使用
- **审核确认**:让人工审核 LLM 输出后继续
- **修改意见**:收集用户对生成内容的修改建议
- **关键决策**:需要人工判断才能继续的分支
- **数据补充**:需要用户提供额外信息
- **质量把关**:在关键节点引入人工质检
## 示例
### 基础配置
```yaml
nodes:
- id: Human Reviewer
type: human
config:
description: 请审阅上述内容,如满意请输入 ACCEPT,否则输入修改意见。
```
### 人机协作循环
```yaml
nodes:
- id: Article Writer
type: agent
config:
provider: openai
name: gpt-4o
api_key: ${API_KEY}
role: 你是一位专业作家,根据用户要求撰写文章。
- 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: false
```
### 多阶段审核
```yaml
nodes:
- id: Draft Generator
type: agent
config:
provider: openai
name: gpt-4o
- id: Content Review
type: human
config:
description: 请审核内容准确性,输入 APPROVED 或修改意见。
- id: Final Reviewer
type: human
config:
description: 最终确认,输入 PUBLISH 发布或 REJECT 驳回。
edges:
- from: Draft Generator
to: Content Review
- from: Content Review
to: Final Reviewer
condition:
type: keyword
config:
any: [APPROVED]
```
## 最佳实践
-`description` 中清晰说明期望的操作和关键词
- 使用条件边配合关键词实现流程控制
- 考虑添加超时机制避免工作流无限等待
+140
View File
@@ -0,0 +1,140 @@
# Literal 节点
Literal 节点用于输出固定的文本内容。当节点被触发时,它会忽略所有输入,直接输出预定义的消息。
## 配置项
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| `content` | text | 是 | - | 输出的固定文本内容,不能为空 |
| `role` | string | 否 | `user` | 消息角色:`user``assistant` |
## 核心概念
### 固定输出
Literal 节点的特点:
- **忽略输入**:不管上游传入什么内容,都不影响输出
- **固定内容**:每次执行都输出相同的 `content`
- **角色标记**:输出消息带有指定的角色标识
### 消息角色
- `user`:表示这是用户发出的消息
- `assistant`:表示这是助手(AI)发出的消息
角色设置会影响下游节点对消息的处理方式。
## 何时使用
- **固定提示注入**:向流程中注入固定的指令或上下文
- **测试调试**:使用固定输入测试下游节点
- **默认响应**:在特定条件下返回固定消息
- **流程初始化**:作为工作流的起点提供初始内容
## 示例
### 基础用法
```yaml
nodes:
- id: Welcome Message
type: literal
config:
content: |
欢迎使用智能助手!请描述您的需求。
role: assistant
```
### 注入固定上下文
```yaml
nodes:
- id: Context Injector
type: literal
config:
content: |
请注意以下规则:
1. 回答必须简洁明了
2. 使用中文回复
3. 如有不确定,请说明
role: user
- id: Assistant
type: agent
config:
provider: openai
name: gpt-4o
edges:
- from: Context Injector
to: Assistant
```
### 条件分支中的固定响应
```yaml
nodes:
- id: Classifier
type: agent
config:
provider: openai
name: gpt-4o
role: 判断用户意图,回复 KNOWN 或 UNKNOWN
- id: Known Response
type: literal
config:
content: 我能帮助您完成这个任务。
role: assistant
- id: Unknown Response
type: literal
config:
content: 抱歉,我无法理解您的请求,请换一种方式描述。
role: assistant
edges:
- from: Classifier
to: Known Response
condition:
type: keyword
config:
any: [KNOWN]
- from: Classifier
to: Unknown Response
condition:
type: keyword
config:
any: [UNKNOWN]
```
### 测试用途
```yaml
nodes:
- id: Test Input
type: literal
config:
content: |
这是一段测试文本,用于验证下游处理逻辑。
包含多行内容。
role: user
- id: Processor
type: python
config:
timeout_seconds: 30
edges:
- from: Test Input
to: Processor
start: [Test Input]
```
## 注意事项
- `content` 字段不能为空字符串
- 使用 YAML 多行字符串语法 `|` 便于编写长文本
- 选择正确的 `role` 以确保下游节点正确处理消息
+153
View File
@@ -0,0 +1,153 @@
# Loop Counter 节点
Loop Counter 节点是一种循环控制节点,用于限制工作流中环路的执行次数。它通过计数机制,在达到预设上限前抑制输出,达到上限后才释放消息触发出边,从而终止循环。
## 配置项
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| `max_iterations` | int | 是 | `10` | 最大循环次数,必须 ≥ 1 |
| `reset_on_emit` | bool | 否 | `true` | 达到上限后是否重置计数器 |
| `message` | text | 否 | - | 达到上限时发送给下游的消息内容 |
## 核心概念
### 工作原理
Loop Counter 节点维护一个内部计数器,其行为如下:
1. **每次被触发时**:计数器 +1
2. **计数器 < `max_iterations`**:**不产生任何输出**,出边不会被触发
3. **计数器 = `max_iterations`**:产生输出消息,触发出边
这种"抑制-释放"机制使得 Loop Counter 可以精确控制循环何时终止。
### 拓扑结构要求
Loop Counter 节点在图结构中有特殊的位置要求:
```
┌──────────────────────────────────────┐
▼ │
Agent ──► Human ─────► Loop Counter ──┬──┘
▲ │ │
└─────────┘ ▼
End Node (环外)
```
> **重要**:由于 Loop Counter **未达上限时不产生任何输出**,因此:
> - **Human 必须同时连接到 Agent 和 Loop Counter**:这样"继续循环"的边由 Human → Agent 承担,而 Loop Counter 仅负责计数
> - **Loop Counter 必须连接到 Agent(环内)**:使其被识别为环内节点,避免提前终止环路
> - **Loop Counter 必须连接到 End Node(环外)**:当达到上限时触发环外节点,终止整个环的执行
### 计数器状态
- 计数器状态在整个工作流执行期间持久化
-`reset_on_emit: true` 时,达到上限后计数器重置为 0
-`reset_on_emit: false` 时,达到上限后继续累计,后续每次触发都会输出
## 何时使用
- **防止无限循环**:为人机交互循环设置安全上限
- **迭代控制**:限制 Agent 自我迭代改进的最大轮次
- **超时保护**:作为流程执行的"熔断器"
## 示例
### 基础用法
```yaml
nodes:
- id: Iteration Guard
type: loop_counter
config:
max_iterations: 5
reset_on_emit: true
message: 已达到最大迭代次数,流程终止。
```
### 人机交互循环保护
这是 Loop Counter 最典型的使用场景:
```yaml
graph:
id: review_loop
description: 带迭代上限的审稿循环
nodes:
- id: Writer
type: agent
config:
provider: openai
name: gpt-4o
role: 根据用户反馈改进文章
- id: Reviewer
type: human
config:
description: |
审阅文章,输入 ACCEPT 接受或提供修改意见。
- id: Loop Guard
type: loop_counter
config:
max_iterations: 3
message: 已达到最大修改次数(3次),流程自动结束。
- id: Final Output
type: passthrough
config: {}
edges:
# 主循环:Writer -> Reviewer
- from: Writer
to: Reviewer
# 条件1:用户输入 ACCEPT -> 结束
- from: Reviewer
to: Final Output
condition:
type: keyword
config:
any: [ACCEPT]
# 条件2:用户输入修改意见 -> 同时触发 Writer 继续循环 AND Loop Guard 计数
- from: Reviewer
to: Writer
condition:
type: keyword
config:
none: [ACCEPT]
- from: Reviewer
to: Loop Guard
condition:
type: keyword
config:
none: [ACCEPT]
# Loop Guard 连接到 Writer(使其保持在环内)
- from: Loop Guard
to: Writer
# Loop Guard 达到上限时:触发 Final Output 结束流程
- from: Loop Guard
to: Final Output
start: [Writer]
end: [Final Output]
```
**执行流程说明**
1. 用户首次输入修改意见 → 同时触发 Writer(继续循环)和 Loop Guard(计数 1,无输出)
2. 用户再次输入修改意见 → 同时触发 Writer(继续循环)和 Loop Guard(计数 2,无输出)
3. 用户第三次输入修改意见 → Writer 继续执行,Loop Guard 计数 3 达到上限,输出消息触发 Final Output,终止环路
4. 或者在任意时刻用户输入 ACCEPT → 直接到 Final Output 结束
## 注意事项
- `max_iterations` 必须为正整数(≥ 1
- Loop Counter **未达上限时不产生任何输出**,出边不会触发
- 确保 Loop Counter 同时连接环内节点和环外节点
- `message` 字段可选,默认消息为 `"Loop limit reached (N)"`
+206
View File
@@ -0,0 +1,206 @@
# Passthrough 节点
Passthrough 节点是最简单的节点类型,它不执行任何操作,仅将接收到的消息传递给下游节点。默认情况下只传递**最后一条消息**。它主要用于图结构的"理线"优化和上下文控制。
## 配置项
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| `only_last_message` | bool | 否 | `true` | 是否只传递最后一条消息。设为 `false` 时传递所有消息。 |
### 基本配置
```yaml
config: {} # 使用默认配置,只传递最后一条消息
```
### 传递所有消息
```yaml
config:
only_last_message: false # 传递所有接收到的消息
```
## 核心概念
### 透传行为
- 接收上游传入的所有消息
- **默认只传递最后一条消息**`only_last_message: true`
- 设置 `only_last_message: false` 时传递所有消息
- 不做任何内容处理或转换
### 图结构优化
Passthrough 节点的核心价值不在于数据处理,而在于**图结构的优化**("理线"):
- 使复杂的边连接更加清晰
- 集中管理出边配置(如 `keep_message`
- 作为逻辑分界点,提高工作流可读性
## 关键用途
### 1. 作为起始节点保留初始上下文
将 Passthrough 作为工作流的入口节点,配合边的 `keep_message: true` 配置,可以确保用户的初始任务始终保留在上下文中,不会被后续节点的输出覆盖:
```yaml
nodes:
- id: Task Keeper
type: passthrough
config: {}
- id: Worker A
type: agent
config:
provider: openai
name: gpt-4o
- id: Worker B
type: agent
config:
provider: openai
name: gpt-4o
edges:
# 从入口分发任务,保留原始消息
- from: Task Keeper
to: Worker A
keep_message: true # 保留初始任务上下文
- from: Task Keeper
to: Worker B
keep_message: true
start: [Task Keeper]
```
**效果**Worker A 和 Worker B 都能看到用户的原始输入,而不仅仅是上一个节点的输出。
### 2. 过滤循环中的冗余输出
在包含循环的工作流中,循环内的节点可能产生大量中间输出。如果将所有输出都传递给后续节点,会导致上下文膨胀。使用 Passthrough 节点可以**只传递循环的最终结果**:
```yaml
nodes:
- id: Iterative Improver
type: agent
config:
provider: openai
name: gpt-4o
role: 根据反馈不断改进输出
- id: Evaluator
type: agent
config:
provider: openai
name: gpt-4o
role: |
评估输出质量,回复 GOOD 或提供改进建议
- id: Result Filter
type: passthrough
config: {}
- id: Final Processor
type: agent
config:
provider: openai
name: gpt-4o
role: 对最终结果进行后处理
edges:
- from: Iterative Improver
to: Evaluator
# 循环:评估不通过时回到改进节点
- from: Evaluator
to: Iterative Improver
condition:
type: keyword
config:
none: [GOOD]
# 循环结束:通过 Passthrough 过滤,只传递最后一条
- from: Evaluator
to: Result Filter
condition:
type: keyword
config:
any: [GOOD]
- from: Result Filter
to: Final Processor
start: [Iterative Improver]
end: [Final Processor]
```
**效果**:无论循环迭代多少次,`Final Processor` 只会收到 `Evaluator` 的最后一条输出(表示质量通过的那条),而不是所有中间结果。
## 其他用途
- **占位符**:在设计阶段预留节点位置
- **条件分支**:配合条件边实现路由逻辑
- **调试观察点**:在流程中插入便于观察的节点
## 示例
### 基础用法
```yaml
nodes:
- id: Router
type: passthrough
config: {}
```
### 条件路由
```yaml
nodes:
- id: Classifier
type: agent
config:
provider: openai
name: gpt-4o
role: |
分类输入内容,回复 TECHNICAL 或 BUSINESS
- id: Router
type: passthrough
config: {}
- id: Tech Handler
type: agent
config:
provider: openai
name: gpt-4o
- id: Biz Handler
type: agent
config:
provider: openai
name: gpt-4o
edges:
- from: Classifier
to: Router
- from: Router
to: Tech Handler
condition:
type: keyword
config:
any: [TECHNICAL]
- from: Router
to: Biz Handler
condition:
type: keyword
config:
any: [BUSINESS]
```
## 最佳实践
- 使用有意义的节点 ID 描述其拓扑作用(如 `Task Keeper``Result Filter`
- 作为入口节点时,出边配置 `keep_message: true` 保留上下文
- 在循环后使用,可以过滤掉冗余的中间输出
+89
View File
@@ -0,0 +1,89 @@
# Python 节点
Python 节点用于在工作流中执行 Python 脚本或内联代码,实现自定义数据处理、API 调用、文件操作等逻辑。脚本在共享的 `code_workspace/` 目录中执行,可访问工作流上下文数据。
## 配置项
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| `interpreter` | string | 否 | 当前 Python | Python 解释器路径 |
| `args` | list[str] | 否 | `[]` | 追加到解释器后的启动参数 |
| `env` | dict[str, str] | 否 | `{}` | 额外环境变量,会覆盖系统默认值 |
| `timeout_seconds` | int | 否 | `60` | 脚本执行超时时间(秒) |
| `encoding` | string | 否 | `utf-8` | 解析 stdout/stderr 的编码 |
## 核心概念
### 代码工作区
Python 脚本在 `code_workspace/` 目录下执行:
- 脚本可以读写该目录中的文件
- 多个 Python 节点共享同一工作区
- 工作区在单次工作流执行期间持久化
### 输入输出
- **输入**:上游节点的输出作为环境变量或标准输入传递
- **输出**:脚本的 stdout 输出将作为 Message 传递给下游节点
## 何时使用
- **数据处理**:解析 JSON/XML、数据转换、格式化
- **API 调用**:调用第三方服务、获取外部数据
- **文件操作**:读写文件、生成报告
- **复杂计算**:数学运算、算法实现
- **胶水逻辑**:连接不同节点的自定义逻辑
## 示例
### 基础配置
```yaml
nodes:
- id: Data Processor
type: python
config:
timeout_seconds: 120
env:
key: value
```
### 指定解释器和参数
```yaml
nodes:
- id: Script Runner
type: python
config:
interpreter: /usr/bin/python3.11
timeout_seconds: 300
encoding: utf-8
```
### 典型工作流示例
```yaml
nodes:
- id: LLM Generator
type: agent
config:
provider: openai
name: gpt-4o
api_key: ${API_KEY}
role: 你需要根据用户的输入,生成可执行的 Python 代码。代码应当包裹在 ```python ``` 之间。
- id: Result Parser
type: python
config:
timeout_seconds: 30
edges:
- from: LLM Generator
to: Result Parser
```
## 注意事项
- 确保脚本文件放置在 `code_workspace/` 目录下
- 长时间运行的脚本应适当增加 `timeout_seconds`
- 使用 `env` 传递额外的环境变量,可在脚本中通过 `os.getenv` 访问
+138
View File
@@ -0,0 +1,138 @@
# Subgraph 节点
Subgraph 节点允许将另一个工作流图嵌入到当前工作流中,实现流程复用和模块化设计。子图可以来自外部 YAML 文件,也可以直接在配置中内联定义。
## 配置项
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| `type` | string | 是 | - | 子图来源类型:`file``config` |
| `config` | object | 是 | - | 根据 `type` 不同,包含不同的配置 |
### file 类型配置
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `path` | string | 是 | 子图文件路径(相对于 `yaml_instance/` 或绝对路径) |
### config 类型配置
内联定义完整的子图结构,包含与顶层 `graph` 相同的字段:
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `id` | string | 是 | 子图标识符 |
| `description` | string | 否 | 子图描述 |
| `log_level` | string | 否 | 日志级别(DEBUG/INFO |
| `nodes` | list | 是 | 节点列表 |
| `edges` | list | 否 | 边列表 |
| `start` | list | 否 | 入口节点列表 |
| `end` | list | 否 | 出口节点列表 |
| `memory` | list | 否 | 子图专用的 Memory 定义 |
## 核心概念
### 模块化复用
将常用的流程片段抽取为独立的 YAML 文件,多个工作流可以复用同一子图:
- 例如:将"文章润色"流程封装为子图
- 不同的主工作流都可以调用该子图
### 变量继承
子图会继承父图的 `vars` 变量定义,支持跨层级变量传递。
### 执行隔离
子图作为独立单元执行,拥有自己的:
- 节点命名空间
- 日志级别配置
- Memory 定义(可选)
## 何时使用
- **流程复用**:多个工作流共享相同的子流程
- **模块化设计**:将复杂流程拆分为可管理的小单元
- **团队协作**:不同团队维护不同的子图模块
## 示例
### 引用外部文件
```yaml
nodes:
- id: Review Process
type: subgraph
config:
type: file
config:
path: common/review_flow.yaml
```
### 内联定义子图
```yaml
nodes:
- id: Translation Unit
type: subgraph
config:
type: config
config:
id: translation_subgraph
description: 多语言翻译子流程
nodes:
- id: Translator
type: agent
config:
provider: openai
name: gpt-4o
role: 你是一位专业翻译,将内容翻译为目标语言。
- id: Proofreader
type: agent
config:
provider: openai
name: gpt-4o
role: 你是一位校对专家,检查并润色翻译内容。
edges:
- from: Translator
to: Proofreader
start: [Translator]
end: [Proofreader]
```
### 组合多个子图
```yaml
nodes:
- id: Input Handler
type: agent
config:
provider: openai
name: gpt-4o
- id: Analysis Module
type: subgraph
config:
type: file
config:
path: modules/analysis.yaml
- id: Report Module
type: subgraph
config:
type: file
config:
path: modules/report_gen.yaml
edges:
- from: Input Handler
to: Analysis Module
- from: Analysis Module
to: Report Module
```
## 注意事项
- 子图文件路径支持相对路径(基于 `yaml_instance/`)和绝对路径
- 避免循环嵌套(A 引用 B,B 再引用 A)
- 子图的 `start``end` 节点决定了数据如何流入流出,这决定了子图如何处理父图传入的消息,以及以哪个节点的最终输出作为返回给父图的消息。
+99
View File
@@ -0,0 +1,99 @@
# 前端 Web UI 快速入门指南
本指南帮助用户快速上手 DevAll Web UI,涵盖主要功能页面和操作流程。
## 1. 系统入口
启动前后端服务后,访问 `http://localhost:5173` 进入 Web UI。
## 2. 主要页面
### 2.1 首页 (Home)
系统首页,提供快速导航入口。
### 2.2 工作流列表 (Workflow List)
查看和管理所有可用的工作流 YAML 文件。
**功能**
- 浏览 `yaml_instance/` 目录下的工作流
- 预览 YAML 配置内容
- 选择工作流进入执行或编辑
### 2.3 启动页 (Launch View)
工作流执行的主界面,是最常用的页面。
**操作流程**
1. **选择工作流**:从左侧列表选择要执行的 YAML 文件
2. **上传附件**(可选):点击上传按钮添加文件(如 CSV 数据、图片等)
3. **输入任务提示**:在文本框中输入指导工作流执行的提示词
4. **点击 Launch**:启动工作流执行
**执行期间**
- **节点视图**:观察节点状态变化(pending → running → success/failed
- **输出面板**:实时查看执行日志、节点输出上下文和生成的工件(三者共用同一面板)
**人工输入**
- 当执行到 `human` 节点时,界面会显示输入提示
- 填写文本内容或上传附件后提交继续执行
### 2.4 工作流工作台 (Workflow Workbench)
可视化工作流编辑器。
**功能**
- 拖拽式节点编辑
- 节点配置面板
- 边连接与条件设置
- 导出为 YAML 文件
### 2.5 教程页 (Tutorial)
内置教程,帮助新用户了解系统功能。
## 3. 常用操作
### 3.1 运行工作流
1. 进入 **Launch View**
2. 从左侧选择工作流
3. 输入 Task Prompt(任务提示)
4. 点击 **Launch** 按钮
5. 观察执行过程,等待完成
### 3.2 下载运行结果
执行完成后:
1. 点击右侧面板的 **Download** 按钮
2. 下载完整的 Session 压缩包(含 context.json、附件、日志等)
### 3.3 人工审阅节点交互
当工作流包含 `human` 节点时:
1. 执行暂停并显示提示信息
2. 阅读上下文内容
3. 输入审阅意见或操作指令
4. 点击提交继续执行
## 4. 快捷键
| 快捷键 | 功能 |
|--------|------|
| `Ctrl/Cmd + Enter` | 提交输入 |
| `Esc` | 关闭弹窗/面板 |
## 5. 故障排查
| 问题 | 解决方案 |
|------|----------|
| 页面无法加载 | 确认前端服务 `npm run dev` 正常运行 |
| 无法连接后端 | 确认后端服务 `uv run python server_main.py` 正常运行 |
| 工作流列表为空 | 检查 `yaml_instance/` 目录是否有 YAML 文件 |
| 执行无响应 | 检查浏览器开发者工具的 Network/Console 日志 |
| WebSocket 断开 | 刷新页面重新建立连接 |
## 6. 相关文档
- [工作流编排](workflow_authoring.md) - YAML 编写指南
+247
View File
@@ -0,0 +1,247 @@
# 工作流编排指南
本指南聚焦 YAML 结构、节点类型、Provider 配置、边条件与模板导出,帮助工作流作者快速构建与调试 DAG。
## 1. 必备背景
- 熟悉 `yaml_instance/``yaml_template/` 的目录结构。
- 了解基本节点类型(`model``python``agent``human``subgraph``passthrough``literal`)。
- 理解 `FIELD_SPECS`(见 [field_specs.md](field_specs.md))与 Schema API(见 [config_schema_contract.md](config_schema_contract.md))可被前端/IDE 用于动态表单。
## 2. YAML 顶层结构
所有工作流文件都遵循 `DesignConfig` 根结构,仅包含 `version``vars``graph` 三个键。下面示例节选自 `yaml_instance/net_example.yaml`,可以直接运行:
```yaml
version: 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: false
```
- `version`:配置版本号,缺省为 `0.0.0`。当 `entity/configs/graph.py` 中的 Schema 发生破坏性调整时,用于与前端模板和迁移脚本对齐。
- `vars`:根级键值对,可在任意字段使用 `${VAR}` 占位,若未命中则回退到同名环境变量。`GraphDefinition.from_dict` 会拒绝在子图或节点下声明 `vars`,因此请仅在顶层维护。
**环境变量与 `.env` 文件**
系统支持在 YAML 配置中使用 `${VAR}` 语法引用变量。这些变量可用于配置中的任意字符串字段,常见用途包括:
- **API 密钥**`api_key: ${API_KEY}`
- **服务地址**`base_url: ${BASE_URL}`
- **模型名称**`name: ${MODEL_NAME}`
系统在解析配置时会自动加载项目根目录下的 `.env` 文件(若存在)。变量解析的优先级如下:
| 优先级 | 来源 | 说明 |
| --- | --- | --- |
| 1(最高) | `vars` 中显式定义的值 | YAML 文件中直接声明的键值对 |
| 2 | 系统/Shell 环境变量 | 如通过 `export` 设置的值 |
| 3(最低) | `.env` 文件中的值 | 仅当环境变量尚未存在时生效 |
> [!TIP]
> `.env` 文件不会覆盖已存在的环境变量。这意味着您可以在 `.env` 中定义默认值,同时通过 `export` 或部署平台的环境变量配置来覆盖它们。
> [!WARNING]
> 若占位符引用的变量在上述三个来源中均未定义,配置解析时将抛出 `ConfigError` 并指明出错路径。
- `graph`:唯一必填段落,映射到 `GraphDefinition` dataclass。它包含:
- **基础元信息**`id`(必填)、`description``log_level`(默认 `DEBUG`)、`is_majority_voting``initial_instruction`、可选 `organization`
- **执行控制**`start`/`end`(入口出口列表;系统会在启动时执行 `start` 中的节点)、`nodes``edges``nodes``edges` 同步 `entity/configs/node/*.py``entity/configs/edge.py`,所有 Provider、模型、Tooling 配置都挂在 `node.config` 内,不再在顶层维护 `providers` 表。上例通过 `keyword` 条件在 `Human Reviewer -> Article Writer` 边上避免输入 `ACCEPT` 时继续循环。
- **共享资源**`memory`(定义 Memory store 列表,供模型节点的 `config.memories` 引用)。调度器会校验节点引用是否在 `graph.memory` 中声明。
- **Schema 参考**`yaml_template/design.yaml` 会实时反映 `GraphDefinition` 字段,建议在修改后运行 `python -m tools.export_design_template` 或调用 Schema API 校验。
进一步阅读:`docs/user_guide/zh/field_specs.md`(字段精细描述)、`docs/user_guide/zh/runtime_ops.md`(运行期可观测性)、以及 `yaml_template/design.yaml`(自动生成的基准模板)。
## 3. 节点类型速览
| 类型 | 描述 | 关键字段 | 详细文档 |
| --- |------------------------------------------| --- | --- |
| `agent` | 调用 LLM,支持工具、记忆、thinking | `provider`, `model`, `prompt_template`, `tooling`, `thinking`, `memories` | [agent.md](nodes/agent.md) |
| `python` | 执行 Python 代码(脚本或指令),共享 `code_workspace/` | `entry_script`, `inline_code`, `timeout`, `env` | [python.md](nodes/python.md) |
| `human` | 在 Web UI 阻塞等待人工输入 | `prompt`, `timeout`, `attachments` | [human.md](nodes/human.md) |
| `subgraph` | 嵌入子 DAG,复用复杂流程 | `graph_path` 或内联 `graph` | [subgraph.md](nodes/subgraph.md) |
| `passthrough` | 透传节点,默认只传递最后一条消息,可传递所有信息;用于上下文过滤和图结构优化 | `only_last_message` | [passthrough.md](nodes/passthrough.md) |
| `literal` | 被触发时输出固定文本消息,忽略输入 | `content`, `role``user`/`assistant` | [literal.md](nodes/literal.md) |
| `loop_counter` | 限制环路执行次数的控制节点 | `max_iterations`, `reset_on_emit`, `message` | [loop_counter.md](nodes/loop_counter.md) |
详细字段可在前端使用 Schema API (`POST /api/config/schema`) 动态查询,也可参照 `entity/configs/` 中同名 dataclass。
## 4. Provider 与 Agent 设置
- `provider` 字段缺省时,使用 `globals.default_provider`(如 `openai`)。
- `model``api_key``base_url` 等字段支持 `${VAR}` 占位,便于跨环境复用。
- 对接多个 Provider 时,可在 workflow 层设置 `globals`: `{ default_provider: ..., retry: {...} }`(若 dataclass 支持)。
### 4.1 Gemini Provider 配置示例
```yaml
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 支持多模态输入(图片/视频/音频会自动转换为 Part),并支持 `function_calling_config` 来控制工具调用行为。
## 5. 边与条件
- 基本边:
```yaml
- source: plan
target: execute
```
- 条件边:
```yaml
edges:
- source: router
target: analyze
condition:
type: function
config:
name: should_analyze # functions/edge/should_analyze.py
```
- 当 `condition` 抛错时,调度器会记录错误并抛出 `WorkflowExecutionError`,导致该分支(通常是整个运行)终止,后继节点不会继续执行。
- 通过注册中心可以声明更多条件类型,例如内置的 `keyword`(无需写 Python 函数):
```yaml
edges:
- from: review
to: finalize
condition:
type: keyword
config:
any: ["FINAL", "APPROVED"]
none: ["RETRY"]
case_sensitive: false # 默认为 true
```
`condition.type` 的合法值由后端注册中心(使用 `register_edge_condition` 注册)决定,schema 会自动在前端的下拉列表中展示 `summary` 描述。默认的 `function` 类型兼容旧写法(直接填写函数名字符串),未提供配置时等价于 `name: true`。
### 5.1 边级 Payload Processor
- 场景:当条件成立后希望“先处理一下消息”,例如根据正则提取得分、只保留结构化字段或者调用自定义函数对文本重写。
- YAML 字段:在任意边上新增 `process`,结构与 `condition` 相同(`type + config`),目前内置
- `regex_extract`:基于 Python 正则。支持 `pattern`、`group`(名称或序号)、`mode``replace_content`、`metadata`、`data_block`)、`multiple`、`on_no_match``pass`/`default`/`drop`)等字段。
- `function`:调用 `functions/edge_processor/*.py` 中的处理函数。函数签名为 `def foo(payload: Message, **kwargs) -> Message | None`。现在Processor 接口已标准化,`kwargs` 中包含了 `context: ExecutionContext`,可访问当前执行上下文。
- 运行时行为:
- Processor 在条件通过且 `carry_data=true` 时执行,若返回 `None`,该边不会触发也不会向后继节点发送输入。
- 日志中会在 `EDGE_PROCESS` 事件里显示 `process_label`、`process_type`,便于排查。
- 示例:
```yaml
edges:
- 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"
```
## 6. 模型节点高级特性
- **Tooling**:在 `AgentConfig.tooling` 中配置,具体见 [Tooling 模块](modules/tooling/README.md)。
- **Thinking**:在 `AgentConfig.thinking` 中开启,如 `chain-of-thought`、`reflection`(详见 `entity/configs/thinking.py`)。
- **Memories**`AgentConfig.memories` 绑定 `MemoryAttachmentConfig`,详见 [Memory 模块](modules/memory.md)。
## 7. 动态执行 (Map-Reduce/Tree)
节点配置新增同级字段 `dynamic`,用于启用并行处理或 Map-Reduce 模式。
### 7.1 核心概念
- **Map 模式** (`type: map`):扇出(Fan-out)。将 List 输入拆分为多个单元并行执行,输出 `List[Message]`(结果打平)。
- **Tree 模式** (`type: tree`):扇出与归约(Fan-out & Reduce)。将输入拆分并行执行后,按 `group_size` 分组递归归约,最终输出单个结果(如“总结的总结”)。
- **Split 策略**:定义如何将上一节点的输出或当前输入拆分为并行单元。
### 7.2 配置结构
```yaml
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 # 控制并发度
```
### 7.3 Tree 模式示例
适用于长文本分段摘要等场景:
```yaml
dynamic:
type: tree
split:
type: regex
pattern: "(?s).{1,2000}(?:\\s|$)" # 每 2000 字符切分
config:
group_size: 3 # 每 3 个结果归约为 1 个
max_parallel: 10
```
该模式会自动构建多层级执行树,直到结果数量归约为 1。split 配置与 map 模式一致,
## 8. 设计模板导出
任意修改 Config/FIELD_SPECS 后,运行:
```bash
python -m tools.export_design_template \
--output yaml_template/design.yaml \
--mirror frontend/public/design_0.4.0.yaml
```
- 命令会读取注册表(节点、memory、tooling 等)与 `FIELD_SPECS`,自动生成 YAML 模板与前端镜像。
- 更新后请提交模板文件,并通知前端刷新静态资源。
## 9. CLI / API 运行
- **Web UI**:访问前端页面 → 选择 YAML → 填写运行参数 → 启动 → 在面板监控。**我们建议您采用此方式运行。**
- **HTTP**`POST /api/workflow/execute`payload 包含 `session_name`, `graph_path` 或 `graph_content`, `task_prompt`、可选的 `attachments`,以及 `log_level`(默认 `INFO`,支持 `INFO` 或 `DEBUG`)。
- **CLI**`python run.py --path yaml_instance/demo.yaml --name test_run`(执行前可设置 `TASK_PROMPT` 环境变量或在 CLI 提示中输入)。
## 10. 调试建议
- 使用 Web UI 的上下文快照或 WareHouse 中的 `context.json` 检查节点输入输出。注意所有节点输出现已统一为 `List[Message]` 结构。
- 结合 [config_schema_contract.md](config_schema_contract.md) 的 breadcrumbs 功能,用 CLI `python run.py --inspect-schema` 快速查看字段定义。
- 若 YAML 占位符缺失,解析阶段会抛出 `ConfigError`,在 UI/CLI 中都可看到明确路径。