Skip to main content

workflow-builder

根据自然语言描述生成 flocks 内置工作流(workflow.md, workflow.json)。当用户提出创建/设计/生成/搭建工作流或任何多步骤流程(如告警调查、事件响应、SOP/Runbook 自动化)时使用本 skill。

Informations de source

Dépôt
AgentFlocks/flocks
Dernière activité de la source
20 septembre 2026 à 16:54
Langue détectée de SKILL.md
chinois
Étoiles
479
Forks
90

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Explorateur de fichiers
10 fichiers

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
workflow-builder
group
系统辅助
category
system
description
根据自然语言描述生成 flocks 内置工作流(workflow.md, workflow.json)。当用户提出创建/设计/生成/搭建工作流或任何多步骤流程(如告警调查、事件响应、SOP/Runbook 自动化)时使用本 skill。
# Workflow Builder 创建模式按以下顺序构建工作流:**场景确认与流程设计** → **确认 workflow.md 文档语言** → **workflow.md 草稿与确认循环** → **workflow.json 生成与验证** → **逐节点测试** → **集成测试** → **性能评估与优化**。 > **产物**:`workflow.json` 中所有可执行节点均为 `type="python"` 并自带 `code`。最终交付物固定为:`workflow.md`、`workflow.json`。 > > **顺序强制**:创建工作流时,`workflow.md` 是唯一的人类意图源。必须先询问用户需要中文还是英文流程说明文档,再按所选语言创建并确认 `workflow.md`,最后基于已确认的 `workflow.md` 生成 `workflow.json`。在 `workflow.md` 写入并确认前,严禁写入或覆盖 `workflow.json`。 ## 参考资料(按需读取) | 文件 | 内容 | 何时读取 | |------|------|---------| | [references/reference.md](references/reference.md) | 节点类型详解、出边选择行为、分支/循环/Join 规则、Edge Mapping 指南、Tool vs LLM 决策、文件输出规则、报告生成模板、`workflow.json` 骨架模板 | **生成 `workflow.json` 前建议读取** | | [references/composition.md](references/composition.md) | 嵌套工作流(subworkflow)组合格式与展开规则 | 仅在用户需要嵌套工作流时读取 | | [references/workflow_zh.md](references/workflow_zh.md) | 中文 `workflow.md` 结构模板 | 用户选择中文流程说明文档时读取 | | [references/workflow_en.md](references/workflow_en.md) | English `workflow.md` structure template | 用户选择英文流程说明文档时读取 | | [references/workflow_template/](references/workflow_template/) | 工作流创建参考包,包含标准 `workflow.md`、`workflow.json`、`config.json`、`guide.md` 和 `meta.json` 模板 | **创建工作流、生成配置模板或补齐 guide.md 前按需读取** | | `~/.flocks/plugins/workflows/stream_alert_denoise/workflow.md` | 已成型业务工作流示例,展示“功能、流程、输入输出、模块逻辑、发布配置、编辑指南”的写法 | 文件存在且需要参考真实工作流表达时读取 | --- ## 0. 开始前 ### Todo List(每次创建必须生成) **在开始任何工作前,必须先用 Todo 工具列出完整任务清单**,并在整个过程中实时更新状态(pending → in_progress → completed)。标准 Todo 清单如下,根据实际工作流复杂度增减: ``` [ ] 0. 核验可用工具列表(读取 registry.py) [ ] 1. 场景深度确认:与用户对话,明确业务场景与核心目标 [ ] 1. 输出思考维度分析 + Mermaid 流程简图,与用户沟通对齐 [ ] 1. 获取样例数据(用户上传或自动构造后确认) [ ] 2. 用 Question 工具确认 workflow.md 使用中文还是英文 [ ] 2. 读取对应语言模板 workflow_zh.md 或 workflow_en.md,以及可用业务示例 [ ] 2. 生成单份 workflow.md 草稿(人读描述,包含功能、流程、节点、输入输出、处理逻辑) [ ] 2. 写入 workflow.md 文件,供页面编辑器展示 [ ] 2. 向用户展示流程摘要并收集修改建议(循环直至满意) [ ] 2. 确认 workflow.md 已是最新意图源 [ ] 3. 读取 reference.md [ ] 3. 基于已确认 workflow.md 生成完整 workflow.json(含代码) [ ] 3. 写入 workflow.json 文件 [ ] 4. 验证 JSON 格式 + Python 语法 [ ] 4. 保存样例数据到 /api/workflow/{id}/sample-inputs [ ] 5. 逐节点测试:节点 1 - <node_id> [ ] 5. 逐节点测试:节点 2 - <node_id> [ ] 5. 逐节点测试:节点 N - <node_id>(按拓扑顺序补充) [ ] 6. 集成测试:全量运行验证 [ ] 6. 记录各节点及总运行时间 [ ] 7. 性能评估:识别瓶颈节点 [ ] 7. 优化慢节点(并发/缓存/精简 prompt 等) [ ] 7. 通知用户工作流已就绪 ``` > 每完成一项立即标记为 completed;每进入一项立即标记为 in_progress。**严禁在 Todo 全部完成前宣布任务结束。** --- ### 实时工具核验(重要) 生成 workflow 前必须核验可用工具列表与参数签名: - **强制读取** `flocks/flocks/tool/registry.py`(`ToolInfo.parameters` 是参数 schema 的权威来源)。 - 工具名必须一致,参数名必须严格对齐,禁止调用 `run_workflow`(在 `WORKFLOW_TOOL_BLOCKLIST` 中)。 --- ## 1. 第一阶段:场景确认与流程设计 > 目标:通过对话真正理解用户需求,输出完整的思考维度与流程简图,让用户在花时间构建工作流之前就能确认方向。 ### 1.1 深度场景对话 使用 `Question` 工具与用户确认以下维度(根据场景选取相关项,不必逐条询问,尽量合并为 1-2 轮对话): **业务背景** - 这个工作流解决什么安全/业务问题?触发条件是什么? - 谁会使用这个工作流?是定时自动触发还是手动触发? - 有没有现有的 SOP 或人工处理流程可以参考? **数据与工具** - 输入数据是什么?(告警字段、IP/域名/哈希、日志条目等) - 需要调用哪些外部工具或服务?(威胁情报、SIEM、资产库等) - 输出结果是什么?(报告、工单、通知、打标签等) **流程要求** - 有没有需要特殊处理的条件分支?(如高危 vs 低危、内部 IP vs 外部 IP) - 对运行时间有要求吗?(实时响应 < 30s?批量处理可接受数分钟?) - 有哪些已知的"陷阱"或边界情况需要注意? ### 1.2 输出思考维度与流程简图 对话完成后,在消息中输出以下内容供用户确认: **思考维度总结**(结构化列举,涵盖:数据流、工具调用链、分支逻辑、异常处理、性能关键点、可扩展性) **流程简图**(使用 Mermaid flowchart 语法,清晰展示节点与边关系) 示例格式: ``` ## 思考维度 **数据流**:输入告警 → 资产丰富 → 情报查询 → LLM 分析 → 报告输出 **分支逻辑**:IP 类型判断(内网 / 外网)→ 不同查询策略 **性能关键点**:情报查询可并发;LLM 调用是主要耗时节点 **异常处理**:工具调用失败时降级到日志记录,不中断流程 **可扩展性**:后续可插入 SOAR 工单节点 ## 流程简图 \`\`\`mermaid flowchart TD A[接收告警] --> B[提取 IP/域名] B --> C{IP 类型?} C -->|内网| D[查询资产库] C -->|外网| E[查询威胁情报] D --> F[汇总上下文] E --> F F --> G[LLM 分析] G --> H[生成报告] \`\`\` ``` ### 1.3 获取样例数据 在流程简图得到用户认可后,请用户上传一条完整的样例输入数据(JSON 格式): - 若用户能提供:直接使用 - 若用户无法提供:根据场景自动构造一条最小可用样例 JSON,并请用户确认字段和数值是否合理 > 样例数据将用于后续每个节点的逐步测试,是测试阶段的核心依据。获得样例后,待工作流 ID 确定时调用 `POST /api/workflow/{id}/sample-inputs` 保存(body: `{ "sampleInputs": <样例 JSON 对象> }`)。 --- ## 2. 第二阶段:生成并确认 workflow.md(人读意图源) > 目标:先把工作流的业务意图、节点结构、输入输出和处理逻辑写成可读、可编辑的 `workflow.md`。页面左侧编辑器以 `workflow.md` 表达工作流,用户应先在这里确认意图;只有确认后才能生成 `workflow.json`。 ### 2.0 文档语言选择(必须) 创建 `workflow.md` 前,必须用 `Question` 工具询问用户需要哪种流程说明文档: - 中文流程说明文档:读取 [references/workflow_zh.md](references/workflow_zh.md),并可参考 [references/workflow_template/workflow.md](references/workflow_template/workflow.md) 的章节完整性,生成中文 `workflow.md`。 - English workflow specification:读取 [references/workflow_en.md](references/workflow_en.md),并可参考 [references/workflow_template/workflow.md](references/workflow_template/workflow.md) 的章节完整性,生成英文 `workflow.md`。 规则: - 工作流目录里最终只写一份 `workflow.md`。 - 不要在工作流目录里创建 `workflow_zh.md`、`workflow_en.md`、`workflow.en.md` 或其它语言副本。 - `workflow_zh.md` / `workflow_en.md` 只是本 skill 内部的结构模板。 - `references/workflow_template/` 只是本 skill 内部的创建参考包,严禁复制成可扫描的 `workflow_template` 工作流目录;需要模板内容时,只读取其中的文件并改造成当前真实工作流。 - 不要根据用户当前会话语言自动猜测文档语言;创建 `workflow.md` 前必须明确询问并得到选择。 ### 2.1 核心要求 `workflow.md` 必须让人读得懂,也必须足够结构化,便于后续稳定生成 `workflow.json`。每个步骤必须包含: - **功能概述**:用人能理解的话说明这个工作流解决什么问题、不解决什么问题。 - **总体流程**:用箭头、表格或 Mermaid 描述节点顺序和职责。 - **输入/输出**:数据来源、格式、用途。 - **模块逻辑**:每个节点的职责、处理步骤、判定条件、循环方式、异常处理。 - **工具/LLM 标注**:明确该步是 Tool-driven 还是 LLM-driven(详细决策指南见 [reference.md § Tool vs LLM](references/reference.md#5-tool-vs-llm-决策指南))。 - **推荐组合**:`tool.run_safe(...)` 获取数据 → `llm.ask(...)` 分析 → `tool.run('write', ...)` 落盘。 - **默认使用 `tool.run_safe()`**,返回 `{"success", "text", "obj", "error"}` 统一包络。 - **文件落盘**:节点有任何文件输出时,统一写入 `~/.flocks/workspace/outputs/<YYYY-MM-DD>/` 目录下,详见 [reference.md § 文件输出规则](references/reference.md#6-文件输出规则)。 - **决策分支**:写清条件、各分支处理、跳转规则。 - **发布和配置**:写清 API、Syslog、Kafka、Webhook、Schedule 等入口是否支持,运行态配置由 `config.json` 模板和 Storage/SQL 管理。 - **编辑指南**:告诉用户修改输入、节点逻辑、输出、发布方式时应该优先改哪里。 - **报告结构**(若涉及):除非用户要求简化,需包含摘要、分析、发现、建议、来源(模板见 [reference.md § 报告生成](references/reference.md#7-报告生成最佳实践))。 ### 2.2 写入 workflow.md 1. 先按用户选择的语言模板生成内容,再用 `write` 工具将单份 `workflow.md` **写入文件**(路径与第 9 节一致,例如 `.../plugins/workflows/<id>/workflow.md`)。 - **⚠️ 路径必须使用绝对路径**:全局目录可用 `python3 -c "import os; print(os.path.expanduser('~/.flocks/plugins/workflows/<id>'))"`;项目目录可先解析 workspace(从 cwd 向上第一个含 `.flocks` 的目录)再拼接 `/.flocks/plugins/workflows/<id>`。 - **严禁**使用未展开的相对路径(如 `.flocks/plugins/workflows/<id>/` 相对仓库根随手写入错误位置),否则 WebUI 可能无法从实际扫描目录读到文件。 - **严禁**同时写入 `workflow.en.md` 或语言副本;UI 和生成流程只认当前工作流目录下的 `workflow.md`。 2. 写入成功后,在消息中说明:「已创建 `workflow.md`,请在左侧编辑器查看并确认。需要调整节点、输入输出或处理逻辑时,请先改 `workflow.md`。」 3. 需要用户确认是否进入 `workflow.json` 生成时,必须使用 `Question` 工具或等待页面 diff 的接受/拒绝结果;不要用普通文本提问替代确认。 ### 2.3 用户反馈循环(循环直至满意) 收集用户对 `workflow.md` 的修改建议,按照以下循环执行,**直到用户确认满意**: ``` 接收用户反馈 ↓ 分析修改需求(功能描述、节点职责、输入输出、处理逻辑、分支关系) ↓ 更新 workflow.md ↓ 重新写入文件 ↓ 向用户展示更新摘要,并用 Question 工具或页面 diff 请用户确认 ↓ [满意] → 进入第三阶段,基于已确认 workflow.md 生成 workflow.json [还有修改] → 继续循环 ``` > **禁止事项**:不要为了提前展示流程图而先写一个简化 `workflow.json`。当前创建流程必须让 `workflow.md` 先落盘并完成确认,`workflow.json` 只能作为已确认 `workflow.md` 的机器执行产物。 --- ## 3. 第三阶段:生成完整 workflow.json(机器执行) 根据已确认的 `workflow.md` 生成严格可执行的 `workflow.json`。**生成前必须读取最新磁盘上的 `workflow.md`,并建议读取 [references/reference.md](references/reference.md)**。 ### 3.0 节点生成策略 - **主路径**:每个可执行步骤 → `type="python"` 节点,必须同时包含 `code`(执行逻辑)+ `description`(文档说明)。 - **兜底**:`logic` 节点仅在用户明确要求"不写代码"或快速原型时使用,运行时由 codegen 兜底。 ### 3.1 运行时硬约束 **顶层字段:** - `start` 必须等于某个 `nodes[i].id` - `nodes[].id` 必须唯一 - `name`/`description`(可选)用于工作流级别说明 - `version` 会被运行时忽略,不需要生成 **Node 约束**(对应 `flocks/workflow/models.py`): - `python`:`code` 必须非空 - `logic`:`description` 必须非空 - **出边选择行为**(关键):`python` → 所有出边触发;`logic`/`branch`/`loop` → 通过 `select_key` 取值做 label 匹配选边 - `join=true`:等待所有入边到齐再执行一次 **代码约束:** - 同步 `exec()` 模型,**严禁** `await`/`async def`/`async for`/`async with`。确保节点的代码要可以独立运行。 **Edge 约束:** - JSON 中用 `"from"` 而非 `"from_"`;`from`/`to` 引用存在的 node id;`order` ≥ 0。 - **新建 workflow 的每条 edge 必须包含非空 `mapping` 对象**。不要生成无 `mapping` 的 edge;不要只写 `const` 而省略 `mapping`。新建 workflow 默认启用 strict edge mapping,无 `mapping` 会在创建或运行时失败。 ### 3.2 映射规则 - `workflow.md` 每步对应一个节点,`id` 用 snake_case。 - md 中写的输出字段,必须在 `outputs[...]` 中体现。 - md 中 `Tool: xxx` 标记 → 对应节点 `description` 保留。 - 所有 edge 都必须写 `edge.mapping`,只映射下游节点实际需要的字段,避免全量 payload 传递。 - 下游节点如需 `tool.run(..., **inputs)`,用 `edge.mapping`/`edge.const` 规整输入到匹配工具参数形状;其中 `edge.mapping` 仍然必须非空。 - 若某条边只是控制流、下游不需要业务字段,也必须映射一个确定存在的小字段(如 `case_id`、`has_results`、`status`);如果没有合适字段,让上游节点写出 `outputs["_edge_context"] = True`,并在该边映射 `{ "_edge_context": "_edge_context" }`。 - `branch`/`loop` 出边同样必须写 `mapping`。映射源可以来自该分支节点收到的输入 payload(例如 `search_text`、`case_id`、`has_results`),不要求来自 branch 节点自身输出。 - 详细 Mapping 指南见 [reference.md § Edge Mapping](references/reference.md#4-edge-mapping-详细指南)。 ### 3.3 分支/循环与 Join - **branch/loop 选边**:`bool` 值 label 用 `"true"`/`"false"`;`str` 值精确匹配;无命中回退到空 label 默认边。上游必须把 `select_key` 所需字段写入 payload。 - **分支汇合(强制)**: - 多入边且非互斥 → **必须** `join=true` - 判断互斥:所有入边来自同一 branch/loop 的不同 label 出边 - **昂贵节点保护**:含 `llm.ask()` 或 `tool.run('write', ...)` 的节点,禁止被两条非互斥路径直达,必须先经 join 节点 - 推荐模式:join 节点(python, `join=true`)归一化多分支输出 → 再传给后续步骤 - **嵌套工作流**:见 [references/composition.md](references/composition.md)。 ### 3.4 代码实现 **辅助函数:** | 函数 | 说明 | |------|------| | `tool.run(name, **inputs)` | 返回 `ToolResult.output`(类型 `Any`,**通常是字符串**),失败抛异常 | | `tool.run_safe(name, **inputs)` | **推荐**,返回 `{"success": bool, "text": str, "obj": Any, "error": str\|None}`,永不抛异常 | | `llm.ask(prompt)` | 调用 LLM,返回字符串 | | `get_path(path)` | payload 深层取值 | **⚠️ 返回值类型警告(常见 Bug 源):** - **`tool.run()` 返回的是 `Any` 类型**,大多数工具返回的是**字符串**(格式化文本),**不是字典**。**严禁**直接对返回值调用 `.get()` 等字典方法。 - **`tool.run_safe()["obj"]` 也是 `Any` 类型**,可能是 `str`、`dict`、`list` 或 `None`。使用前**必须检查类型**。 - 如果工具返回的是 JSON 格式的字符串,需要用 `json.loads()` 解析后再作为字典操作。 ```python # ❌ 错误:直接在 tool.run() 返回值上调用 .get() result = tool.run('some_tool', ip=ip) value = result.get("key") # AttributeError: 'str' object has no attribute 'get' # ❌ 错误:假设 obj 一定是 dict result = tool.run_safe('some_tool', ip=ip) value = result["obj"].get("key") # obj 可能是 str,同样报错 # ✅ 正确:使用 text 做字符串操作 result = tool.run_safe('some_tool', ip=ip) outputs["text"] = result["text"] # text 永远是 str,安全 # ✅ 正确:需要结构化数据时,先检查 obj 类型 result = tool.run_safe('some_tool', ip=ip) obj = result["obj"] if isinstance(obj, dict): value = obj.get("key") elif isinstance(obj, str): import json try: parsed = json.loads(obj) value = parsed.get("key") if isinstance(parsed, dict) else None except json.JSONDecodeError: value = None ``` **`tool.run_safe()` 使用指南:** - 字符串拼接 / LLM prompt 插值 → `result["text"]`(永远是 `str`,最安全)
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub