mirror of
https://git.openapi.site/https://github.com/desirecore/market.git
synced 2026-06-06 09:30:42 +08:00
feat: skills i18n 改造(schemaVersion 1.1,零向后兼容) (#1)
* feat: skills i18n 改造 — schemaVersion 1.1,零向后兼容
把 21 个 skills + 1 个 agent + manifest/categories 全量迁移到 schemaVersion 1.1
的 i18n 结构,配套 CI AI 翻译流水线(GitHub Models)与本地工具链。
## 关键变更
### 数据结构(破坏性,schemaVersion 1.0 → 1.1)
- SKILL.md: 顶层 name 改为 ASCII slug(== 目录名,符合 agentskills.io 规范);
中文显示名/short_desc/description 全部迁入 metadata.i18n.<locale>
- agents/<id>/agent.json: shortDesc/fullDesc/tags/persona.{role,traits} 迁入
i18n.<locale>;changelog[].changes 改为 { <locale>: string[] } 对象
- categories.json: 每个分类的 label/description 迁入 i18n.<locale>,顶层只剩
color/icon
- manifest.json: 加 supportedLocales / defaultLocale;顶层 description 迁入
i18n.<locale>
### Body 文件结构
- 根 SKILL.md = frontmatter + default_locale (en-US) body
- SKILL.<locale>.md = 各 locale 的 markdown body(首行 <!-- locale: xx --> 自校验)
### 工具链(scripts/i18n/)
- glossary.json: zh→en 术语表 + do_not_translate 白名单
- schema/skill-frontmatter.schema.json: i18n frontmatter JSON Schema
- validate-i18n.py: 8 条校验规则(name 合规 / locale 完整性 / hash 一致性等)
- translate.py: GitHub Models / Anthropic 双 backend,sha256 增量翻译
- migrate.py: 一次性迁移脚本(旧格式 → i18n 结构)
### CI(.github/workflows/)
- i18n-validate.yml: PR 触发跑 validate + translate --check
- i18n-translate.yml: PR 触发用 GitHub Models(默认 openai/gpt-5-mini)翻译缺失
locale,自动追加 commit;可切到 ANTHROPIC_API_KEY 走 Claude
### 文档
- docs/I18N.md: 作者贡献指南(schema 说明 / 提交流程 / 常见问题)
- README.md: 加多语言段落
## 验证
- uv run scripts/i18n/validate-i18n.py: OK,49 文件 0 错误
- uv run scripts/i18n/translate.py --check: 0 stale locale
- 21 skills 标题数 zh-CN == en-US 严格对齐(最大 66=66)
- skills-ref 规范校验:全部通过(顶层 name ASCII slug + description 单字段)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(i18n): 修复 PR #1 review 反馈的 6 项问题
- schema: translated_by 正则放宽为 ^(human|ai:[A-Za-z0-9._:/-]+)$,接受
'ai:github:openai/gpt-5-mini' 这类 backend:model 形式(CI 翻译输出格式)
- README + docs/I18N.md: 修正"CI 用 Claude API"误导描述,正确说明默认是
GitHub Models(openai/gpt-5-mini)+ GITHUB_TOKEN,可选切到 Anthropic
- skills/minimax-tts/SKILL.md & SKILL.zh-CN.md: 删除多余的 ``` 闭合,避免
Markdown 后续渲染错乱
- skills/docx/SKILL.md: 翻译时丢失的 • Unicode escape 示例已恢复,
与 zh-CN 版本对齐
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
584
skills/workflow/SKILL.zh-CN.md
Normal file
584
skills/workflow/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,584 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# workflow 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
引导 Agent 通过 DSL 设计、编辑、校验、测试和执行多节点自动化工作流。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
workflow 是一个**流程型技能(Procedural Skill)**,赋予 Agent 编排多步骤自动化工作流的能力。工作流以 YAML DSL 文件描述,由引擎按拓扑顺序自动执行。
|
||||
|
||||
**五种基座节点**:
|
||||
|
||||
| 基座 | 用途 | 典型场景 |
|
||||
|------|------|---------|
|
||||
| `trigger` | 工作流入口,声明输入参数 | 手动触发、webhook 触发 |
|
||||
| `code` | 执行代码(JS/Python) | 数据获取、API 调用 |
|
||||
| `llm` | 单次 LLM 调用(无状态) | 文本生成、数据分析、摘要 |
|
||||
| `agent` | 调用完整 Agent(有状态) | 需要 Agent 记忆、工具、技能的复杂任务 |
|
||||
| `human_gate` | 等待用户确认 | 敏感操作审批 |
|
||||
|
||||
### 使用场景
|
||||
|
||||
- 用户想把重复性多步骤工作编排成自动化流程
|
||||
- 用户需要多个 Agent 协作完成一个复杂任务
|
||||
- 用户需要在自动化流程中插入人工审批环节
|
||||
- 用户想复用和分享已验证的工作流程
|
||||
|
||||
### 核心价值
|
||||
|
||||
- **可视化编排**:DSL 描述清晰直观,支持画布可视化
|
||||
- **渐进式构建**:先写骨架再逐步丰富,降低出错概率
|
||||
- **安全门控**:通过 human_gate 节点在关键环节保留人工决策权
|
||||
- **可复用**:DSL 文件可存档、版本管理、跨 Agent 共享
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
### 工作流程 SOP
|
||||
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ 1. 理解意图 │ ──→ │ 2a. 设计拓扑 │ ──→ │ 2b. 逐节点配置 │ ──→ │ 3. 校验 DSL │
|
||||
└──────────────┘ │ (节点骨架) │ │ (config/code)│ └──────────────┘
|
||||
└──────────────┘ └──────────────┘ │
|
||||
↓
|
||||
┌──────────────┐ ┌──────────────┐
|
||||
│ 5. 正式执行 │ ←── │ 4. 干跑测试 │
|
||||
└──────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
### 阶段 1:理解意图
|
||||
|
||||
**触发条件**(任一满足):
|
||||
- 用户明确说"创建一个工作流"或"帮我编排一个流程"
|
||||
- 用户描述一个需要多步骤、多角色协作的任务
|
||||
- 用户想把手动重复的操作自动化
|
||||
|
||||
**收集信息**:
|
||||
|
||||
| 信息 | 说明 | 引导问题 |
|
||||
|------|------|---------|
|
||||
| 目标 | 工作流要完成什么 | "这个流程最终要产出什么?" |
|
||||
| 步骤 | 大致有哪些环节 | "你通常是怎么做的?分几步?" |
|
||||
| 审批 | 哪些环节需要人工确认 | "有哪些步骤需要你亲自过目确认?" |
|
||||
| Agent | 是否需要调用特定 Agent | "有没有已有的 Agent 可以参与?" |
|
||||
|
||||
### 阶段 2:渐进式构建 DSL
|
||||
|
||||
**DSL 文件位置**:
|
||||
|
||||
```
|
||||
~/.desirecore/workflows/<wf_id>/workflow.dsl.yaml
|
||||
```
|
||||
|
||||
其中 `wf_id` 使用 `wf_` 前缀 + snake_case,如 `wf_legal_review`、`wf_daily_report`。
|
||||
|
||||
**构建策略**:严格分两步——先设计节点拓扑,再逐节点填充配置。**禁止在骨架阶段编写节点的 config 和 code 细节。**
|
||||
|
||||
#### 步骤 2a:设计节点拓扑(骨架)
|
||||
|
||||
先与用户对齐整体流程设计,确认后使用 Write 工具一次性创建骨架 DSL 文件。骨架用于对齐拓扑,不要求立即通过 `WorkflowValidate`;最终完整 DSL 写入时优先使用 `WorkflowCreate`。
|
||||
|
||||
**骨架只包含**:
|
||||
- 根字段(version、id、name、description、creator)
|
||||
- 每个节点的 `id`、`base`、`display.name`
|
||||
- 每个节点的 `outputs`(声明变量名和描述)
|
||||
- `flow`(start、edges、end)
|
||||
|
||||
**骨架不包含**:config 内容(code / system_prompt / task / prompt 等)、inputs 引用。
|
||||
|
||||
```yaml
|
||||
# 骨架示例——只有结构,没有实现细节
|
||||
version: "1.0"
|
||||
id: wf_daily_report
|
||||
name: 每日报告生成
|
||||
description: 从多个数据源获取数据,生成日报并审批发送
|
||||
creator: desirecore
|
||||
|
||||
nodes:
|
||||
- id: trigger
|
||||
base: trigger
|
||||
display:
|
||||
name: 手动触发
|
||||
config:
|
||||
type: manual
|
||||
outputs:
|
||||
date:
|
||||
type: string
|
||||
description: "报告日期"
|
||||
required: true
|
||||
|
||||
- id: fetch_data
|
||||
base: code
|
||||
display:
|
||||
name: 获取数据
|
||||
config: {} # 待步骤 2b 填充
|
||||
outputs:
|
||||
raw_data: "原始数据"
|
||||
|
||||
- id: analyze
|
||||
base: llm
|
||||
display:
|
||||
name: AI 分析
|
||||
config: {} # 待步骤 2b 填充
|
||||
outputs:
|
||||
report: "分析报告"
|
||||
|
||||
- id: review
|
||||
base: human_gate
|
||||
display:
|
||||
name: 人工审阅
|
||||
config: {} # 待步骤 2b 填充
|
||||
outputs:
|
||||
decision: "审批决定"
|
||||
comment: "审批备注"
|
||||
|
||||
- id: send
|
||||
base: code
|
||||
display:
|
||||
name: 发送报告
|
||||
config: {} # 待步骤 2b 填充
|
||||
outputs:
|
||||
status: "发送状态"
|
||||
|
||||
flow:
|
||||
start: trigger
|
||||
edges:
|
||||
- { from: trigger, to: fetch_data }
|
||||
- { from: fetch_data, to: analyze }
|
||||
- { from: analyze, to: review }
|
||||
- { from: review, to: send }
|
||||
end: [send]
|
||||
```
|
||||
|
||||
骨架创建后,向用户确认节点设计和流程是否正确,再进入步骤 2b。
|
||||
|
||||
#### 步骤 2b:逐节点填充配置
|
||||
|
||||
按拓扑顺序(从 trigger 开始,沿 edges 方向)逐个节点填充 config 和 inputs。每完成一个节点使用 Edit 工具写入,**不要一次性填充所有节点**。
|
||||
|
||||
**每个节点填充内容**:
|
||||
1. `inputs` — 引用上游节点的输出(`{{nodeId.outputKey}}`)
|
||||
2. `config` — 该基座类型的具体配置:
|
||||
- **code 节点**:编写 `runtime` 和 `code`(完整的可执行代码)
|
||||
- **llm 节点**:编写 `system_prompt`、选择 `model` / `provider`、设置 `temperature` 等参数
|
||||
- **agent 节点**:指定 `agent_id` 和编写 `task` 描述
|
||||
- **human_gate 节点**:编写审批 `prompt`(含 `{{}}` 插值)
|
||||
|
||||
**逐节点填充顺序示例**(以上方骨架为例):
|
||||
|
||||
```
|
||||
1. fetch_data — 编写获取数据的 JS/Python 代码
|
||||
2. analyze — 编写 system_prompt,选择模型,配置 inputs 引用 fetch_data 输出
|
||||
3. review — 编写审批提示词,配置 inputs 引用 analyze 输出
|
||||
4. send — 编写发送逻辑的代码,配置 inputs 引用 review 输出
|
||||
```
|
||||
|
||||
填充完所有节点后进入阶段 3 校验。
|
||||
|
||||
### DSL 编写规范
|
||||
|
||||
#### 根结构
|
||||
|
||||
```yaml
|
||||
version: "1.0" # 固定值
|
||||
id: wf_<snake_case_name> # 必须以 wf_ 前缀开头
|
||||
name: 工作流显示名称 # 人类可读名称
|
||||
description: 工作流用途描述 # 可选,说明适用场景
|
||||
creator: <agent_id> # 创建此工作流的 Agent ID
|
||||
|
||||
nodes: # 节点列表(至少 1 个)
|
||||
- id: ...
|
||||
base: ...
|
||||
...
|
||||
|
||||
flow: # 流程控制
|
||||
start: <起始节点 id>
|
||||
edges:
|
||||
- { from: <节点 id>, to: <节点 id> }
|
||||
end: [<终止节点 id>]
|
||||
```
|
||||
|
||||
#### code 节点配置
|
||||
|
||||
code 节点执行**内联代码**(JS 或 Python),通过 `inputs` 对象访问上游数据,通过 `return` 返回结果。
|
||||
|
||||
```yaml
|
||||
- id: format_data
|
||||
base: code
|
||||
display:
|
||||
name: 格式化数据
|
||||
config:
|
||||
runtime: nodejs # nodejs 或 python
|
||||
timeout_ms: 30000 # 超时毫秒数(可选,默认 30000)
|
||||
code: |
|
||||
// inputs 对象包含所有上游传入的数据
|
||||
const data = JSON.parse(inputs.raw_data)
|
||||
const formatted = data.map(item => ({
|
||||
title: item.title.trim(),
|
||||
date: new Date(item.pubDate).toISOString().slice(0, 10),
|
||||
}))
|
||||
return { formatted: JSON.stringify(formatted) }
|
||||
inputs:
|
||||
raw_data: "{{fetch_node.result}}" # 引用上游节点 fetch_node 的 result 输出
|
||||
outputs:
|
||||
formatted: "格式化后的数据"
|
||||
```
|
||||
|
||||
**config 字段说明**:
|
||||
|
||||
| 字段 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `runtime` | 是 | `nodejs` 或 `python` |
|
||||
| `code` | 是 | 内联代码。JS 通过 `inputs` 对象访问输入,`return` 返回输出对象。Python 同理。 |
|
||||
| `timeout_ms` | 否 | 执行超时(默认 30000ms) |
|
||||
|
||||
**JS 代码注意事项**:
|
||||
- 代码在 `new Function('inputs', ...)` 中执行,支持 `async/await` 和 `fetch`
|
||||
- **不支持 `require()`**,不能导入 Node.js 模块
|
||||
- 通过 `inputs.xxx` 访问输入数据
|
||||
- 必须 `return` 一个对象,其 key 对应 `outputs` 中声明的变量名
|
||||
|
||||
**Python 代码注意事项**:
|
||||
- 通过 `inputs['xxx']` 访问输入数据
|
||||
- 必须 `return` 一个字典
|
||||
|
||||
#### llm 节点配置
|
||||
|
||||
llm 节点执行**单次无状态 LLM 调用**,适用于文本生成、数据分析、摘要等场景。与 agent 节点的区别是不涉及 Agent 的记忆、工具和技能。
|
||||
|
||||
```yaml
|
||||
- id: summarize
|
||||
base: llm
|
||||
display:
|
||||
name: AI 摘要
|
||||
config:
|
||||
provider: anthropic # 供应商名称(可选,精确匹配)
|
||||
model: claude-sonnet-4-6 # 模型(可选,不填使用默认)
|
||||
system_prompt: "你是摘要助手" # 系统提示词
|
||||
max_tokens: 2048 # 最大 token
|
||||
temperature: 0.3 # 温度(可选)
|
||||
reasoning: medium # 思维链级别(可选)
|
||||
inputs:
|
||||
data: "{{fetch_data.result}}"
|
||||
outputs:
|
||||
summary: "摘要文本"
|
||||
```
|
||||
|
||||
**config 字段说明**:
|
||||
|
||||
| 字段 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `system_prompt` | 是 | 系统提示词,定义 LLM 的角色和行为 |
|
||||
| `provider` | 否 | 供应商名称(如 `anthropic`、`openai`),精确匹配已配置的供应商。不填则由系统自动匹配 |
|
||||
| `model` | 否 | 指定模型,不填使用默认模型 |
|
||||
| `max_tokens` | 否 | 最大输出 token 数 |
|
||||
| `temperature` | 否 | 温度参数(0-2),控制输出随机性 |
|
||||
| `reasoning` | 否 | 思维链级别:`low` / `medium` / `high`。开启后模型先推理再回答,适合复杂分析任务 |
|
||||
| `output_schema` | 否 | JSON Schema 对象。设置后 LLM 将尝试返回符合 Schema 的结构化 JSON |
|
||||
|
||||
#### agent 节点配置
|
||||
|
||||
agent 节点调用**完整的 Agent**(有状态),适用于需要 Agent 的专业知识、记忆、工具或技能的复杂任务。
|
||||
|
||||
```yaml
|
||||
- id: legal_review
|
||||
base: agent
|
||||
display:
|
||||
name: 法律审核
|
||||
config:
|
||||
agent_id: legal-advisor # 必填:目标 Agent ID
|
||||
task: "审核以下内容:{{summarize.summary}}" # 任务描述
|
||||
inputs:
|
||||
content: "{{summarize.summary}}"
|
||||
outputs:
|
||||
review: "审核意见"
|
||||
```
|
||||
|
||||
**config 字段说明**:
|
||||
|
||||
| 字段 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `agent_id` | 是 | 目标 Agent 的 ID |
|
||||
| `task` | 是 | 交给 Agent 的任务描述,支持 `{{nodeId.outputKey}}`、`{{trigger.key}}`、`{{secrets.keyName}}` 插值 |
|
||||
|
||||
#### human_gate 节点配置
|
||||
|
||||
```yaml
|
||||
- id: approval
|
||||
base: human_gate
|
||||
display:
|
||||
name: 人工审批
|
||||
config:
|
||||
prompt: |
|
||||
请审阅以下内容并决定是否通过:
|
||||
审阅意见:{{draft_review.review_result}}
|
||||
风险等级:{{draft_review.risk_level}}
|
||||
options:
|
||||
- { label: "批准", value: approve }
|
||||
- { label: "拒绝", value: reject }
|
||||
- { label: "修改后通过", value: modify }
|
||||
inputs:
|
||||
review_result: "{{draft_review.review_result}}"
|
||||
risk_level: "{{draft_review.risk_level}}"
|
||||
outputs:
|
||||
decision: "审批决定(approve/reject/modify)"
|
||||
comment: "审批备注"
|
||||
```
|
||||
|
||||
#### llm vs agent 选择指南
|
||||
|
||||
| 场景 | 推荐基座 | 理由 |
|
||||
|------|---------|------|
|
||||
| 文本摘要、翻译、格式转换 | `llm` | 单次调用,不需要 Agent 上下文 |
|
||||
| 数据分析、信息提取 | `llm` | 无状态处理即可完成 |
|
||||
| 需要专业知识的审核 | `agent` | 需要 Agent 的领域知识和记忆 |
|
||||
| 需要调用外部工具 | `agent` | 需要 Agent 的工具能力 |
|
||||
| 多轮推理、复杂决策 | `agent` | 需要 Agent 的完整推理链 |
|
||||
|
||||
**简单判断**:如果任务可以用一段 system prompt + 一次输入完成,用 `llm`;如果任务需要 Agent 的记忆、工具或技能,用 `agent`。
|
||||
|
||||
#### trigger 节点
|
||||
|
||||
每个工作流**必须有且仅有一个** trigger 节点,作为工作流入口。`flow.start` 必须指向 trigger 节点。
|
||||
|
||||
**规则**:
|
||||
- trigger 节点**无 inputs**
|
||||
- trigger 节点的 outputs 使用结构化格式(`type` / `description` / `required` / `default`),声明工作流接受的输入参数
|
||||
- `config.type` 指定触发方式:`manual`(手动触发)或 `webhook`(外部触发)
|
||||
|
||||
```yaml
|
||||
- id: trigger
|
||||
base: trigger
|
||||
display:
|
||||
name: 手动触发
|
||||
icon: ▶️
|
||||
config:
|
||||
type: manual # manual | webhook
|
||||
outputs:
|
||||
param_name:
|
||||
type: string # 参数类型:string / number / boolean / object / array
|
||||
description: "参数描述"
|
||||
required: true # 是否必填
|
||||
default: "默认值" # 可选,未传入时的默认值
|
||||
```
|
||||
|
||||
**示例**——带多个参数的 trigger:
|
||||
|
||||
```yaml
|
||||
- id: trigger
|
||||
base: trigger
|
||||
display:
|
||||
name: 文档摘要触发
|
||||
icon: ▶️
|
||||
config:
|
||||
type: manual
|
||||
outputs:
|
||||
filePath:
|
||||
type: string
|
||||
description: "要摘要的文档路径"
|
||||
required: true
|
||||
language:
|
||||
type: string
|
||||
description: "摘要输出语言"
|
||||
required: false
|
||||
default: "zh-CN"
|
||||
```
|
||||
|
||||
下游节点通过 `{{trigger.paramName}}` 引用 trigger 输出的参数值。
|
||||
|
||||
#### inputs 格式规范
|
||||
|
||||
inputs 使用**对象映射格式**——key 为本节点的变量名,value 为数据来源引用:
|
||||
|
||||
```yaml
|
||||
# 引用其他节点的输出
|
||||
inputs:
|
||||
varName: "{{nodeId.outputKey}}"
|
||||
|
||||
# 引用触发参数
|
||||
inputs:
|
||||
query: "{{trigger.userQuery}}"
|
||||
|
||||
# 引用用户级 secret
|
||||
inputs:
|
||||
api_key: "{{secrets.email_api_key}}"
|
||||
|
||||
# 多个输入
|
||||
inputs:
|
||||
title: "{{extract.title}}"
|
||||
body: "{{extract.body}}"
|
||||
metadata: "{{trigger.metadata}}"
|
||||
```
|
||||
|
||||
**禁止使用数组格式**:
|
||||
|
||||
```yaml
|
||||
# 错误!不要用数组
|
||||
inputs:
|
||||
- name: varName
|
||||
source: nodeId.outputKey
|
||||
```
|
||||
|
||||
#### outputs 格式规范
|
||||
|
||||
outputs 使用**对象映射格式**——key 为输出变量名,value 为描述文本:
|
||||
|
||||
```yaml
|
||||
outputs:
|
||||
result: "处理后的结果数据"
|
||||
summary: "结果摘要"
|
||||
```
|
||||
|
||||
#### flow 定义
|
||||
|
||||
```yaml
|
||||
flow:
|
||||
start: first_node # 起始节点 ID
|
||||
edges: # 边列表(定义执行顺序)
|
||||
- { from: first_node, to: second_node }
|
||||
- { from: second_node, to: third_node }
|
||||
- from: third_node # 条件分支(可选)
|
||||
to: branch_a
|
||||
condition: "risk_level == 'high'"
|
||||
end: [final_node] # 终止节点列表
|
||||
```
|
||||
|
||||
#### 变量引用体系
|
||||
|
||||
DSL 中所有动态值统一使用 `{{}}` 模板语法引用:
|
||||
|
||||
| 语法 | 来源 | 示例 |
|
||||
|------|------|------|
|
||||
| `{{nodeId.outputKey}}` | 前置节点输出 | `{{summarize.summary}}` |
|
||||
| `{{trigger.key}}` | 触发时传入的参数 | `{{trigger.filePath}}` |
|
||||
| `{{secrets.keyName}}` | 用户级 secret | `{{secrets.dingtalk_token}}` |
|
||||
|
||||
**适用位置**:`inputs` 的值、`config.prompt` 中的插值均使用此语法。
|
||||
|
||||
#### Secrets 引用
|
||||
|
||||
工作流可通过 `{{secrets.keyName}}` 引用用户预配置的密钥,用于 API 调用等场景。
|
||||
|
||||
- Secrets 由用户在 `~/.desirecore/config/secrets.json` 中预配置
|
||||
- 引擎在运行时自动解析 `{{secrets.*}}`,将其替换为实际值
|
||||
- Secrets 仅在执行阶段解析,校验和干跑阶段不会暴露实际值
|
||||
|
||||
```yaml
|
||||
# 在 inputs 中引用 secret
|
||||
inputs:
|
||||
api_key: "{{secrets.email_api_key}}"
|
||||
webhook_url: "{{secrets.dingtalk_webhook}}"
|
||||
|
||||
# 在 config.prompt 中引用 secret(不推荐,仅特殊场景)
|
||||
config:
|
||||
prompt: "使用 token {{secrets.github_token}} 访问仓库"
|
||||
```
|
||||
|
||||
### 阶段 3:校验 DSL
|
||||
|
||||
使用 `WorkflowValidate` 工具校验 DSL 文件的结构和引用完整性。
|
||||
|
||||
**调用方式**:
|
||||
|
||||
```
|
||||
工具:WorkflowValidate
|
||||
参数:
|
||||
path: ~/.desirecore/workflows/<wf_id>/workflow.dsl.yaml
|
||||
```
|
||||
|
||||
**校验内容**:
|
||||
- YAML 语法正确性
|
||||
- JSON Schema 合规性(必填字段、类型、格式)
|
||||
- 节点 ID 唯一性
|
||||
- 边的引用有效性(from/to 均指向已存在的节点)
|
||||
- 起始节点和终止节点存在
|
||||
- 无环检测(DAG 校验)
|
||||
- inputs 引用的上游节点和输出字段存在
|
||||
|
||||
**校验通过** → 进入阶段 4
|
||||
**校验失败** → 根据错误信息用 Edit 工具修复,重新校验
|
||||
|
||||
### 阶段 4:干跑测试
|
||||
|
||||
使用 `WorkflowTest` 工具进行模拟执行(dry-run),不实际调用 Agent 或执行代码。
|
||||
|
||||
**调用方式**:
|
||||
|
||||
```
|
||||
工具:WorkflowTest
|
||||
参数:
|
||||
path: ~/.desirecore/workflows/<wf_id>/workflow.dsl.yaml
|
||||
params: # 可选,用于模拟 trigger 参数
|
||||
filePath: /path/to/input.md
|
||||
```
|
||||
|
||||
**测试内容**:
|
||||
- 验证拓扑排序是否成功
|
||||
- 模拟数据在节点间的流转路径
|
||||
- 检查所有 inputs 引用在运行时是否可解析
|
||||
- 输出执行计划预览(节点执行顺序)
|
||||
|
||||
**测试通过** → 向用户确认是否正式执行
|
||||
**测试失败** → 根据错误信息修复,重新测试
|
||||
|
||||
### 阶段 5:正式执行
|
||||
|
||||
使用 `WorkflowRun` 工具启动工作流。
|
||||
|
||||
**调用方式**:
|
||||
|
||||
```
|
||||
工具:WorkflowRun
|
||||
参数:
|
||||
path: ~/.desirecore/workflows/<wf_id>/workflow.dsl.yaml
|
||||
params: # 可选,作为 {{trigger.key}} 上下文传入
|
||||
filePath: /path/to/input.md
|
||||
```
|
||||
|
||||
**执行过程**:
|
||||
- 引擎按拓扑顺序逐节点执行
|
||||
- 实时通过 SSE 推送节点状态变更事件
|
||||
- 遇到 human_gate 节点时暂停,等待用户审批
|
||||
- 所有终止节点完成后,返回最终结果
|
||||
|
||||
**执行完成后**:
|
||||
- 向用户展示执行结果摘要
|
||||
- 如有失败节点,说明失败原因和建议修复方式
|
||||
|
||||
### 注意事项
|
||||
|
||||
1. **workflow_id 命名**:必须以 `wf_` 前缀开头,使用 snake_case,如 `wf_contract_review`
|
||||
2. **严格分步构建**:步骤 2a 只写节点拓扑骨架(不含 config/code),确认后步骤 2b 按拓扑顺序逐节点填充配置,禁止一次性写完所有细节
|
||||
3. **输入输出格式**:inputs 和 outputs 必须使用对象映射格式(`{ key: value }`),不要用数组
|
||||
4. **变量插值**:inputs、llm/agent/human_gate 的 prompt / system_prompt / task 支持 `{{nodeId.outputKey}}`、`{{trigger.key}}`、`{{secrets.keyName}}`
|
||||
5. **校验先行**:正式执行前务必先校验再干跑测试,减少运行时错误
|
||||
6. **人工门控**:涉及重要决策(如发布、付款、删除)的步骤,建议使用 human_gate 节点
|
||||
|
||||
### 错误处理
|
||||
|
||||
| 错误场景 | 处理方式 |
|
||||
|---------|---------|
|
||||
| YAML 语法错误 | 检查缩进和格式,用 Edit 工具修正 |
|
||||
| 校验失败 | 根据 WorkflowValidate 的错误详情逐项修复 |
|
||||
| 节点引用不存在 | 检查 inputs 中引用的 nodeId.outputKey 是否拼写正确 |
|
||||
| 干跑测试失败 | 检查拓扑排序和数据流转路径 |
|
||||
| 执行超时 | 检查是否有 agent 节点 prompt 过于复杂 |
|
||||
| human_gate 被拒绝 | 工作流中止,向用户说明中止原因和已完成的步骤 |
|
||||
|
||||
### 背景知识
|
||||
|
||||
> AgentFS 仓库结构、排查要点与受保护路径详见 `_agentfs-background.md` 和 `_protected-paths.yaml`。
|
||||
|
||||
### 依赖
|
||||
|
||||
- `WorkflowValidate` 内置工具 — 校验 DSL 结构
|
||||
- `WorkflowTest` 内置工具 — 干跑测试
|
||||
- `WorkflowCreate` 内置工具 — 校验并写入全局工作流目录
|
||||
- `WorkflowRun` 内置工具 — 正式执行工作流
|
||||
- Write / Edit / Read 工具 — 创建和编辑 DSL 文件
|
||||
- Agent Service Workflow 引擎(`lib/workflow-service/`)
|
||||
Reference in New Issue
Block a user