Files

17 KiB
Raw Permalink Blame History

任务分析定时 · 对外接口对接文档

面向外部任务系统(下称「对方系统」)的开发者。覆盖任务接入、时间线详情拉取、 总控问答、定时数据交付(任务 6 块 JSON)四组接口。智能体编排配置 (选业务链 / 执行频率)在 DeerFlow 任务分析页操作,对方系统无需开发。

相关实现:app/gateway/routers/task_analysis.py(任务/绑定/运行记录)、 app/gateway/routers/task_analysis_qa.py(问答)。

0. 通用约定

  • Base URL:DeerFlow Gateway 地址(如 http://<host>:8001)。
  • 鉴权:所有接口需带 Authorization: Bearer <token> 请求头(token 获取方式见登录对接,本文不重复)。
  • Content-Type:application/json(SSE 接口除外,响应为 text/event-stream)。
  • 时间格式:ISO 8601 字符串(含时区,如 2026-09-10T10:14:55+08:00)。
  • 两类任务标识:
    • source_task_id:对方系统的任务号(创建时由你们传入);
    • task_id:DeerFlow 内部任务 id(创建接口的响应里返回,问答接口使用它)。 创建任务后请保存响应中的 task_id;也可随时通过时间线详情接口重新取到。

1. 任务接入

1.1 创建任务

对方系统创建任务完成后调用,DeerFlow 落一条任务记录(初始未绑定分析方案)。

POST /api/task-analysis/external/tasks

请求体:

{
  "source_task_id": "TS-2026-0147",
  "name": "东南亚舆论环境监测",
  "description": "持续跟踪东南亚重点渠道舆论动向,输出结构化分析详情。"
}
字段 类型 必填 说明
source_task_id string(≤128) 是 对方任务号,全局唯一
name string(≤512) 是 任务名称
description string(≤8192) 否 任务简介。定时执行时注入各智能体的任务上下文以此为准(存量快照,执行时不会回拉)

响应 200:

{
  "task_id": "ta-TS-2026-0147",
  "default_chain_id": "ta-demo-chain"
}
  • task_id:DeerFlow 内部任务 id,问答接口需要它,请保存。
  • default_chain_id:DeerFlow 侧最近一次绑定使用的业务链 id,可作为你们界面上绑定流程的默认选项;无绑定为 null。

错误:409 —— source_task_id 已存在。

1.2 删除任务

对方系统删除任务时同步调用,彻底删除:任务、绑定、全部执行记录、过程消息与时间线版本一并清除(不可恢复)。

DELETE /api/task-analysis/external/tasks/{source_task_id}

响应 200:{"deleted": true, "task_id": "..."}。错误:404 —— 任务不存在。

2. 任务详情(时间线)

对方系统详情页的数据源。每次定时执行成功会落一期时间线版本(含各智能体产出),按时间倒序返回。

GET /api/task-analysis/external/tasks/{source_task_id}/detail?limit=20&offset=0

响应 200:

{
  "task": {
    "task_id": "ta-TS-2026-0147",
    "source_task_id": "TS-2026-0147",
    "name": "东南亚舆论环境监测"
  },
  "binding": {
    "chain_id": "ta-demo-chain",
    "cron_expr": "0 9 * * *",
    "schedule_type": "cron",
    "enabled": true
  },
  "timeline": [
    {
      "id": "…",
      "external_task_id": "ta-TS-2026-0147",
      "run_id": "tar-…",
      "blocks": {
        "eightbf-roundtable-intent": {
          "name": "8BF 任务理解",
          "seat_agent_id": "eightbf-roundtable-intent",
          "content": "(该智能体本次产出的 Markdown 正文)",
          "format": "markdown"
        },
        "c0a8799da8724e179e086ea9ca723967": { "name": "策略分析师", "…": "…" }
      },
      "created_at": "2026-09-10T10:15:13+08:00"
    }
  ]
}
  • binding:当前绑定信息(未绑定为 null,此时 timeline 不会有新版本)。 schedule_type 为执行方式:cron = 按 cron_expr 频率定时执行; once = 只执行一次(创建后立即执行,之后不再自动执行,cron_expr 不生效)。
  • timeline[].blocks:每个参与执行的智能体一块,key 为该智能体的 agent_id, name 为执行时的名称快照,content 为其交付正文(Markdown)。 按你们的详情分区规则渲染即可(如按 block 顺序分栏)。
  • 分页:limit(默认 20)/ offset,按 created_at 倒序。

3. 总控问答(详情页对话)

详情页的对话入口:用户提问 → DeerFlow 总控按任务绑定的编排给对应智能体派活 → 智能体执行 → 总控汇总结论。一次问答会话记为一条「手动执行」记录,过程消息可查。

3.1 发起问答会话(init)

POST /api/task-analysis/tasks/{task_id}/qa/init

注意:此处 {task_id} 为 DeerFlow 内部任务 id(创建接口响应里的 task_id)。

请求体:空(无需参数)。

响应 200:

{
  "run_id": "tar-0743654e-…",
  "coordinator": "roundtable-coordinator",
  "thread_ids": {
    "eightbf-roundtable-intent": "ta-seat-…-…",
    "c0a8799da8724e179e086ea9ca723967": "ta-seat-…-…",
    "roundtable-coordinator": "ta-seat-…-…"
  },
  "seats": [
    { "agent_id": "eightbf-roundtable-intent", "name": "8BF 任务理解" },
    { "agent_id": "c0a8799da8724e179e086ea9ca723967", "name": "策略分析师" }
  ]
}
  • run_id:本次问答会话的运行记录 id(查历史 / 应用方向都用它)。
  • thread_ids:会话线程映射,请保存并在后续每轮 stream 原样传回(会话不跨请求保存在服务端)。
  • init 时已自动把任务上下文(名称/简介/编排/历次方向备注)注入总控,之后每轮消息传用户原话即可。

错误:400 —— 任务未绑定分析方案 / 绑定链没有可调度席位。

3.2 发送消息(stream,SSE)

POST /api/task-analysis/tasks/{task_id}/qa/stream
Content-Type: application/json
Accept: text/event-stream

请求体:

{
  "run_id": "tar-0743654e-…",
  "message": "请让两个席位各自分析当前的主要风险点,然后给我综合结论。",
  "thread_ids": { "…init 返回的映射原样传回…" }
}

响应为 SSE 流,每帧 data: {JSON}\n\n。帧类型:

帧 触发时机 关键字段
LangGraph 上游事件(无 event 字段的多种帧) 总控正在生成(token 流) 透传自运行时,可用于打字机效果
{"event": "leader", "status": [[seat_id, task], …], …} 总控一轮结束 status 为派活表(二维数组)时表示已派活
{"event": "leader", "status": "clarification", …} 总控需要澄清 question / options,前端展示追问,等用户补充后发下一轮
{"event": "leader", "status": [], "content": …} 总控给出结论(共识) content 为结论正文
{"event": "seat", "agent": id, "name": …, "content": …} 某智能体执行完成 content 为该智能体交付正文
{"event": "round_done", "consensus": true/false} 本轮结束 consensus=true 会话已收口(run 置 succeeded);false(如澄清)可继续发下一轮

一轮完整时序:leader(派活)→ 若干 seat(交付)→ leader(综合结论)→ round_done。

约定:

  • 澄清(consensus=false, kind=clarification):继续对同一 run_id 发下一轮 stream;
  • 共识(consensus=true):run 已自动收口,如需再问请新开一次 qa/init;
  • 客户端中断流不影响服务端继续执行(消息仍会落库,可从历史接口补读)。

错误:404 会话不存在;409 会话已收口(需重新 init)或 thread_ids 缺失(重新 init)。

3.3 应用调整方向(可选)

问答结束后,若用户确认「把本次调整应用到后续执行」,调用本接口把结论沉淀为 执行方向备注——该备注会注入此任务后续每次定时执行各智能体的任务上下文。

POST /api/task-analysis/qa/{run_id}/apply-direction

请求体:{"note": "后续执行请重点关注台湾海峡北段动态,风险输出按高/中/低分级。"}

响应 200:{"applied": true, "direction_notes": ["…", "…"]}(全部累计备注)。

3.4 对话历史查询

按运行记录查询完整过程消息(总控 + 各智能体),供会话回放或补读。

GET /api/task-analysis/external/runs/{run_id}/messages?seat=&limit=500
  • seat 可选:传智能体 agent_id 只看该席位;传 __coordinator__ 只看总控;不传看全部。
  • 响应:{"run": {"id", "trigger", "status", "started_at", "finished_at"}, "messages": […]}
  • 消息字段:seq(顺序)、seat_agent_id、stage_index、event_type (input 输入 / llm.ai 智能体输出 / artifact 产物备注)、content。

4. 定时数据交付(任务 6 块数据)

按任务展示 6 块结构化数据(相当于 6 个页面分区,每块含多个部分),每块一个 JSON 对象。DeerFlow 只负责数据管道与调度:智能体在定时执行过程中把成果提交进 数据块,归配智能体 / 业务链的配置由管理方维护。

口径要点:

  • 块 key 定死 block_1block_6,标题默认「数据块一六」,可经 4.4 修改; 存量 5 块任务在读接口 / 首次提交时懒补 block_6,已改过的标题不覆盖;
  • payload 不做 schema 校验(结构会变),只要求是 JSON 对象;
  • 不定席位↔块映射:多个智能体可各写一个块的不同部分,一个智能体也可写多个块;
  • 同一块多次提交按「顶层 key 合并、同 key 后写覆盖」合并——某个部分一提交, 立刻体现在任务的当前数据里(实时更新);
  • 不挂时间轴:一个任务的数据只有一份「当前状态」,所有提交(定时轮次、 手动触发、对话修复)都合并进它,越提交越新;
  • 调度不管上一轮跑没跑完:到期照常触发,同任务允许多轮并行,不跳过不顺延; 多轮提交按流水顺序收敛到同一份数据;
  • 首次提交时若任务还没有数据承载记录,自动创建一条(trigger=external), 保证写入永远成功。

4.1 数据块定义列表

GET /api/task-analysis/external/tasks/{source_task_id}/blocks

响应 200:

{
  "task": {"task_id": "ta-TS-2026-0147", "source_task_id": "TS-2026-0147", "name": "东南亚舆论环境监测"},
  "blocks": [
    {"block_key": "block_1", "title": "数据块一", "sort_order": 1},
    {"block_key": "block_2", "title": "数据块二", "sort_order": 2},
    {"block_key": "block_3", "title": "舆情热点", "sort_order": 3},
    {"block_key": "block_4", "title": "数据块四", "sort_order": 4},
    {"block_key": "block_5", "title": "数据块五", "sort_order": 5},
    {"block_key": "block_6", "title": "数据块六", "sort_order": 6}
  ]
}

固定 6 条,按 sort_order 升序返回;title 为修改后的标题(见 4.4)。

4.2 当前数据状态(兼容旧路径 periods)

GET /api/task-analysis/external/tasks/{source_task_id}/periods

时间轴已去掉:任务的数据只有一份当前状态,本接口固定返回唯一一条当前数据 承载记录(periods 数组长度恒为 1,is_current 恒为 true),供消费方感知 数据更新时间。响应 200:

{
  "task": {"task_id": "…", "source_task_id": "…", "name": "…"},
  "current_period_index": 3,
  "total": 1,
  "periods": [
    {
      "period_index": 3,
      "opened_at": "2026-09-14T15:00:00+08:00",
      "trigger": "cron",
      "run_id": "tar-…",
      "is_current": true,
      "blocks": {
        "block_1": {"updated_at": "2026-09-14T15:03:12+08:00"},
        "block_2": {"updated_at": null},
        "block_3": {"updated_at": null},
        "block_4": {"updated_at": null},
        "block_5": {"updated_at": null},
        "block_6": {"updated_at": null}
      }
    }
  ]
}
  • 各块 updated_at 为 null 表示该块尚无数据;
  • 首条承载记录由首次数据提交自动创建(trigger=external);存量任务沿用 历史期号(period_index 数值仅作标识,无时间轴含义)。

4.3 单期数据详情

GET /api/task-analysis/external/tasks/{source_task_id}/periods/{period}

{period} 传期号数字(如 2)或 latest(当前最新一期)。响应 200:

{
  "task": {"task_id": "…", "source_task_id": "…", "name": "…"},
  "period": {
    "period_index": 2,
    "opened_at": "2026-09-14T12:00:00+08:00",
    "trigger": "cron",
    "run_id": "tar-…",
    "is_current": false
  },
  "blocks": [
    {
      "block_key": "block_1",
      "title": "数据块一",
      "sort_order": 1,
      "payload": {"热点列表": ["…"], "统计": {"提及量": 128}},
      "updated_at": "2026-09-14T12:04:55+08:00"
    },
    {"block_key": "block_2", "title": "数据块二", "sort_order": 2, "payload": null, "updated_at": null}
  ]
}
  • blocks 固定 6 条、按 sort_order 升序;尚未提交的块 payload / updated_at 为 null;
  • payload 即该块的合并结果(多次提交按顶层 key 合并、同 key 后写覆盖), 结构由智能体产出决定,请按 JSON 对象渲染;
  • {period} 推荐传 latest(当前数据);传数字期号可访问存量任务的历史 遗留数据(时间轴去掉前的旧期,仅供排查)。

错误:404 —— 期不存在;400 —— period 既不是数字也不是 latest。

4.4 修改块标题 / 排序(管理端)

块标题支持后续修改(页面 + API)。{task_id} 为 DeerFlow 内部任务 id(创建 接口响应里保存的那个)。

PUT /api/task-analysis/tasks/{task_id}/blocks

请求体(只传要改的块;块集合固定 6 条,不能增删):

{
  "blocks": [
    {"block_key": "block_3", "title": "舆情热点"},
    {"block_key": "block_1", "sort_order": 9}
  ]
}

响应 200:{"blocks": […]}(修改后的完整定义列表,形状同 4.1)。 错误:400 —— block_key 不在 block_1~block_6 内。

4.5 演示数据(已预存)

开发环境已预存一个演示任务,可直接用于联调:

  • 任务号 source_task_id = BUSINESS-OVERVIEW-DEMO;block_1 标题「商业态势总览」;
  • 预存时按 13 期小时刻度写入(时间轴去掉前的演示口径);当前对外仅暴露最新一期 的 block_1 payload = 页面整卡数据(pageTitle / briefs / objectives / events / businessNarratives / insights / chart / snapshotName 等, 与页面 mock 快照同构);block_2~block_6 暂无数据;
  • 预存脚本:scripts/seed_business_overview_demo.py(可重复运行,幂等重建)。

4.6 智能体数据提交(内部,供参考)

智能体侧由内置技能 task-data-submit(skills/public/task-data-submit/)调以下 接口完成入库,对方系统无需调用,此处仅供联调排查参考:

POST /api/task-analysis/data/submit

请求体:{"task_id": "<source_task_id>", "block_key": "block_2", "data": {…JSON 对象…}}。 响应 200:{"source_task_id", "task_id", "block_key", "period_index", "updated_at", "keys"}。 错误:400 —— 块 key 非法 / payload 不是对象;404 —— 任务不存在;422 —— 请求体不是合法 JSON 对象。

5. 典型对接流程

对方系统创建任务
  └─ POST /external/tasks ──► 保存 task_id(+ default_chain_id)
        │
        │   (DeerFlow 管理页配置:选业务链 + 执行频率 —— 无需开发)
        ▼
按 cron 自动执行(多轮并行,产出时间线版本)
  ├─ 详情页定期/手动 GET /external/tasks/{source_task_id}/detail ──► 渲染 blocks
  └─ 数据交付(任务 6 块 JSON,见第 4 章)
       ├─ GET /external/tasks/{source_task_id}/periods ──► 当前数据状态(兼容路径)
       └─ GET /external/tasks/{source_task_id}/periods/latest ──► 6 块完整 JSON
        │
        ▼
详情页问答(可选)
  ├─ POST /tasks/{task_id}/qa/init ──► 保存 run_id + thread_ids
  ├─ POST /tasks/{task_id}/qa/stream(每轮,SSE 渲染对话与席位交付)
  ├─ (可选)POST /qa/{run_id}/apply-direction ──► 调整注入后续执行
  └─ GET /external/runs/{run_id}/messages ──► 历史回放

对方系统删除任务
  └─ DELETE /external/tasks/{source_task_id} ──► DeerFlow 侧级联清除

6. 错误码汇总

状态 场景
400 任务未绑定分析方案 / 链无席位 / 请求参数非法 / 数据块 key 非法
401 未带 token 或 token 失效
404 任务 / 会话 / 运行记录 / 期不存在
409 source_task_id 重复创建;会话已收口或线程映射缺失;执行被跳过(业务链已删除/停用)