external-workflow-api.md 7.2 KB

外部工作流 API 参考

当需要从其他应用或新的集成层调用 agent-management 工作流时,按本参考实现服务调用。

契约概要

  • 基础路径:http(s)://<host>:<port>/api/v1
  • 默认后端端口:2438
  • 鉴权:每个 /api/v1/** 请求需携带 X-API-Key: <key>
  • JSON 成功响应包:

    { "code": "OK", "message": "", "data": {} }
    
  • 错误响应包:

    { "code": "VALIDATION_FAILED", "message": "可读错误信息", "data": null }
    
  • 主要错误码:UNAUTHORIZEDVALIDATION_FAILEDWORKFLOW_NOT_FOUNDRUN_NOT_FOUNDGRAPH_INVALIDRUN_ALREADY_STARTEDINTERNAL_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.runIddata.links
  3. POST /workflows/{workflowId}/runs/{runId}/start
  4. 打开 GET /workflows/{workflowId}/runs/{runId}/stream,请求头 Accept: text/event-stream
  5. 收到 workflow_completeworkflow_error 后,关闭流或标记为终态。
  6. 查询 GET /workflows/{workflowId}/runs/{runId} 获取持久化输出与节点摘要。
  7. GET /workflows/{workflowId}/runs/{runId}/workspace 作为二进制下载入口提供给用户。

仅当期望"单次阻塞请求直接返回 SSE"时才使用 async: false

创建运行

纯 JSON 请求:

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 请求:

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:取值 abortskip;可选且前向兼容。当前 agent-management 实现中该字段虽被 DTO 接收,但执行仍依赖 graphData 中节点级别的 failStrategy;除非目标版本显式支持请求级覆盖,否则不要依赖此字段。
  • ttlHours:工作空间保留小时数;默认 720
  • files:可重复的 multipart 二进制 part;可选。
  • X-Relative-Path:multipart part 的可选 header,用于保留目录路径。若客户端技术栈不支持,则退化为仅使用文件名并明确记录该限制。

async: true 的响应:

{
  "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 流

打开连接:

GET /api/v1/workflows/{workflowId}/runs/{runId}/stream
X-API-Key: <key>
Accept: text/event-stream

断线重连时携带:

Last-Event-ID: 42

每条事件遵循标准 SSE 格式:

event: node_stream
id: 43
data: {"runId":"a3f9b2c1","type":"node_stream"}

事件类型:

  • run_started:引擎已启动。
  • node_status:节点状态变更。用于创建/更新节点卡片。
  • node_stream:节点增量流。kind 取值为 thinkingtool_calltool_result
  • workflow_complete:终态成功。包含最终输出和工作空间/结果 URL。
  • workflow_error:终态失败。包含错误信息,通常带有失败节点 ID。

关键负载字段示例:

{
  "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_calltool_result 作为日志存储,保留工具名和内容。
  • workflow_completeworkflow_error 视为终态。
  • 如需支持重连,持久化最近一条 SSE 的 id

查询结果

GET /api/v1/workflows/12/runs/a3f9b2c1
X-API-Key: demo-key

预期的 data 形态:

{
  "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"
  }
}

状态取值:CREATEDRUNNINGSUCCESSFAILED

日志与工作空间

节点日志:

GET /api/v1/workflows/{workflowId}/runs/{runId}/nodes/{nodeId}/logs

日志类型通常为 THINKINGTOOL_CALLTOOL_RESULTINFOERROR。把思考过程抽到独立展示区,非思考日志放在可折叠的日志列表中。

工作空间下载:

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 响应包解析。