# 外部工作流 API 参考 当需要从其他应用或新的集成层调用 agent-management 工作流时,按本参考实现服务调用。 ## 契约概要 - 基础路径:`http(s)://:/api/v1` - 默认后端端口:`2438` - 鉴权:每个 `/api/v1/**` 请求需携带 `X-API-Key: ` - JSON 成功响应包: ```json { "code": "OK", "message": "", "data": {} } ``` - 错误响应包: ```json { "code": "VALIDATION_FAILED", "message": "可读错误信息", "data": null } ``` - 主要错误码:`UNAUTHORIZED`、`VALIDATION_FAILED`、`WORKFLOW_NOT_FOUND`、`RUN_NOT_FOUND`、`GRAPH_INVALID`、`RUN_ALREADY_STARTED`、`INTERNAL_ERROR` ## 端点 | 方法 | 路径 | 用途 | |---|---|---| | `GET` | `/api/v1/workflows` | 列出当前 API key 可访问的工作流。当前 agent-management 实现返回所有可访问工作流;分页/搜索查询参数仅作前向兼容保留,除非已确认目标版本支持。 | | `POST` | `/api/v1/workflows/{workflowId}/runs` | 创建一次运行,可携带变量与可选文件 | | `POST` | `/api/v1/workflows/{workflowId}/runs/{runId}/start` | 启动一个已创建的异步运行 | | `GET` | `/api/v1/workflows/{workflowId}/runs/{runId}/stream` | 订阅 SSE 节点/运行事件 | | `GET` | `/api/v1/workflows/{workflowId}/runs/{runId}` | 查询运行状态、输出、节点和工作空间信息 | | `GET` | `/api/v1/workflows/{workflowId}/runs/{runId}/nodes/{nodeId}/logs` | 查询某节点的持久化日志 | | `GET` | `/api/v1/workflows/{workflowId}/runs/{runId}/workspace` | 下载工作空间 zip | ## 推荐的异步流程 1. `POST /workflows/{workflowId}/runs`,带 `async: true`。 2. 读取 `data.runId` 和 `data.links`。 3. `POST /workflows/{workflowId}/runs/{runId}/start`。 4. 打开 `GET /workflows/{workflowId}/runs/{runId}/stream`,请求头 `Accept: text/event-stream`。 5. 收到 `workflow_complete` 或 `workflow_error` 后,关闭流或标记为终态。 6. 查询 `GET /workflows/{workflowId}/runs/{runId}` 获取持久化输出与节点摘要。 7. 将 `GET /workflows/{workflowId}/runs/{runId}/workspace` 作为二进制下载入口提供给用户。 仅当期望"单次阻塞请求直接返回 SSE"时才使用 `async: false`。 ## 创建运行 纯 JSON 请求: ```http POST /api/v1/workflows/12/runs X-API-Key: demo-key Content-Type: application/json { "variables": { "topic": "大语言模型在企业中的应用", "maxTokens": 2048, "options": { "lang": "zh", "verbose": false } }, "async": true, "failStrategy": "abort", "ttlHours": 720 } ``` Multipart 请求: ```http POST /api/v1/workflows/12/runs X-API-Key: demo-key Content-Type: multipart/form-data payload: {"variables":{"topic":"汇总报告"},"async":true} files: report.md files: inputs/2024/data.csv ``` 字段说明: - `variables`:自定义工作流输入变量;对象;可选。 - `async`:默认 `true`。为 `true` 时仅创建;为 `false` 时立即启动并以 SSE 形式返回。 - `failStrategy`:取值 `abort` 或 `skip`;可选且前向兼容。当前 agent-management 实现中该字段虽被 DTO 接收,但执行仍依赖 `graphData` 中节点级别的 `failStrategy`;除非目标版本显式支持请求级覆盖,否则不要依赖此字段。 - `ttlHours`:工作空间保留小时数;默认 `720`。 - `files`:可重复的 multipart 二进制 part;可选。 - `X-Relative-Path`:multipart part 的可选 header,用于保留目录路径。若客户端技术栈不支持,则退化为仅使用文件名并明确记录该限制。 `async: true` 的响应: ```json { "code": "OK", "data": { "runId": "a3f9b2c1", "workflowId": 12, "status": "CREATED", "createdAt": "2026-07-01T08:30:00Z", "links": { "start": "/api/v1/workflows/12/runs/a3f9b2c1/start", "stream": "/api/v1/workflows/12/runs/a3f9b2c1/stream", "result": "/api/v1/workflows/12/runs/a3f9b2c1", "workspace": "/api/v1/workflows/12/runs/a3f9b2c1/workspace" } } } ``` ## SSE 流 打开连接: ```http GET /api/v1/workflows/{workflowId}/runs/{runId}/stream X-API-Key: Accept: text/event-stream ``` 断线重连时携带: ```http Last-Event-ID: 42 ``` 每条事件遵循标准 SSE 格式: ```text event: node_stream id: 43 data: {"runId":"a3f9b2c1","type":"node_stream"} ``` 事件类型: - `run_started`:引擎已启动。 - `node_status`:节点状态变更。用于创建/更新节点卡片。 - `node_stream`:节点增量流。`kind` 取值为 `thinking`、`tool_call` 或 `tool_result`。 - `workflow_complete`:终态成功。包含最终输出和工作空间/结果 URL。 - `workflow_error`:终态失败。包含错误信息,通常带有失败节点 ID。 关键负载字段示例: ```json { "runId": "a3f9b2c1", "nodeId": "node-2", "nodeType": "agent", "label": "研究助手", "status": "RUNNING", "kind": "thinking", "content": "首先我需要搜索相关资料...", "toolName": null, "timestamp": "2026-07-01T08:30:07Z" } ``` 客户端行为约定: - 以 `nodeId` 为主键维护每个节点的状态。 - 将 `node_stream.kind === "thinking"` 的内容追加到该节点的思考缓冲区。 - 将 `tool_call` 与 `tool_result` 作为日志存储,保留工具名和内容。 - 把 `workflow_complete` 与 `workflow_error` 视为终态。 - 如需支持重连,持久化最近一条 SSE 的 `id`。 ## 查询结果 ```http GET /api/v1/workflows/12/runs/a3f9b2c1 X-API-Key: demo-key ``` 预期的 data 形态: ```json { "runId": "a3f9b2c1", "workflowId": 12, "status": "SUCCESS", "startedAt": "2026-07-01T08:30:05Z", "completedAt": "2026-07-01T08:31:12Z", "error": null, "outputs": { "summary": "本报告探讨了...", "_workingDirFiles": ["report.md"], "_runId": "a3f9b2c1" }, "nodes": [ { "nodeId": "node-2", "nodeType": "agent", "label": "研究助手", "status": "SUCCESS", "output": { "research": "..." }, "error": null, "logsCount": 124, "logsUrl": "/api/v1/workflows/12/runs/a3f9b2c1/nodes/node-2/logs" } ], "workspace": { "fileCount": 12, "totalBytes": 456789, "downloadUrl": "/api/v1/workflows/12/runs/a3f9b2c1/workspace" } } ``` 状态取值:`CREATED`、`RUNNING`、`SUCCESS`、`FAILED`。 ## 日志与工作空间 节点日志: ```http GET /api/v1/workflows/{workflowId}/runs/{runId}/nodes/{nodeId}/logs ``` 日志类型通常为 `THINKING`、`TOOL_CALL`、`TOOL_RESULT`、`INFO`、`ERROR`。把思考过程抽到独立展示区,非思考日志放在可折叠的日志列表中。 工作空间下载: ```http GET /api/v1/workflows/{workflowId}/runs/{runId}/workspace ``` 响应是二进制 zip 内容,不要走 JSON 响应拦截器。 ## 安全与集成注意事项 - 默认不要在前端代码中暴露 `X-API-Key`。优先使用后端代理,由服务端注入密钥。 - base URL 与 API key 应存放在环境/配置中,不要硬编码到源码。 - 如实现代理上传,需校验路径,防止 `../` 路径穿越。 - 代理 SSE 时关闭缓冲,保留事件名、id 和 data 负载。 - 未经用户同意,不要悄悄把 SSE 降级为轮询。 - 使用 axios/fetch 等封装时,对 `text/event-stream` 和工作空间 zip 端点绕过 JSON 响应包解析。