From 833961766f0cd2b9c5258c61a76c99e3fe7a7c0c Mon Sep 17 00:00:00 2001 From: JOJO <1498581755@qq.com> Date: Wed, 19 Aug 2026 13:53:51 +0800 Subject: [PATCH] =?UTF-8?q?docs(workflow):=20=E5=B7=A5=E4=BD=9C=E6=B5=81?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E8=AE=BE=E8=AE=A1=E6=96=B9=E6=A1=88=E4=B8=8E?= =?UTF-8?q?=E8=B0=83=E7=A0=94=E6=8A=A5=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/workflow_feature_plan.md | 109 ++++++++ .../code_mount_points/code_mount_points.md | 218 +++++++++++++++ .../agentic_workflow_research.md | 258 ++++++++++++++++++ 3 files changed, 585 insertions(+) create mode 100644 docs/workflow_feature_plan.md create mode 100644 workflow_research/code_mount_points/code_mount_points.md create mode 100644 workflow_research/external_products/agentic_workflow_research.md diff --git a/docs/workflow_feature_plan.md b/docs/workflow_feature_plan.md new file mode 100644 index 00000000..dd0235b8 --- /dev/null +++ b/docs/workflow_feature_plan.md @@ -0,0 +1,109 @@ +# 工作流(Workflow)功能设计方案 + +> 状态:设计已讨论定稿(2026-08-18),待实施。 +> 调研依据:`workflow_research/external_products/agentic_workflow_research.md`(外部产品)、`workflow_research/code_mount_points/code_mount_points.md`(代码挂载点)。 + +## 1. 功能定义 + +用户把「一套既定流程:工作方式 → 验证方式 → 结束方式」存为一个**工作流**(workflow),之后在任何普通对话中激活它,让主智能体复用现有循环与执行引擎按流程推进;阶段结束/整体结束时可由审核智能体软审核。 + +核心原则(来自外部调研共识):**结构在边上,自主在节点内**——工作流只约束阶段顺序与进出契约,阶段内主智能体完全自主(自由调工具、跑脚本)。 + +## 2. 已拍板的设计决策 + +| 决策点 | 结论 | +|---|---| +| 运行方式 | **不做独立模式/特殊 URL/新对话类型**,只能在正常对话中激活 | +| 激活入口 | **/ 菜单(slash 菜单)**,新增 workflows 模式选择要激活的工作流(仿 skills 模式) | +| 前后端通信 | **轮询**(复用 task 轮询 session_data 快照链路,不新增 websocket 通道) | +| 状态隔离 | **对话级状态**,多对话可同时激活不同工作流,进度互不串扰 | +| 审核机制 | 复用审核智能体架构(`goal_review_agent.py` 模式),审核智能体可调用只读 run_command 取证 | +| 硬校验 | 不做步骤级硬校验;只做归档时结构校验(frontmatter 合法、阶段 id 唯一等) | +| 存储形态 | 工作流文件夹 = `WORKFLOW.md`(frontmatter 结构 + 自然语言正文)+ `scripts/`(已验证脚本)+ `references/`(可选),与 skill 对齐 | + +## 3. 存储与落盘位置 + +| 模式 | 用户工作流库 | 说明 | +|---|---|---| +| host | `~/.astrion/astrion/host/workflows/` | 统一,不按用户拆(对齐 `CUSTOM_SKILLS_DIR`) | +| docker/web | `users//personal/workflows/` | 每用户私有,多项目共享(对齐 `infer_private_skills_dir`) | + +- 源码树 `workflows/` 只放内置示例种子,双源合并(对齐 `agentskills/` + `CUSTOM_SKILLS_DIR`)。 +- 归档工具 `create_workflow`:校验 → `shutil.move` → 已存在拒绝覆盖(复用 `archive_skill_directory` 模式)。 +- 运行时状态:`{workspace.data_dir}/workflow_states/.json`(对话级,压缩 handoff 点处理 key 迁移)。 + +## 4. WORKFLOW.md 格式(草案,实施时可微调) + +```markdown +--- +name: code-review-pipeline +description: 代码评审标准流程 +review_mode: active # 审核智能体是否可调用只读 run_command 取证 +max_stage_rounds: 20 # 单阶段最大轮数,防死循环 +stages: + - id: explore + name: 代码探索 + goal: 理解改动范围与相关模块 + review: false + - id: review + name: 逐项评审 + goal: 按 checklist 评审每个文件 + review: true + review_prompt: 检查是否遗漏边界条件和安全问题 + - id: report + name: 输出报告 + goal: 生成结构化评审报告 + review: true +end_conditions: 报告落盘且审核通过 +--- + +# 工作方式 / 验证方式 / 结束方式(自然语言正文,随阶段上下文注入) +``` + +- 阶段默认线性推进;`on_pass` / `on_fail` 可跳转指定阶段(一期线性+有限跳转,不做完整 DAG)。 +- 结构校验在归档时做(name/description/stages 存在、id 唯一、跳转目标存在);内容质量交给审核智能体。 + +## 5. 运行时机制(全部复用现有引擎) + +- **主循环不新增**:复用 `process_message_task` 门闸 + `handle_task_with_sender` 迭代。 +- **拦截点**:`server/chat_flow_task_main.py` 的 `if not tool_calls:` 分支,与 goal 分支平排新增 workflow 分支: + - 当前阶段 `review=false` → 推进下一阶段,注入新阶段上下文,`continue` 主循环 + - `review=true` → `WorkflowReviewAgent` 审核 → pass 推进 / retry 则 `inject_runtime_user_message` 续命 + - 最后阶段通过 → 整体结束审核 → `mark_done` + - 边界保护:`max_stage_rounds`、空转保护(仿 `REASON_IDLE_NO_TOOL`)、用户取消 +- **压缩维持**:状态落盘 + `handle_task_with_sender` 入口检查活跃状态并重注入当前阶段上下文(对齐 goal 的 `inject_goal_prompt` 重注入模式)。 +- **编排模块**:新增 `server/workflow_flow.py`(仿 `server/goal_flow.py`),减少对主循环侵入。 +- **审核智能体**:新增 `modules/workflow_review_agent.py`(fork `goal_review_agent.py`),内部工具 `report_workflow_stage_status`(pass/retry/complete),active 模式注入只读 run_command;配置走 `resolve_deploy_config("workflow_review.json")` 回退链。 + +## 6. 通信与前端 + +- **轮询链路**(现成):sender 事件 → `session_data` 快照(`server/tasks/models.py` L763 模式)→ REST 轮询透传(`server/tasks/api.py` L269 模式)→ 前端 `taskPolling/lifecycle.ts` case 消费。 + - 新增事件:`workflow_progress` / `workflow_review_progress` / `workflow_completed` / `workflow_stopped`。 + - socket 事件 data 必须带 `conversation_id`,前端按当前对话过滤,保证多对话不串。 +- **激活**:`InputComposer.vue` slash 菜单新增 `workflows` 模式(数据 `GET /api/workflows`),root 菜单加「工作流」入口;激活/退出走 REST(`POST /api/workflow/activate|deactivate`)。 +- **进度展示**:仿 goal 进度组件——当前阶段 x/N · 阶段名 · 审核状态 · 轮数。 +- **状态 API**:`GET /api/workflow/status?conversation_id=` 供轮询/刷新恢复。 + +## 7. 新增工具与文件清单 + +| 项 | 类型 | 参照 | +|---|---|---| +| `create_workflow` | AI 工具(生成并归档) | `create_skill` | +| `read_workflow` | AI 工具(读定义) | `read_skill` | +| `report_workflow_stage_status` | 审核智能体内部工具 | `report_goal_status` | +| `modules/workflows_manager.py` | 校验/归档/目录合并 | `modules/skills_manager.py` | +| `modules/workflow_state_manager.py` | 对话级状态落盘 | `modules/goal_state_manager.py` | +| `server/workflow_flow.py` | 编排(启动/注入/审核/推进) | `server/goal_flow.py` | +| `prompts/workflow.txt` | 提示词模板 | `prompts/` 现有模板 | +| `server/tasks/workflows.py` | REST API(列表/激活/状态) | `server/tasks/skills.py` | + +## 8. 分期 + +- **一期(本次)**:格式 + 归档工具 + 提示词注入 + 阶段状态机与审核 + 轮询进度 + slash 菜单激活 + 对话级状态隔离。 +- **二期**:拖拽画布编辑器(React Flow),本质是 stages frontmatter 的可视化编辑器(坐标只作视觉)。 +- **三期**:分支/DAG、并行阶段、子工作流嵌套。 + +## 9. 待确认(实施前如需变更再讨论) + +- 工作流与目标模式是否互斥激活(建议互斥,避免双「防停止」机制叠加)。 +- `activate_workflow`/`deactivate_workflow` 是否做成 AI 工具(slash 菜单人工激活为一期必须)。 diff --git a/workflow_research/code_mount_points/code_mount_points.md b/workflow_research/code_mount_points/code_mount_points.md new file mode 100644 index 00000000..465b4bc7 --- /dev/null +++ b/workflow_research/code_mount_points/code_mount_points.md @@ -0,0 +1,218 @@ +# 代码库「工作流(Workflow)功能」挂载点调研报告 + +> 调研目标:为即将新增的「工作流(Workflow)功能」定位代码库内的接入挂载点。 +> 前提理解:工作流 = 用户把「一套既定流程:工作方式→验证方式→结束方式」存为一个工作流文件夹(类似现有 skill 文件夹机制,可附带验证过的脚本/代码文件);之后在对话中复用以现有智能体循环+执行引擎运行它;可能有独立 URL(如 `/workflow/new`)或作为普通对话的一种运行方式;阶段/整体结束时由审核智能体审核(复用两套现有审核:工具审核 + 目标模式 goal_review)。 +> +> **调研约束**:仅只读操作,未修改任何项目文件。所有结论均基于实际读到的代码,标注文件路径与行号;不确定处明确写「未确认」。 +> 所有代码路径均以项目根 `/Users/jojo/Desktop/agents/正在修复中/agents` 为准(相对路径书写)。 + +--- + +## 1. Skill 系统全链路(工作流文件夹需仿照它) + +### 1.1 目录结构与 SKILL.md frontmatter + +- **源码树 skill 库**:`agentskills/`(每个 skill 一个子目录,内含 `SKILL.md`,可含 `references/`、`scripts/` 等附带文件)。示例:`agentskills/terminal-guide/SKILL.md`、`agentskills/skill-creator/SKILL.md`。 +- **SKILL.md frontmatter 格式**(YAML 简单解析): + ``` + --- + name: terminal-guide + description: 持久化终端使用指南。…… + --- + ``` + 后端校验逻辑见 `modules/skills_manager.py::validate_skill_directory`(第 146 行起),**只强制要求存在 `name:` 与 `description:`**(`re.search(r"(?m)^\s*name\s*:", content)` 与 description 同理)。frontmatter 全文解析见 `_parse_frontmatter`(L174)。 +- **目录名校验**:`_is_valid_skill_id`(L202),用 `SKILL_ID_PATTERN`。 + +**工作流接入判断**:工作流文件夹可直接复用这套「SKILL.md + 附带脚本」结构。建议新增一个 `WORKFLOW.md`(或复用 frontmatter 扩展字段),并在目录中携带验证过的 `scripts/` 目录。校验时除 SKILL.md 的 name/description 外,可扩展校验「工作方式→验证方式→结束方式」三段定义。 + +### 1.2 skill 创建/归档工具后端实现 + +- **工具定义**:`core/main_terminal_parts/tools_definition/file_tools.py` L139 定义 `create_skill`(描述「验证并归档一个已创建好的 skill 文件夹」)。 +- **handler**:`core/main_terminal_parts/tools_execution.py` + - `_resolve_create_skill_source_dir`(L525):解析 source_dir(相对/绝对/宿主机任意路径)。 + - `_get_create_skill_target_root`(L539):归档目标根目录 —— 优先 `infer_private_skills_dir(self.data_dir)`,否则 `data_dir` 父级下 `agentskills`。 + - `_handle_create_skill_tool`(L545):调用 `archive_skill_directory(source, target_root)` 归档;成功后同步工作区 skills(`sync_workspace_skills`)。 +- **归档函数**:`modules/skills_manager.py::archive_skill_directory`(L182)——先 `validate_skill_directory` 校验,再 `shutil.move` 移动到目标库;目标存在则拒绝(不覆盖)。 +- **私有 skill 目录推断**:`modules/skills_manager.py::infer_private_skills_dir`(L97)——host 模式统一 `~/.astrion/astrion//agentskills`;web/docker 按用户路径推断。 + +**工作流接入判断**:可仿 create_skill 新增 `create_workflow` 工具(或复用同一归档通道),handler 在 `tools_execution.py` 的 `handle_tool_call` 分发链(L960,elif tool_name 分支约 L1130)注册;归档逻辑复用 `archive_skill_directory` 的校验+移动+拒绝覆盖机制。 + +### 1.3 skill 如何注入提示词 + +- 注入点:`core/main_terminal_parts/context/messages.py` L305-320,`build_messages` 内按 system prompt 顺序追加 skills 列表: + ```python + skills_catalog = get_skills_catalog(private_dir=infer_private_skills_dir(self.data_dir)) + enabled_skills = merge_enabled_skills(...) + def _build_skills_system_prompt(): + template = self.load_prompt("skills_system") + return build_skills_prompt(template, build_skills_list(...)) + skills_prompt = self._get_or_init_frozen_prompt("frozen_skills_prompt", _build_skills_system_prompt) + if skills_prompt: messages.append({"role":"system","content":skills_prompt}) + ``` +- **模板**:`prompts/skills_system.txt`(占位 `{skills_list}`,提示用 `read_skill` 读取)。 +- **enabled/sync**:`merge_enabled_skills`(skills_manager L373)、`sync_workspace_skills`(L409)——把启用 skill 复制到工作区 `.astrion/skills/`。 +- **skill_hints 意图识别**:`config/skill_hints.json`(关键词→hint),用于在用户消息中检测相关 skill 并注入提示(读 `_inject_intent` 相关)。 + +**工作流接入判断**:工作流列表可仿 skills_prompt 在 `messages.py` `build_messages` 增加一段 system prompt 注入当前工作流上下文(当前已激活工作流的流程说明),复用 `_get_or_init_frozen_prompt` 冻结机制与 `load_prompt` 模板机制。 + +### 1.4 skill 列表/读取 API + +- **列表 API**:`server/tasks/skills.py` `GET /api/skills`(L126,`@tasks_bp.route`)→ `_list_workspace_skills`(L83)读取工作区 `.astrion/skills/*/SKILL.md`,解析 name/description/path。 +- **读取**:工具 `read_skill`(file_tools.py L132)→ handler `_handle_read_skill_tool`(tools_execution.py 中)。 + +**工作流接入判断**:仿 `server/tasks/skills.py` 新增 `GET /api/workflows`(读工作流库目录),用于前端列表展示与「作为对话新类型创建」时选择工作流。 + +--- + +## 2. 两套审核智能体架构(工作流阶段审核复用) + +### 2.1 工具审核 approval_agent + +- **实现**:`modules/approval_agent.py`(由配置 `CONFIG_PATH = Path(resolve_deploy_config("auto_approval.json"))` 指定,L16 → `config/auto_approval.json[.example]`)。 +- **调用方式**:`modules/auto_approval_service.py::run_auto_approval`(L84)构造 `ApprovalAgent(web_terminal=web_terminal)` 并 `await agent.review(payload_text=..., progress_cb=..., cancel_check=...)`。`build_auto_approval_payload`(L15)组装用户输入+最近工具操作+触发风险标记。 +- **输入**:payload 纯文本(审批场景上下文 + 当前工具调用函数名/参数)。 +- **输出**:`{"decision": "approved"|"rejected", "reason": str, "source": "approval_agent"}`。内部通过工具 `approve_decision`(L168)返回,异常/配置缺失时兜底 `{"decision":"rejected", ...}`。 +- **执行模式**:readonly 或注入只读 run_command 取证(与 goal_review 同构)。 + +**工作流接入判断**:工作流的「工具/操作级」安全审核可直接复用 `ApprovalAgent`,通过 `auto_approval_service` 同构入口调用;无需新造。若需按工作流阶段应用不同审核,可在 `run_auto_approval` 之外包装一个「阶段审核」封装函数。 + +### 2.2 目标审核 goal_review + +- **实现**:`modules/goal_review_agent.py`(配置 `CONFIG_PATH = resolve_deploy_config("goal_review.json")`,L20)。`GoalReviewAgent(web_terminal=...)`,`async review(payload_text, review_mode, progress_cb, cancel_check)`。 +- **输出**:`{"status":"done"|"continue", "message": str, "source":"goal_review_agent"}`;兜底保守返回 continue。review_mode 由 `modules/goal_state_manager.py` 常量 `REVIEW_MODE_READONLY="readonly"` / `REVIEW_MODE_ACTIVE="active"`(L34-35)决定是否注入只读 run_command。 +- **目标模式如何触发审核**:`server/goal_flow.py`: + - `maybe_start_goal`(L56):用户显式开启目标模式时启动(读 personalization 的 review_mode/end_conditions)。 + - `inject_goal_prompt`(L88):注入目标模式提示词。 + - `handle_goal_after_turn`(L147):**在主循环「主模型一轮无 tool_calls」时拦截**——先空转保护/边界检查,再调 `GoalReviewAgent.review`; + - `status=="continue"` → `append_review` 记录审核历史 + `inject_runtime_user_message(CONTINUE_PREFIX + message)` **回写续命 user 消息到 messages**,调用方 `continue` 回主循环开下一轮; + - `status=="done"` → `mark_done`,任务结束。 +- **状态落盘**:`modules/goal_state_manager.py`,工作区 `{data_dir}/goal_state.json`(含 goal、review_mode、turns、review_history 等)。 +- **触发入口**(后端):创建任务时传 `goal_mode` → `server/tasks/models.py` `create_chat_task` 存 session_data → `run_chat_task_sync` 时置 `terminal._goal_mode_requested=True`(models.py L961/L998-999)→ `chat_flow_task_main.py L1863` 检测并 `maybe_start_goal`。 + +**工作流接入判断(关键复用点)**:工作流的「阶段结束/整体结束审核」几乎可 1:1 复用 goal_review 的回写机制——在 `chat_flow_task_main.py` 主循环的 no-tool-call 结束判定处(L2226 附近 `if not tool_calls:`),当前已有 `if goal_is_active(workspace): handle_goal_after_turn(...)` 分支;工作流运行时可仿照新增「工作流阶段/整体审核」调用 `GoalReviewAgent`(或新 `WorkflowReviewAgent`),并把 continue/done 语义映射为「进入下一阶段/结束工作流」。建议抽出一个与 `goal_flow.py` 同构的 `workflow_flow.py` 编排模块,减少对主循环侵入。 + +--- + +## 3. 智能体循环与执行引擎(工作流运行时复用) + +### 3.1 主循环入口链路(骨架级) + +- **唯一入口(门闸)**:`server/chat_flow.py::process_message_task`(L130)——先 `acquire_adopted_main_task_gate` 拿对话级门闸(§12 单写者不变量),然后 `loop.create_task(handle_task_with_sender(...))`。**任何新增的主任务入口必须走此门闸**(AGENTS.md §12.4)。 +- **实际任务执行**:`server/chat_flow_task_main.py::handle_task_with_sender`(L1411): + - L1855 `messages = web_terminal.build_messages(context, message)`;`tools = web_terminal.define_tools()`。 + - L1863 目标模式启动/续注入。 + - L1962 `while max_iterations is None or iteration < max_iterations:` 主循环迭代: + - 每轮 `run_streaming_attempts(messages=messages, tools=tools, ...)`(L2082,导入自 `server/chat_flow_stream_loop.py`)调模型,返回 full_response / tool_calls。 + - **有 tool_calls** → L2325 `execute_tool_calls(...)` 执行工具(结果 append 到 messages/对话历史),`continue` 下一轮。 + - **无 tool_calls**(L2226 `if not tool_calls:`)→ 目标审核分支(L2230)→ 多智能体注入分支(L2314)→ 否则 `break` 结束。 +- **工具执行循环**:`server/chat_flow_tool_loop.py::execute_tool_calls`(L409)→ `_execute_tool_calls_impl`(L426,守护包装 try/finally 复位 `_tool_loop_active`): + - 白名单校验(allowed_tool_names)→ 权限评估 `web_terminal.evaluate_tool_permission` → 逐个 `tool_call` 解析/执行,结果 `web_terminal.context_manager.add_conversation("tool", ...)` + `messages.append({"role":"tool", ...})`。 + - 工具真实执行在 `core/main_terminal_parts/tools_execution.py::handle_tool_call`(L960,elif tool_name = handler 分发大表)。 + +**工作流接入判断**:工作流运行**不需要**新增主循环,直接复用 `process_message_task` 门闸 + `handle_task_with_sender` 迭代即可(把工作流定义作为额外的 system 上下文 + 结束阶段审核挂钩即可)。若想「阶段结束审核后进入下一阶段并继续迭代」,参照 goal_review 的 continue → `inject_runtime_user_message` + `continue` 模式,完全在现有消息/迭代机制内实现。 + +### 3.2 运行模式 work_mode 三档(plan/ask/execute)——新增一种运行方式的最相近参照 + +- **核心实现**:`core/main_terminal_parts/tools_policy.py`:`WORK_MODES = {"plan","ask","execute"}`, `WORK_MODE_DEFAULT="plan"`(L88);`set_work_mode` / `switch_work_mode`(处理 plan⇄只读权限+沙箱联动)/ `get_work_mode`;权限模式 `PERMISSION_MODES` 与 plan 锁。 +- **怎么注入提示词规则**:`core/main_terminal_parts/context/mode.py` + - `_build_work_mode_rules(mode)`(L192):三档规则文本唯一来源(plan/ask/execute 各自的 detailed_rules)。 + - `_build_work_mode_message`(L220):`load_prompt("work_mode")` 模板 + `replace work_mode/work_mode_label/mode_description/detailed_rules`。 + - 属于 `_RUNTIME_MODE_KINDS`(L133,含 permission_mode/execution_mode/network_permission/work_mode),切换走 drift 通知(`_RUNTIME_MODE_SOURCE` 第 花 种 "work_mode_change")。 + - **冻结注入**:`messages.py::build_messages` L203-208 `_get_or_init_frozen_mode_prompt("frozen_work_mode_prompt", self._build_work_mode_message)`。 +- **怎么影响工具可用性**:work_mode 主要通过**提示词**约束(三档规则正文),而非硬性工具过滤(行为差异在规则里,如 ask 禁用 ask_user 工具由提示词说明;plan 的只读是权限层联动)。工具的硬开关由 `tool_category_states`/`disabled_tools`(同一文件 tools_policy.py)控制。 + +**工作流接入判断**:若把「工作流运行」作为与 work_mode 平行的「一种运行方式」,可仿此模式:新增一类提示词规则(如 `workflow.txt` 模板 + `_build_workflow_rules`)+ 在 `messages.py` 追加一段冻结注入;运行会话期间注入工作流当前阶段上下文。但注意 work_mode 是「与用户交互节奏」正交档位,与工作流(一套流程)语义不同——更倾向工作流作为「消息级上下文+审核挂钩」,而非新增第四档 work_mode。建议工作流保持并在 `_RUNTIME_MODE_KINDS` 之外独立管理(不要混入 work_mode 切档,避免交互节奏冲突)。 + +### 3.3 提示词模板机制(prompts/ 组织 + mode.py 构建) + +- **目录**:`prompts/*.txt`(如 `main_system.txt`、`work_mode.txt`、`skills_system.txt`、`goal_review_agent.txt`、`execution_mode/`、`multi_agent/`、`sub_agent/`)。 +- **加载**:`core/main_terminal_parts/context/prompt.py::load_prompt(name)`(L157)——`Path(PROMPTS_DIR)/f"{name}.txt"`,存在则读,否则返回兜底文案。 +- **构建规则**:`context/mode.py` 负责把「运行期状态」渲染进 prompt(permission/execution/work_mode/network),`context/messages.py` 在 `build_messages`(L109)按固定 order 追加各 system prompt:主 prompt → 权限 → 执行环境 → 运行模式 → 最近对话 → 个性化 → 工作区 → AGENTS.md → skills → 记忆 → 自定义 → 禁用提示。 +- **冻结机制**:`_get_or_init_frozen_prompt` / `_get_or_init_frozen_mode_prompt` 对可变但需稳定的 system 段做一次性构建缓存。 + +**工作流接入判断**:新增 `prompts/workflow.txt` 模板(或 `prompts/workflow/` 子目录),在 `messages.py::build_messages` 适当的 order 位(建议主 prompt 后、skills 前/后)插入工作流上下文 system 段,并用 `load_prompt("workflow")` 加载。完全复用现有模板/冻结机制。 + +--- + +## 4. 前端入口与路由(/workflow/new 怎么挂) + +### 4.1 路由定义位置与现有 /multiagent 兼容重定向 + +- **前端未用 vue-router**,而是手动处理 `window.location.pathname`(无 createRouter/createWebHistory,全库无 vue-router)。 +- **路由解析/重定向核心**:`static/src/app/methods/ui/route.ts::bootstrapRoute`(L26 起): + ``` + let path = window.location.pathname.replace(/^\/+/, ''); + if (path === 'multiagent/new' || path === 'multiagent') { + history.replaceState({}, '', '/new'); path = 'new'; + } else if (path.startsWith('multiagent/')) { + const bareId = ...; history.replaceState({}, '', `/${bareId}`); path = bareId; + } + ``` + 即旧 `/multiagent/*` → 重定向到裸 `/conv_xxx`;`/multiagent/new` → `/new`(对话类型是 metadata 属性,不再是路由概念)。 + - 若裸新建路由:清空当前对话、恢复 draft → 结束。 + - 否则按 `conv_` 调 `this.enterConversation(convId, ...)`(`app/methods/conversation/bootstrap.ts`)加载并恢复。 +- `isExplicitNewConversationRoute()`:判断是否显式新建路由。 + +**工作流接入判断**:`/workflow/new` 可在 `bootstrapRoute` 增加一个分支:`if (path === 'workflow/new' || path === 'workflow')` → 进入「新建工作流对话」模式(清空 + 标记 `newConversationType='workflow'`),`history.replaceState` 保持 URL 为 `/workflow/new`。后端需相应 `with_terminal`/路由能接受该路径(未确认:当前 route 无条件把 path 当 conv id,需额外分支避开)。 + +### 4.2 对话类型机制(newConversationType / currentConversationType) + +- **状态定义**:`static/src/app/state.ts` + - `currentConversationType`(L57):当前已打开对话类型 `'normal'|'multi_agent'|null`,由 `enterConversation` 从 metadata 恢复(`bootstrap.ts` L66)。 + - `newConversationType`(L59):空对话待创建类型 `'agent'|'multi_agent'`,localStorage 持久化(key 见 state.ts 上方 `NEW_CONVERSATION_TYPE_STORAGE_KEY`),由 input composer 的 `agent-type-switcher` 修改。 +- **创建对话按类型选 API**: + - 首条消息创建:`static/src/app/methods/message/send.ts` L269:`const isMultiAgent = this.newConversationType === 'multi_agent'; const createUrl = isMultiAgent ? '/api/multiagent/conversations' : '/api/conversations';` + - 侧边栏新建:`static/src/app/methods/conversation/action.ts` L134/L276:按 `useConversationStore().sidebarConversationType` 选同两个 URL。 +- **输入栏类型选择器**:`components/input/InputComposer.vue` L328 `agent-type-switcher`(渲染 `newConversationType` 选项:智能体/多智能体)。 + +**工作流接入判断(关键)**:若工作流作为新对话类型:需在 `newConversationType`/`currentConversationType` 类型联合中增加 `'workflow'`;`send.ts L269` 与 `action.ts L134/276` 增加「工作流创建」的 URL 分支(如 `/api/workflow/conversations` 或复用 `/api/conversations`+`workflow_id` 参数);`InputComposer.vue` 的 agent-type-switcher 增加工作流选项。注意 types 是字符串字面量联合(L780 `newConversationType?: 'agent'|'multi_agent'`),需同步扩展 TS 类型与所有 switch 点。 + +### 4.3 输入栏运行模式切换器 work-mode-switcher + +- **实现位置**:`static/src/components/input/InputComposer.vue` L354:`
`,渲染 `workModeOptions`,`@click` 开 `workModeMenuOpen` 菜单。 +- **切换逻辑**:`static/src/app/methods/ui/workMode.ts`:`fetchWorkMode`(GET /api/work-mode,带 conversation_id)、`changeWorkMode`(POST /api/work-mode,409 空闲才可切)、`toggleWorkModeMenu`/`closeWorkModeMenu`。plan 联动更新前端 permissionMode/executionMode 显示。 +- **后端 API**:`server/chat/permission.py` `GET/POST /api/work-mode`(L402/L418)。 + +**工作流接入判断**:若工作流作为「普通对话的一种运行方式」(而非新 URL),可在 work-mode-switcher 同区域加一个「工作流选择器」(选当前激活的工作流 / 另存为新工作流),方法放 `static/src/app/methods/ui/workflow.ts`(同构 workMode.ts),后端提供 `GET/POST /api/workflow` 子资源。 + +--- + +## 5. 数据存储约定(工作流文件夹放哪) + +- **运行态数据根**:`config/paths.py`:`RUNTIME_ROOT = ~/.astrion/astrion`(L83-84,可 `ASTRION_DATA_ROOT` 覆盖);`_MODE = _runtime_mode()` 分流 host/web(`TERMINAL_SANDBOX_MODE` 决定)。各目录见 §1.5:`DATA_DIR/LOGS_DIR/USER_SPACE_DIR/API_USER_SPACE_DIR`(L102-106)。 +- **CUSTOM_SKILLS_DIR**:`str(Path(RUNTIME_ROOT)/_MODE/"agentskills")`(L109)——私有 skill/工作流的运行态位置。host 模式 `IS_HOST_MODE`(L112)。 +- **源码树 seed**:`AGENT_SKILLS_DIR`(默认 `./agentskills`,L163)、`PROMPTS_DIR`(`./prompts`,L162)、`AGENT_SKILLS_DIR` 默认源码树。 +- **resolve_deploy_config 回退链**(L135):`/config/`(部署者真实配置)→ 源码树 `config/`(seed)→ 源码树 `config/.example`(示例兜底)。`deploy_config_path`(L126)用于可写配置(不回退)。 +- **工作区级 .astrion**:`WORKSPACE_SKILLS_DIRNAME=".astrion/skills"`(L170)、`WORKSPACE_MEMORY_DIRNAME=".astrion/memory"`(L171)、`WORKSPACE_REVIEW_DIRNAME=".astrion/review"`(L172)。**注意:这是工作区项目内(源码树或其他工作目录)的 `.astrion`,与运行态 `~/.astrion/astrion/` 不同。** + +**工作流接入判断(关键决策点)**: +- **源码树 vs 运行态**:skill 采用「源码树 seed(`agentskills/`)” + “运行态私有(`~/.astrion/astrion//agentskills/`,CUSTOM_SKILLS_DIR)双源」,通过 `get_skills_catalog(base_dir=AGENT_SKILLS_DIR, private_dir=CUSTOM_SKILLS_DIR)` 合并(skills_manager.py L282);启用后同步到工作区 `.astrion/skills/`(`sync_workspace_skills`)。 +- 现有机制**同时支持**两种:工作流库若仿 skill,可在源码树 `workflows/`(seed)+ 运行态 `~/.astrion/astrion//workflows`(CUSTOM_SKILLS_DIR 同级)建库,再按启用/激活同步到工作区 `.astrion/workflows/`。**判断**:用户创建的工作流属「运行态/用户私有」,应落运行态(含脚本的可执行文件),源码树只放内置种子示例;这与 AGENTS.md §1.5「运行态数据不落源码树」一致。 +- 部署级配置(如 `auto_approval`、`goal_review`)走 `resolve_deploy_config`;工作流若需独立审核配置可仿 `config/workflow_review.json[.example]` 加入该回退链。 + +--- + +## 总结:新增工作流功能的最小改动路径建议(文件级) + +基于上述调研,判断实现「工作流」的最小改动路径如下(按依赖顺序,每个文件给出改动性质): + +1. **`config/paths.py`**(改动):新增 `CUSTOM_WORKFLOWS_DIR`(运行态,仿 `CUSTOM_SKILLS_DIR` L109)、`WORKFLOWS_DIR`(源码树 seed,仿 `AGENT_SKILLS_DIR` L163)、`WORKSPACE_WORKFLOWS_DIRNAME`(仿 L170 `.astrion/workflows`)三个路径常量。 + +2. **`modules/workflows_manager.py`**(新增):仿 `modules/skills_manager.py` 提供 `validate_workflow_directory` / `archive_workflow_directory` / `get_workflows_catalog` / `sync_workspace_workflows`,校验「工作方式→验证方式→结束方式」三段 + 附带 scripts。 + +3. **`core/main_terminal_parts/tools_definition/file_tools.py` + `tools_execution.py`**(改动):新增 `create_workflow` 工具定义(仿 create_skill L139)与 handler `_handle_create_workflow_tool`(仿 L545/530),在 `handle_tool_call` 分发链(L960 的 elif 分支)注册;归档复用 `modules/workflows_manager`。 + +4. **`prompts/workflow.txt`**(新增)+ **`core/main_terminal_parts/context/messages.py`**(改动):新增工作流上下文模板;在 `build_messages`(L109,skills 段 L305 附近)追加「当前激活工作流」的 system 上下文注入(复用 `load_prompt` + `_get_or_init_frozen_prompt` 冻结)。 + +5. **`server/workflow_flow.py`**(新增)+ **`server/chat_flow_task_main.py`**(改动):仿 `server/goal_flow.py` 编排「阶段/整体审核」。接入点:主循环 `if not tool_calls:` 结束判定(L2226)处,仿 goal 分支(L2230)增加工作流审核调用——复用 `modules/goal_review_agent.py`(或其派生 `WorkflowReviewAgent`)返回 done/continue;continue 注入续命 user 消息回写 messages(复用 `chat_flow_task_support.inject_runtime_user_message`)。**注意**:任何新增主任务入口必须遵守 §12 门闸(`process_message_task`)。 + +6. **`server/tasks/workflows.py`**(新增,可并入 skills.py)仿 `server/tasks/skills.py`:`GET /api/workflows`(列表/选择)+ 创建工作流对话的后端端点(如 `/api/workflow/conversations` 或复用 `/api/conversations`+`workflow_id`)。 + +7. **`static/src/app/methods/ui/route.ts`**(改动):`bootstrapRoute`(L26)增加 `/workflow/new`(及 `/workflow`)分支,进入「新建工作流对话」模式并 `history.replaceState`;避免被当作 conv id 解析。 + +8. **前端对话类型链路**(改动):`static/src/app/state.ts`(L57/59 类型联合加 `'workflow'`)、`static/src/app/methods/message/send.ts`(L269 createUrl 分支)、`static/src/app/methods/conversation/action.ts`(L134/276 分支)、`static/src/components/input/InputComposer.vue`(L328 agent-type-switcher / L354 work-mode-switcher 区域加「工作流选择器」)。若新增「选择/另存工作流」UI,仿 `static/src/app/methods/ui/workMode.ts` 建 `static/src/app/methods/ui/workflow.ts`。 + +> 附注 / 未确认项: +> - `/workflow/new` 后端的 `with_terminal` 路由是否接受该路径、前端是否需新 socket/status 兼容——**未确认**,需在实现时验证。 +> - 工作流「阶段结束审核后进入下一阶段」与 goal mode「目标完成后结束」的边界语义略有差异,需在 `workflow_flow.py` 内明确「阶段衔接」与「整体结束」的状态机,避免与 `chat_flow_task_main.py` 现有 break/continue 逻辑冲突。 +> - work_mode 三档(plan/ask/execute)是「交互节奏」正交档位;工作流不应作为第四档 work_mode,而应作为独立的「消息级上下文 + 审核挂钩」,避免与现有 `_RUNTIME_MODE_KINDS` drift 通知机制冲突。 diff --git a/workflow_research/external_products/agentic_workflow_research.md b/workflow_research/external_products/agentic_workflow_research.md new file mode 100644 index 00000000..9e93a769 --- /dev/null +++ b/workflow_research/external_products/agentic_workflow_research.md @@ -0,0 +1,258 @@ +# 外部智能体工作流(Agentic Workflow)产品设计调研报告 + +> 调研范围:主流产品的「智能体工作流」设计,即工作流中的节点/步骤由 LLM 智能体自主执行(有工具调用、有推理循环),区别于传统确定性 BPM/ETL 工作流。 +> 信息来源标注:**[官方文档]** = 官方文档/官方博客;**[官方博客]** = 官方博客;**[第三方]** = 社区/媒体/分析文章(标注具体来源)。 +> 本报告的撰写基于对上述公开资料的归纳,反映的是各产品公开设计,非代码级验证。 + +--- + +## 0. 核心立论:工作流与智能体是"控制光谱"的两端 + +调研所有产品后发现一条贯穿主线:**所有"智能体工作流"产品本质上都在解决同一个问题——在"确定性流程控制"与"LLM 自主决策"之间找一个平衡点。** Anthropic 官方博客《Building Effective Agents》给出了最清晰的框架化表述:**agentic systems 被分为两类——workflows(工作流,控制流由预设代码定义)与 agents(智能体,控制流由模型根据环境反馈自主决定)**。[官方博客] + +这条光谱从"完全结构约束"到"完全模型自治"大致为: +**确定性画布 (n8n传统节点) → 结构+局部自主 (Dify 工作流/Coze/Flowise) → 自主协作 (CrewAI Crew) → 图式可控循环 (LangGraph) → 纯自主 (OpenAI Agent/Anthropic Agent)** + +没有任何一款产品走极端,全部是"混合体"。下面的调研即为各产品如何具体落在这条光谱之上。 + +--- + +## 1. LangGraph(LangChain) + +### A. 文件/数据格式 +LangGraph 不依赖外部 DSL 文件表达图,而是用 **Python 代码 + 类型注解**直接构建。图的三个核心单元是 [官方文档]: +- **State**:共享数据结构,用 `TypedDict` 或 Pydantic `BaseModel` 定义 schema,是节点和边的输入输出契约。 +- **Nodes**:普通 Python 函数,接收 state,做计算或副作用,返回更新后的(部分)state。`State -> Partial`。 +- **Edges**:决定下一个执行哪个节点的路由函数,既有固定边也有条件边。 + +```python +class OverallState(TypedDict): + foo: str + messages: Annotated[list, add_messages] # reducer 决定如何合并 + +builder = StateGraph(OverallState, input_schema=InputState, output_schema=OutputState) +builder.add_node("node_a", node_a) +builder.add_edge("node_a", "node_b") +builder.add_conditional_edges("node_a", routing_fn, {True: "node_b", False: "node_c"}) +graph = builder.compile(checkpointer=...) +``` + +图的**状态 schema 本质上是 JSON-serializable** 的类型契约(`TypedDict`/Pydantic),每个 key 可带 **reducer 函数**(如 `operator.add`、`add_messages`)声明多个节点更新该 key 时如何合并。执行模型借鉴 Google Pregel 的 **super-step 消息传递**:每轮 super-step 里可并行的节点同批执行,节点间通过"channel 消息"激活。 [官方文档] + +### B. 节点类型体系 +LangGraph **没有预置的语义化节点类型**(没有"Dify 的 LLM 节点/代码节点"之分)。所有节点都是普通函数——"**nodes do the work, edges tell what to do next**" [官方文档]。LLM 调用、工具调用、条件判断、代码执行都是节点函数的内嵌逻辑。语言层面的抽象只有: +- 普通边 / 条件边 / 条件入口(`add_conditional_edges`) +- `Send` 对象:实现 **map-reduce**,从一条条件边动态扇出多个并行子节点(数量运行时才知道) +- `Command(update=..., goto=...)`:节点内同时"更新状态 + 换路由"的统一原语 +- 支持多 input/output/private schema 分离,节点可写私有 state channel + +循环通过"条件边指回上游节点"表达;并行通过"一个节点多条出边即并行扇出"表达。 + +### C. 自主性与结构性约束的平衡 +LangGraph 体现了最清晰的"**约束留白**"哲学:**边(edge)是开发者唯一强制约束的地方**(结构、路由、参数 schema),**节点内部完全交给代码/LLM 自主执行**。一个节点函数里可以是单次 LLM 调用,也可以是完整的多轮 ReAct 循环。开发者可以"一个 agent 就是整个图(自循环)",也可以"把 agent 作为图中一个节点,用边把它的自主范围圈住"。LangGraph 官方把这种本地化自主称为 **"workflows + agents"** 的经典模式。 [官方文档] + +### D. 验证与审核机制 +- **human-in-the-loop**:核心机制是 `interrupt()` 函数,可在节点内任意代码位置动态暂停图执行,将任意 JSON 可序列化值抛给外部,等待 `Command(resume=...)` 注入继续。 [官方文档] +- 通过 checkpointer(如 PostgresSaver/MemorySaver)+ `thread_id` 持久化图状态,暂停后可安全恢复(time travel)。 +- 没有内建的 "evaluator 节点" 语义,但 evaluator-optimizer 可以作为普通节点组合实现。 +- 提供 **recursion limit**(super-step 上限,默认 1000)+ `RecursionLimit` 主动软降级机制,防止无限循环。 + +### E. 可视化与运行时 +LangGraph **没有拖拽画布作为主要原语**,但编译后的图(`.compile()`)可用 LangGraph Studio 可视化。**编译是必要步骤**(必须有 `.compile()` 才能运行),编译做结构校验(孤儿节点等)+ 附加运行时参数(checkpointer、断点)。思维模型是"**代码即图定义**",运行时按编译后的图执行。 [官方文档] + +### F. 代码/脚本复用 +节点的本质就是 Python 函数,因此复用现有代码是**最直接的**——把任意函数 `add_node` 上去即可(封装为 `RunnableLambda`)。工具也用 Python 装饰器/函数定义。没有脚本沙箱(信任你的 Python 进程)。 + +--- + +## 2. Dify Workflow / Chatflow / Agent + +### A. 文件/数据格式 +Dify 对智能体工作流进行产品分级,并提供明确的三套模式 [官方文档 + 第三方]: +- **Agent 模式**:纯自主,写 prompt、挂工具,由模型自行决定工具调用顺序(无画布路径)。 +- **Workflow 模式**:可视化画布,**从头到尾运行一次**,无对话记忆,适合批处理/流水线。 +- **Chatflow 模式**:同一套节点系统 + 对话层(每条消息触发流程,支持记忆、流式输出)。 + +工作流的存储格式是 **YAML/JSON DSL**(`.dify.yml` 或 `.dify.json`),顶层含 `app`(元信息)、`workflow`(features + graph,graph 由 `nodes[]` + `edges[]` 组成)。DSL 保留节点的 **画布坐标 position**,可由代码直接生成和编辑(社区甚至有"用自然语言生成 Dify DSL"的工具)。 [第三方,基于 dify-workflow-skills] + +节点内变量引用用 `{{#node_id.field_name#}}`,DSL 内部用数组 `value_selector: ['node_id', 'field_name']` 表达同一条引用。变量类型严格化(string/number/object/array/file/secret 等),有 `env`(环境变量)和 `sys` 系统变量节点。 + +### B. 节点类型体系 +Dify 的工作流节点**语义化、预置、丰富**,是按"业务功能"而非"执行能力"分类的: +- **LLM & AI**:`llm`(确定性单次调用)、`agent`(自主多轮推理 + 工具调用)、`parameter-extractor`、`question-classifier` +- **逻辑控制**:`if-else`、`iteration`、`loop`(条件分支、循环、迭代) +- **数据处理**:`code`(python3/javascript)、`template-transform`、`variable-aggregator`、`variable-assigner`、`list-operator` +- **外部集成**:`http-request`、`tool`、`knowledge-retrieval` +- **输入输出**:`start`、`end`、`answer` +- **人工审批**:`human-input`(暂停等用户输入) + +关键设计点:**`agent` 节点是"自主性"在结构化画布内的显式封装**——它像 LLM 节点一样挂在流程某处,但内部是带工具调用 + 多轮推理循环的自主执行。节点有**执行分类**:EXECUTABLE(逻辑节点)、BRANCH(条件路由,如 if-else 的 true/false handle)、CONTAINER(迭代/循环子图,有内部 start/end 节点)、RESPONSE、ROOT(入口)。 + +### C. 平衡 +Dify 的哲学是"**AI 在工作流定义的边界内运行**"。官方对工作流的定位:"与其依赖单个模型自行解决所有问题,不如设计一个流程来逐步编排…AI 仍然承担繁重的工作,但在你定义的边界内运行。" [官方文档] 结构性约束体现在:**边/位置固定、变量类型严格、条件分支显式**;自主性体现在 LLM/agent 节点的 prompt 内。官方与社区都推崇"**workflow 当骨架,agent 做关节**"的混合架构。 [官方文档 + 第三方 53AI] + +### D. 验证与审核 +- **错误处理三级**:`fail-branch`(错误走并行分支,提供 error_message/error_type)、`default-value`(错误用默认值继续)、`abort`(中止)、`retry`(带重试次数与间隔)。 [第三方基于官方源码] +- `human-input` 节点作为**人工审批点**,执行到它即进入 PAUSED 状态等待输入。 +- 工作流执行状态含 PARTIAL_SUCCEEDED(错误被处理则部分成功)等细粒度状态。 + +### E. 可视化与运行时 +Dify 前端用 **React Flow** 做画布,DSL 便是画布状态的序列化(nodes/edges/position)。运行时后端是 **Python GraphEngine + WorkerPool(线程池并行)+ VariablePool(共享变量)+ EdgeProcessor(条件路由)**,前置 Graph Validator 做运行前完整性校验。DSL 与 UI 一一映射(节点→画布块、边→连线、分支用 true/false 标签)。这属于典型的"**编辑态结构数据 = 运行时执行计划**",运行时直接解释执行该结构,画布自由布局的 x/y 仅作视觉呈现,执行顺序由 **edges 连接关系**决定而非坐标。 [第三方基于官方源码] + +### F. 复用 +`code` 节点内置 python3/javascript 沙箱;`tool` 节点对接外部 API;agent 节点可挂载工具与内部工作流。 + +--- + +## 3. Coze / 扣子 + +### A. 文件/数据格式 +Coze 工作流以**可视化画布**为主,支持**导入导出的 JSON DSL**(`{"nodes":[...],"edges":[...],"variables":[...]}`)。工作流与对话流是两类:工作流预置 input 参数,对话流额外预置 `USER_INPUT`、`CONVERSATION_NAME` 会话参数(可互相转换)。 [官方文档] + +### B. 节点类型体系 +Coze 按官方文档的节点家族分为:基础节点(开始/结束)、**大模型节点**、**插件节点**(调用工具 API)、**工作流节点**(工作流间嵌套调用)、业务逻辑节点(条件判断、循环、代码)、数据库节点、知识库节点、图像处理、会话/消息节点等。 [官方文档] +三个最核心的自主/执行节点: +- **开始节点**:定义触发条件与输入参数(String/Number/Boolean/Object/Array/File 等类型),是工作流入口。 +- **大模型节点**:核心 AI 节点。可配置系统/用户提示词,**"添加技能"(插件/工作流/知识库)后它变身为近自主智能体**——官方明确说"大模型节点运行时,会根据用户提示词自动调用插件…能力更接近一个独立运行的智能体"。 [官方文档] +- **代码节点**:支持 Python/JS,通过 `params = args.params` 接收上游变量,`return {key:value}` 定义输出参数。 +- **循环节点**:数组循环/指定次数/无限循环三种模式;条件判断节点决定流转。 + +### C. 输入输出参数绑定 +Coze 的一个特色是**节点输入输出参数显式定义**:大模型/代码/插件节点在配置面板明确声明输出参数(名称+描述+类型),下游节点通过 `{{变量}}` 或 `{{变量名.子变量名}}`/`{{变量名[索引]}}` 引用。参数类型需严格匹配(注释:类型不一致会报错)。大模型节点的输出参数有名称与描述,帮助模型正确生成结构化返回。 [官方文档 + 第三方] + +### D/F (合并) +- 验证:大模型节点支持**异常忽略**(失败继续,用默认输出);代码节点默认最长执行 5 分钟(有超时约束);插件是能力扩展的载体。没有突出的原生 guardrail/evaluator 层(主要靠 prompt 与试运行调试)。 +- 复用:**插件节点**是复用既有 API/工具的一等公民,代码节点复用脚本(沙箱)。 + +### E. 可视化 +Coze 是纯拖拽画布产品,画布布局即工作流拓扑,运行直接按连线顺序解释执行。循环体是一类**容器式画布**(内部节点不可拖出,需在循环体内添加)。 + +--- + +## 4. OpenAI AgentKit / Agent Builder(2025 发布) + +### A/B. 定位与节点 +2025-10-06 DevDay 发布 AgentKit,核心是 **Agent Builder**(beta):一个拖拽可视化画布,"像 agents 界的 Canva",直接用拖拽节点 + 连线构建多步骤、多智能体工作流。 [官方博客 + 第三方 MarkTechPost/Superprompt/CodeConductor] +节点类型据第三方整理为:**Agent节点**(由 GPT 模型驱动)、**工具节点**(actions)、**逻辑节点**(条件、循环)、以及 **Guardrails(流入/流出筛查)** 与人工审批点。 [第三方 digitalapplied] 支持节点顺序/并行连接,Responses API 驱动执行。配上 Connector Registry(连接器注册中心)、ChatKit(嵌入聊天 UI)、Evals(痕迹打分、数据集、自动 prompt 优化)、强化微调,构成"构建-部署-优化"全栈。 + +### C/D. 自主性与审核 +Agent 节点封装了模型自主决策;Guardrails 提供输入/输出的安全筛查;支持 **preview runs 与 inline eval**(画布内联评估),以及完整 versioning。这正是"结构性约束(画布、connector、guardrail)+ 节点内自主(agent 节点)"的落地。 [官方博客 + 第三方] + +### E. 发布与嵌入 +Agent Builder 的产物可通过 **ChatKit**(可嵌入聊天 UI)与 **Agents SDK** 发布嵌入应用。第三方普遍指出其强项是**原型快速搭建**,弱项是生产级(部署、回滚、可观测、成本、状态管理)仍需外部工程层补齐。 [第三方 CodeConductor] + +### C 备注 +OpenAI 官方对 Agent Builder 的核心叙事是"**把编排层的 plumbing 接管**",把工作流从 Zapier/n8n 式 API 连接升级为"推理+工具+评估"的 agent 平台。 + +--- + +## 5. Anthropic《Building effective agents》(workflow vs agent 判定标准) + +这是本次调研的**理论基石**。其核心概念(workflow 与 agent 的分野)准确刻画了"智能体工作流"产品的本质。 [官方博客] + +### 五大 workflow 模式 +1. **Prompt Chaining(提示链)**:任务分解为固定有序步骤,每步处理上一步输出;可加程序化 gate 检查环节是否偏离。适用于可干净分解为固定子任务、且用延迟换精度的场景。 +2. **Routing(路由)**:先分类输入,再导向专门子任务/子提示词。用于类别差异大、分类可靠的任务。 +3. **Parallelization(并行化)**:LLM 同时对子任务工作,程序化聚合输出;两种变体——sectioning(分片)与 voting(多attempt投票)。 +4. **Orchestrator-Workers(编排者-工人)**:中央 LLM 动态分解任务、分派给 worker LLM、合成结果。与并行化的关键区别是**子任务不是预定义**,而是由编排者依据具体输入**运行时决定**。 +5. **Evaluator-Optimizer(评估者-优化者)**:一个 LLM 生成、另一个提供评估反馈,构成循环。适合有清晰评估标准且迭代优化有可度量价值的场景。 + +### workflow 与 agent 的判定标准(核心) +- **Workflow**:通过**预定义代码编排 LLM 与工具调用**,开发者掌控控制流(控制路径)。 +- **Agent**:让**模型从环境反馈中选择下一次工具调用**,开发者掌控的是目标与 guardrail,而非每条分支。 + +### 何时优先选哪类 +- 需可预测、一致性 → workflow;需大规模灵活性 + 模型驱动决策 → agent。 +- Workflow **优于** agent 的判定:**任务步骤可预测、有清晰成功标准、可程序化 gate**。反之 open-ended、步骤数不可预测、能硬编码固定路径时才应考虑 agent。 +- 关键警告:agent 有更高成本与"复合错误(compounding errors)"风险,应在沙箱环境充分测试 + 配 guardrail;没有评估度量就添加复杂度是错误。 + +--- + +## 6. CrewAI(Crew + Flow 双层设计) + +### A/B. 双层抽象 +CrewAI 是 Python 开源框架,用**代码 + YAML 配置**表达(`agents.yaml`/`tasks.yaml`,@CrewBase 装饰器连接 YAML 与代码),是五类原语:Agent(角色/目标/背景/工具)、Tool、Task、Process、Crew。 [第三方 Mastra + GitHub 官方] +其最具借鉴意义的设计是 **Crew(自主协作)与 Flow(确定性流程)并存的双层架构** [第三方 Mastra / firecrawl / GitHub]: +- **Crew = 自主层**:代理以角色扮演、自主协作、委派(delegation),适应开放、路径不可预知的 agentic 任务。Process 有 sequential(顺序传参)与 hierarchical(manager 动态分工)两种。 +- **Flow = 控制层**:**确定性、事件驱动的编排**,用装饰器(`@start`/`@listen`/`@router`)构建事件状态机,提供细粒度状态管理与可预测执行路径,满足可审计、可复现需求。 + +### C/D/F +- 平衡哲学(官方 & 社区一致强调):"多数生产部署**把 Crew 包在 Flow 里**——Flow 在必须受控的部分施加强结构,Crew 在需要灵活的地方自主"。[第三方 Mastra] +- 验证:Task 支持 human-in-the-loop(完成前要求人工审核)、结构化输出(JSON/Pydantic)、任务级约束校验(output validation reject);工具用 `@tool` 装饰器复用 Python 函数。 + +--- + +## 7. 补充:确定性画布中嵌入自主智能体(n8n / Flowise) + +n8n 的 **AI Agent 根节点**是"如何在确定性画布里嵌入自主体"的标杆做法 [官方文档 n8n + 第三方]: +- **AI Agent 节点是一个"根节点",把 LLM 工具循环封装成一个单节点停在画布上**。接线连到该节点的下游节点(HTTP Request、数据库、Code、Airtable、MCP server 等)自动成为它的"工具"。 +- **模型在这个节点内部跑循环**:读上下文 → 决定是否/调用哪个工具 → 用工具输出选择下一步或产出最终答案。第三方明确:"agentic 的部分就是循环。" [第三方 christopheralarcon] +- **约束留白**:画布拓扑、连线(哪些能力可用)是开发者强制约束;节点内部每轮如何选工具是模型自主。 +- n8n 的数据哲学是 item-per-item 逐项处理,可加 Loop/Execute Workflow 做批处理内循环。 + +Flowise 则是**把 LangChain 的组件模型搬上画布**:每个 chain/agent/vector store/memory/tool 都是节点,一 flow ≈ 一 agent 或 chain,多 agent 通过 flow 接线组合。 [第三方 Jahanzaib.ai] + +--- + +## 综合问题归纳(A-G 对照) + +**A. 文件/数据格式** +| 产品 | 格式 | 特征 | +|---|---|---| +| LangGraph | Python + TypedDict/Pydantic | 图 = 代码;状态 schema 即 JSON 契约 + reducer | +| Dify | YAML/JSON DSL `.dify.yml` | app/workflow/nodes[]/edges[];变量 `{{#node.field#}}`;含画布坐标 | +| Coze | 可视化 + JSON DSL(导入导出) | 节点/边/变量声明;输入输出参数显式 | +| CrewAI | YAML + Python | agents.yaml/tasks.yaml + @CrewBase 绑定 | +| OpenAI Agent Builder | 云端可视化 + SDK(Responses API) | 画布产物经 ChatKit/Agents SDK 发布 | +| n8n | JSON 工作流定义 | 节点数组 + 连线,AI Agent 为根节点 | + +**B. 节点类型体系** 分两类设计流派: +- **语义化预置节点(Dify/Coze)**:区分"deterministic 节点"(llm、code、if-else、http)与"autonomy 节点"(agent、大模型节点带技能);条件用 if-else/question-classifier,循环用 iteration/loop,并行靠 DAG 扇出。 +- **统一函数/图(LangGraph)**:不预置语义节点,结构化约束全部落到"边/状态 schema"这一层,节点内部任意。 + +**C. 自主与约束的平衡**:共同最佳实践是"**结构在边上、自主在节点内**"。三层约束次序:① **结构约束**(画布拓扑/边/参数 schema,强制,开发者可控)→ ② **本地自主**(节点内 LLM 多轮循环+工具)→ ③ **软性/安全约束**(guardrail/evaluator/human-in-loop/recursion limit)。Anthropic 指出管理自主性的关键不是剥夺模型决策,而是"控制目标与 guardrail 而非每条分支"。 + +**D. 验证与审核**: +- Human-in-loop:LangGraph `interrupt()`、Dify `human-input`、CrewAI task 级 human review。 +- Evaluator/Guardrail:OpenAI Guardrails + inline Evals;Anthropic evaluator-optimizer 是流程级模式;Dify fail-branch/retry 是错误处理;LangGraph recursion limit 兜底。 +- 共同点:**审核是"插入流程的停顿点/旁路节点"**,而非破坏流程的硬校验。 + +**E. 可视化 vs 运行时**:主流(Dify/Coze/n8n/OpenAI)是"**编辑态结构数据 = 运行时执行计划**",画布 x/y 坐标仅作视觉,执行顺序由 edges 决定;前端(React Flow)序列化 DSL → 后端(解释执行引擎,如 Dify GraphEngine/WorkerPool)逐节点运行。LangGraph 走"代码定义图 → 编译 → 运行时 super-step 消息执行"。没有"编译成独立二进制"的做法,都是**解释执行结构数据**。 + +**F. 复用代码/脚本**:Dify code 节点沙箱、Coze 代码节点、CrewAI/n8n 的 `@tool` 函数、LangGraph 节点即函数、n8n 把普通节点当 agent 工具。 + +--- + +## G. 对"复用现有智能体循环引擎 + 自然语言+结构文件定义流程 + 软性阶段审核"项目的 5 个建议决策 + +> 针对该项目(复用已有智能体循环引擎,用自然语言+结构化文件定义流程,软性阶段审核而非硬性步骤校验),以下是最值得借鉴的设计: + +**✅ 建议决策 1:双层抽象——"引擎自主"与"流程结构"分离。** +借鉴 CrewAI Crew/Flow 与 Dify "workflow 骨架 + agent 关节",把"复用现有循环引擎"封装成一个"自主节点",让它在流程文件的某一步骤内自由执行(本地多轮循环),而流程文件只约束"节点顺序、路由、进来的参数 schema、出去的产物契约"。结构在边上、自主在节点内。 + +**✅ 建议决策 2:用"结构化文件(YAML/JSON)定义流程 + 自然语言填充节点行为"双通道表达。** +借鉴 Dify DSL 与 CrewAI YAML:文件承载拓扑/参数/路由(可版本化、可评审、可 diff),节点内部行为(prompt、工具约束、评估标准)用自然语言声明。这样"用中文写流程"即为合法编辑,天然支持本项目叙事。 + +**✅ 建议决策 3:把关卡设计为"软性阶段审核点/旁路节点",而非硬校验。** +借鉴 LangGraph `interrupt()` 与 Dify human-input:审核是一个"插入流程的暂停节点",只暴露当前阶段产物与决策参数,等待外部确认继续,而非在每个步骤做格式硬校验。这正好契合"软性阶段审核"的定位——审核即一个节点类型,可开可关。 + +**✅ 建议决策 4:把"评估/护栏"做成可插拔的非阻塞节点。** +借鉴 Anthropic evaluator-optimizer 与 OpenAI guardrail+eval:评估者作为独立 LLM 节点在阶段旁路运行,产出"是否通过/反馈",通过与否由审核节点消费,而不是硬性阻断流程(软性)。设置最大循环数(recursion limit 思想),防评估死循环。 + +**✅ 建议决策 5:画布布局与执行逻辑解耦。** +借鉴 Dify/React Flow:存储结构文件中的 position 仅作可视化布局,执行顺序完全由 edges/节点顺序决定。这样无需布局也能运行(纯结构文件 + 自然语言即能定义流程),画布只是可选的可视化层。 + +**❌ 要避免的 3 个坑** + +**⚠️ 坑 1:为"结构感"而过度预置节点类型,导致每一种思维都要新造一类节点。** +Dify 节点爆炸是反面教材——每加一个能力就多一类型。应让节点类型"最小化且正交"(流程结构节点 + 一个通用自主节点 + 一个审核节点),把大部分逻辑留给节点内 LLM/引擎,而非堆节点类型。 + +**⚠️ 坑 2:软性审核做成"无值守地自动放行",退化为硬校验或完全形同虚设。** +不做"硬步骤校验"≠ 不做任何结构完整性校验。应做**运行前结构性验证**(节点 ID 唯一、边引用存在、有终点、无非法循环——借鉴 Dify Graph Validator),而把"内容质量"交给软性阶段审核。结构与内容两类校验分开,缺一不可。 + +**⚠️ 坑 3:忽视状态持久化与恢复。** +智能体循环被暂停在审核点后,若没有 checkpoint/thread 机制(借鉴 LangGraph checkpointer),就无法恢复、无法时间回溯、故障无法续跑。一切 HITL 都依赖"暂停-恢复"这层底座,必须在流程引擎里一等地位,而不是事后补丁。 + +--- + +> 来源标注汇总:LangGraph 部分主要依据 [官方文档 docs.langchain.com];Dify 部分依据 [官方文档 docs.dify.ai] 与基于官方开源的 [第三方 dify-workflow-skills/EvoMap/53AI];Coze 依据 [官方文档 docs.coze.cn] 与 [第三方];OpenAI AgentKit 依据 [官方博客 openai.com DevDay] 与 [第三方 MarkTechPost/digitalapplied/CodeConductor/Superprompt];Anthropic 依据 [官方博客]。CrewAI 依据 [官方 GitHub] 与 [第三方 Mastra/firecrawl];n8n 依据 [官方文档 docs.n8n.io] 与 [第三方];Flowise 依据 [第三方 Jahanzaib.ai]。第三方内容多基于官方源码/转述,个别细节(如 Dify 具体节点内部字段)以第三方整理为主,未做运行级验证。