430 lines
17 KiB
Markdown
430 lines
17 KiB
Markdown
# 任务分析定时 · 对外接口对接文档
|
||
|
||
> 面向外部任务系统(下称「对方系统」)的开发者。覆盖任务接入、时间线详情拉取、
|
||
> 总控问答、**定时数据交付**(任务 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
|
||
```
|
||
|
||
请求体:
|
||
|
||
```json
|
||
{
|
||
"source_task_id": "TS-2026-0147",
|
||
"name": "东南亚舆论环境监测",
|
||
"description": "持续跟踪东南亚重点渠道舆论动向,输出结构化分析详情。"
|
||
}
|
||
```
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| source_task_id | string(≤128) | 是 | 对方任务号,全局唯一 |
|
||
| name | string(≤512) | 是 | 任务名称 |
|
||
| description | string(≤8192) | 否 | 任务简介。**定时执行时注入各智能体的任务上下文以此为准**(存量快照,执行时不会回拉) |
|
||
|
||
响应 `200`:
|
||
|
||
```json
|
||
{
|
||
"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`:
|
||
|
||
```json
|
||
{
|
||
"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`:
|
||
|
||
```json
|
||
{
|
||
"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
|
||
```
|
||
|
||
请求体:
|
||
|
||
```json
|
||
{
|
||
"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_1`~`block_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`:
|
||
|
||
```json
|
||
{
|
||
"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`:
|
||
|
||
```json
|
||
{
|
||
"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`:
|
||
|
||
```json
|
||
{
|
||
"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 条,不能增删):
|
||
|
||
```json
|
||
{
|
||
"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` 重复创建;会话已收口或线程映射缺失;执行被跳过(业务链已删除/停用) |
|