30 KiB
Harness Chat 接口文档
POST /harness/chat
1. 接口说明
- 路径:
/harness/chat - 方法:
POST - 内容类型:
application/json - 返回类型:
Flux<AgentEvent>(流式响应,支持 SSE 与 JSON 数组两种方式) - 功能:向智能体发送一条用户输入,返回一段细粒度智能体事件流。调用方按事件类型逐条解析即可渲染「思考中 / 正在调用工具 / 流式输出答案 / 需要人工确认」等 UI 状态。
源码位置:
mis-common/mis-common-harness/java/com/lcfc/harness/chat/HarnessChatGateway.java#L18-L23@PostMapping("/chat") public Flux<AgentEvent> chat(@RequestBody AgentChatRequest request) { ChatUiChannel channel = HarnessAgent.builder().build().channel(ChatUiChannel.create()); SendOptions sendOptions = SendOptions.of(request.getUserId(), request.getSessionId()); return channel.sendStream(sendOptions, request.getInput()); }
2. 请求
2.1 请求头
| Header | 值 | 说明 |
|---|---|---|
Content-Type |
application/json |
必填 |
Accept |
text/event-stream 或 application/json |
决定响应格式(见 §3) |
2.2 请求体(AgentChatRequest)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
sessionId |
String | ✅ | 会话 ID;同一用户不同会话相互隔离 |
userId |
String | ✅ | 用户 ID;用于智能体命名空间隔离 / 会话路由 |
input |
String | ✅ | 用户输入内容 |
chatModel |
Object | ❌ | 聊天模型配置(name、stream、temperature) |
chatModel 结构:
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
name |
String | - | 模型名称,如 gpt-oss-120b |
stream |
Boolean | true |
是否流式 |
temperature |
Double | 0.2 |
温度 |
2.3 请求示例
POST /harness/chat
Host: localhost:8080
Content-Type: application/json
Accept: text/event-stream
{
"sessionId": "sess-20260918-001",
"userId": "user-10001",
"input": "帮我梳理今天的任务清单,生成一份 markdown 并保存到工作区",
"chatModel": {
"name": "gpt-oss-120b",
"stream": true,
"temperature": 0.2
}
}
⚠️ 注意:当前实现中
chatModel并未被使用(HarnessAgent.builder().build()未传入模型配置)。如需按请求指定模型,需要扩展HarnessChatGateway。
3. 响应
3.1 格式一:SSE(推荐,Accept: text/event-stream)
每发生一个事件,服务端推送一条 data:,事件之间以空行分隔:
data:{"type":"AGENT_START","id":"4f9c1e2d8a7b4c5d9e0f1a2b3c4d5e6f","createdAt":"2026-09-18T02:30:45.123456Z","sessionId":"sess-20260918-001","replyId":"reply-7f3a91","name":"assistant","role":"assistant"}
data:{"type":"THINKING_BLOCK_START","id":"...","createdAt":"...","replyId":"reply-7f3a91","blockId":"blk-001"}
data:{"type":"TEXT_BLOCK_DELTA","id":"...","createdAt":"...","replyId":"reply-7f3a91","blockId":"blk-002","delta":"已完成"}
3.2 格式二:JSON 数组(默认 / Accept: application/json)
整个事件流序列化为一个 JSON 数组,随事件产生逐个写出:
[
{ "type": "AGENT_START", "...": "..." },
{ "type": "THINKING_BLOCK_START", "...": "..." },
{ "type": "TEXT_BLOCK_DELTA", "...": "..." }
]
3.3 HTTP 状态
| 状态码 | 说明 |
|---|---|
200 |
正常,返回事件流 |
400 |
校验失败(sessionId / userId / input 为空时抛 400 Bad Request) |
500 |
智能体执行异常(模型未配置、会话中断等) |
4. 事件通用结构
所有事件(AgentEvent)都包含以下通用字段,通过 type 字段区分具体事件类型:
| 字段 | 类型 | 说明 |
|---|---|---|
type |
String | 类型判别器,取值见 §5 |
id |
String | 事件唯一 ID(32 位十六进制,无连字符 UUID) |
createdAt |
String | 事件创建时间,ISO-8601 格式(如 2026-09-18T02:30:45.123456Z) |
source |
String | 事件来源路径。顶层智能体事件为 null;子智能体转发的事件为 main/researcher 形式。无值时缺省(不输出) |
metadata |
Object | 附加元数据,空时不输出 |
仅 type / id / createdAt 必现;其余字段视事件类型而定。以下各事件示例均基于同一会话回环 "replyId":"reply-7f3a91"。
5. AgentEvent 类型详解与数据示例
5.1 AGENT_START — 智能体开始处理
表示一次智能体调用开始。
| 字段 | 类型 | 说明 |
|---|---|---|
sessionId |
String | 会话 ID |
replyId |
String | 本轮回复 ID,用于关联同一轮事件 |
name |
String | 智能体名称 |
role |
String | 默认 "assistant" |
{
"type": "AGENT_START",
"id": "4f9c1e2d8a7b4c5d9e0f1a2b3c4d5e6f",
"createdAt": "2026-09-18T02:30:45.123456Z",
"sessionId": "sess-20260918-001",
"replyId": "reply-7f3a91",
"name": "assistant",
"role": "assistant"
}
5.2 THINKING_BLOCK_START — 思考块开始
模型开始推理(ReAct 的 reasoning 阶段)。
| 字段 | 类型 | 说明 |
|---|---|---|
replyId |
String | 回复 ID |
blockId |
String | 思考块 ID |
{
"type": "THINKING_BLOCK_START",
"id": "1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d",
"createdAt": "2026-09-18T02:30:45.200000Z",
"replyId": "reply-7f3a91",
"blockId": "blk-001"
}
5.3 THINKING_BLOCK_DELTA — 思考内容增量
逐段推送思考内容。
| 字段 | 类型 | 说明 |
|---|---|---|
replyId |
String | 回复 ID |
blockId |
String | 思考块 ID |
delta |
String | 增量文本 |
{
"type": "THINKING_BLOCK_DELTA",
"id": "2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e",
"createdAt": "2026-09-18T02:30:45.210000Z",
"replyId": "reply-7f3a91",
"blockId": "blk-001",
"delta": "用户希望将任务清单整理成 markdown 文件并保存,需要先规划目录结构。"
}
5.4 THINKING_BLOCK_END — 思考块结束
{
"type": "THINKING_BLOCK_END",
"id": "3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f",
"createdAt": "2026-09-18T02:30:45.350000Z",
"replyId": "reply-7f3a91",
"blockId": "blk-001"
}
5.5 MODEL_CALL_START — 模型调用开始
| 字段 | 类型 | 说明 |
|---|---|---|
replyId |
String | 回复 ID |
{
"type": "MODEL_CALL_START",
"id": "4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f90",
"createdAt": "2026-09-18T02:30:45.180000Z",
"replyId": "reply-7f3a91"
}
5.6 MODEL_CALL_END — 模型调用结束(含 token 用量)
| 字段 | 类型 | 说明 |
|---|---|---|
replyId |
String | 回复 ID |
usage |
Object | token 用量统计 |
usage 结构:
{
"type": "MODEL_CALL_END",
"id": "5e6f7a8b9c0d1e2f3a4b5c6d7e8f9001",
"createdAt": "2026-09-18T02:30:45.680000Z",
"replyId": "reply-7f3a91",
"usage": {
"inputTokens": 1250,
"outputTokens": 320,
"cachedTokens": 512,
"time": 0.482,
"totalTokens": 1570
}
}
| usage 字段 | 类型 | 说明 |
|---|---|---|
inputTokens |
Integer | 输入 token 数(含缓存部分) |
outputTokens |
Integer | 输出 token 数 |
cachedTokens |
Integer | 命中 prompt 缓存的输入 token 数(来自 inputTokens 的子集) |
time |
Number | 本次调用耗时(秒) |
totalTokens |
Integer | inputTokens + outputTokens(派生字段) |
5.7 TOOL_CALL_START — 工具调用开始
模型决定调用某个工具(ReAct 的 acting 阶段)。
| 字段 | 类型 | 说明 |
|---|---|---|
replyId |
String | 回复 ID |
toolCallId |
String | 工具调用 ID |
toolCallName |
String | 工具名 |
{
"type": "TOOL_CALL_START",
"id": "6f7a8b9c0d1e2f3a4b5c6d7e8f900112",
"createdAt": "2026-09-18T02:30:45.700000Z",
"replyId": "reply-7f3a91",
"toolCallId": "call_9f2c4d",
"toolCallName": "shell_execute"
}
5.8 TOOL_CALL_DELTA — 工具入参流式增量
工具参数以 JSON 字符串形式分片送达。
| 字段 | 类型 | 说明 |
|---|---|---|
replyId |
String | 回复 ID |
toolCallId |
String | 工具调用 ID |
toolCallName |
String | 工具名 |
delta |
String | 入参 JSON 片段 |
{
"type": "TOOL_CALL_DELTA",
"id": "7a8b9c0d1e2f3a4b5c6d7e8f90011223",
"createdAt": "2026-09-18T02:30:45.720000Z",
"replyId": "reply-7f3a91",
"toolCallId": "call_9f2c4d",
"toolCallName": "shell_execute",
"delta": "{\"command\":\"cat /tasks.json > "
}
{
"type": "TOOL_CALL_DELTA",
"id": "8b9c0d1e2f3a4b5c6d7e8f9001122334",
"createdAt": "2026-09-18T02:30:45.730000Z",
"replyId": "reply-7f3a91",
"toolCallId": "call_9f2c4d",
"toolCallName": "shell_execute",
"delta": "\\\"/workspace/tasks.md\"}"
}
5.9 TOOL_CALL_END — 工具调用结束
{
"type": "TOOL_CALL_END",
"id": "9c0d1e2f3a4b5c6d7e8f900112233445",
"createdAt": "2026-09-18T02:30:45.740000Z",
"replyId": "reply-7f3a91",
"toolCallId": "call_9f2c4d",
"toolCallName": "shell_execute"
}
5.10 TOOL_RESULT_START — 工具执行结果开始
| 字段 | 类型 | 说明 |
|---|---|---|
replyId |
String | 回复 ID |
toolCallId |
String | 工具调用 ID |
toolCallName |
String | 工具名 |
metadata |
Object | 可选,如携带 taskId 等转发元数据(缺省) |
{
"type": "TOOL_RESULT_START",
"id": "0d1e2f3a4b5c6d7e8f90011223344556",
"createdAt": "2026-09-18T02:30:46.050000Z",
"replyId": "reply-7f3a91",
"toolCallId": "call_9f2c4d",
"toolCallName": "shell_execute"
}
5.11 TOOL_RESULT_TEXT_DELTA — 工具结果文本增量
| 字段 | 类型 | 说明 |
|---|---|---|
replyId |
String | 回复 ID |
toolCallId |
String | 工具调用 ID |
toolCallName |
String | 工具名 |
delta |
String | 结果文本片段 |
{
"type": "TOOL_RESULT_TEXT_DELTA",
"id": "1e2f3a4b5c6d7e8f9001122334455667",
"createdAt": "2026-09-18T02:30:46.060000Z",
"replyId": "reply-7f3a91",
"toolCallId": "call_9f2c4d",
"toolCallName": "shell_execute",
"delta": "exit_code=0\n"
}
{
"type": "TOOL_RESULT_TEXT_DELTA",
"id": "2f3a4b5c6d7e8f9001122334455667788",
"createdAt": "2026-09-18T02:30:46.070000Z",
"replyId": "reply-7f3a91",
"toolCallId": "call_9f2c4d",
"toolCallName": "shell_execute",
"delta": "任务清单已保存到 /workspace/tasks.md"
}
5.12 TOOL_RESULT_DATA_DELTA — 工具结果二进制数据增量
| 字段 | 类型 | 说明 |
|---|---|---|
replyId |
String | 回复 ID |
toolCallId |
String | 工具调用 ID |
toolCallName |
String | 工具名 |
data |
Object | 一个多态 ContentBlock(type 判别器),常见为 data 类型携带 base64 数据 |
data 的 type 取值:text / thinking / image / audio / video / tool_use / tool_result / hint / data。
{
"type": "TOOL_RESULT_DATA_DELTA",
"id": "3a4b5c6d7e8f900112233445566778899",
"createdAt": "2026-09-18T02:30:46.080000Z",
"replyId": "reply-7f3a91",
"toolCallId": "call_9f2c4d",
"toolCallName": "render_chart",
"data": {
"type": "data",
"source": {
"type": "base64",
"media_type": "image/png",
"data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="
},
"id": "d4a3b2c1d5e6f7a8b9c0d1e2f3a4b5c6",
"name": "chart.png"
}
}
URL 型数据源示例:
"source": { "type": "url", "url": "https://cdn.example.com/tmp/chart.png", "mime_type": "image/png" }
5.13 TOOL_RESULT_END — 工具结果结束(含执行状态)
| 字段 | 类型 | 说明 |
|---|---|---|
replyId |
String | 回复 ID |
toolCallId |
String | 工具调用 ID |
toolCallName |
String | 工具名 |
state |
String | 执行结果:success / error / interrupted / denied / running |
{
"type": "TOOL_RESULT_END",
"id": "4b5c6d7e8f90011223344556677889900",
"createdAt": "2026-09-18T02:30:46.150000Z",
"replyId": "reply-7f3a91",
"toolCallId": "call_9f2c4d",
"toolCallName": "shell_execute",
"state": "success"
}
失败示例(state = error):
{
"type": "TOOL_RESULT_END",
"id": "5c6d7e8f9001122334455667788990011",
"createdAt": "2026-09-18T02:30:47.200000Z",
"replyId": "reply-7f3a91",
"toolCallId": "call_9f2c4d",
"toolCallName": "shell_execute",
"state": "error"
}
5.14 DATA_BLOCK_START — 二进制数据块开始
用于向用户直接推送二进制内容(图片 / 音频 / 视频 / 文件),通常出现在最终答案阶段。
| 字段 | 类型 | 说明 |
|---|---|---|
replyId |
String | 回复 ID |
blockId |
String | 数据块 ID |
{
"type": "DATA_BLOCK_START",
"id": "6d7e8f900112233445566778899001122",
"createdAt": "2026-09-18T02:30:48.000000Z",
"replyId": "reply-7f3a91",
"blockId": "blk-003"
}
5.15 DATA_BLOCK_DELTA — 二进制数据块增量
delta 为二进制内容的 base64 分片。
| 字段 | 类型 | 说明 |
|---|---|---|
replyId |
String | 回复 ID |
blockId |
String | 数据块 ID |
delta |
String | base64 数据分片 |
{
"type": "DATA_BLOCK_DELTA",
"id": "7e8f90011223344556677889900112233",
"createdAt": "2026-09-18T02:30:48.010000Z",
"replyId": "reply-7f3a91",
"blockId": "blk-003",
"delta": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="
}
5.16 DATA_BLOCK_END — 二进制数据块结束
{
"type": "DATA_BLOCK_END",
"id": "8f9001122334455667788990011223344",
"createdAt": "2026-09-18T02:30:48.100000Z",
"replyId": "reply-7f3a91",
"blockId": "blk-003"
}
5.17 TEXT_BLOCK_START — 文本块开始
{
"type": "TEXT_BLOCK_START",
"id": "900112233445566778899001122334455",
"createdAt": "2026-09-18T02:30:47.500000Z",
"replyId": "reply-7f3a91",
"blockId": "blk-002"
}
5.18 TEXT_BLOCK_DELTA — 文本块流式增量(最终答案)
前端据此逐字渲染智能体回复。
| 字段 | 类型 | 说明 |
|---|---|---|
replyId |
String | 回复 ID |
blockId |
String | 文本块 ID |
delta |
String | 文本增量 |
{
"type": "TEXT_BLOCK_DELTA",
"id": "a011223344556677889900112233445566",
"createdAt": "2026-09-18T02:30:47.510000Z",
"replyId": "reply-7f3a91",
"blockId": "blk-002",
"delta": "已完成,"
}
{
"type": "TEXT_BLOCK_DELTA",
"id": "b112233445566778899001122334455667",
"createdAt": "2026-09-18T02:30:47.520000Z",
"replyId": "reply-7f3a91",
"blockId": "blk-002",
"delta": "任务清单已保存至 /workspace/tasks.md"
}
5.19 TEXT_BLOCK_END — 文本块结束
{
"type": "TEXT_BLOCK_END",
"id": "c223344556677889900112233445566778",
"createdAt": "2026-09-18T02:30:47.600000Z",
"replyId": "reply-7f3a91",
"blockId": "blk-002"
}
5.20 AGENT_RESULT — 智能体最终结果(含完整 Msg)
在 AGENT_END 之前发出,携带本轮最终回复消息 Msg。调用方可以从事件流直接取结果,无需另外订阅返回值。
| 字段 | 类型 | 说明 |
|---|---|---|
result |
Object | 最终消息体(多态,role 为判别器:USER / ASSISTANT / SYSTEM / TOOL) |
result(Msg)字段:
| 字段 | 类型 | 说明 |
|---|---|---|
id |
String | 消息 ID(UUID) |
name |
String | 消息发送方名称,可为 null |
role |
String | 角色:USER / ASSISTANT / SYSTEM / TOOL |
content |
Array | 内容块数组(多态,type 判别器) |
metadata |
Object | 元数据,如 agentscope_generate_reason |
timestamp |
String | 消息时间戳,格式 yyyy-MM-dd HH:mm:ss.SSS |
usage |
Object | token 用量(同 §5.6),可为 null |
{
"type": "AGENT_RESULT",
"id": "d33445566778899001122334455667788",
"createdAt": "2026-09-18T02:30:48.200000Z",
"result": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "assistant",
"role": "ASSISTANT",
"content": [
{
"type": "text",
"text": "已完成,任务清单已保存至 /workspace/tasks.md"
}
],
"metadata": {
"agentscope_generate_reason": "MODEL_STOP"
},
"timestamp": "2026-09-18 10:30:48.200",
"usage": {
"inputTokens": 1250,
"outputTokens": 320,
"cachedTokens": 512,
"time": 2.46,
"totalTokens": 1570
}
}
}
多模态回复的
content举例(图片 + 文本混排):"content": [ { "type": "text", "text": "这是生成的图表:" }, { "type": "data", "source": { "type": "url", "url": "https://cdn.example.com/chart.png", "mime_type": "image/png" }, "id": "d4a3b2c1d5e6f7a8b9c0d1e2f3a4b5c6", "name": "chart.png" } ]
5.21 AGENT_END — 智能体结束处理
{
"type": "AGENT_END",
"id": "e455667788990011223344556677889900",
"createdAt": "2026-09-18T02:30:48.300000Z",
"replyId": "reply-7f3a91"
}
5.22 EXCEED_MAX_ITERS — ReAct 循环超过最大迭代次数
| 字段 | 类型 | 说明 |
|---|---|---|
replyId |
String | 回复 ID |
maxIters |
Integer | 配置的最大迭代次数 |
currentIter |
Integer | 实际到达的迭代次数 |
{
"type": "EXCEED_MAX_ITERS",
"id": "f566778899001122334455667788990011",
"createdAt": "2026-09-18T02:30:52.000000Z",
"replyId": "reply-7f3a91",
"maxIters": 10,
"currentIter": 10
}
5.23 REQUIRE_USER_CONFIRM — 需要用户确认工具调用(HITL 暂停)
智能体在执行敏感工具前暂停,等待用户逐条确认(前端应弹出授权窗口)。工具调用状态为 asking。
| 字段 | 类型 | 说明 |
|---|---|---|
replyId |
String | 回复 ID |
toolCalls |
Array | 待确认的 ToolUseBlock 列表 |
ToolUseBlock 字段:id、name、input(Map)、content(流式原始内容,可空)、metadata、state(pending / asking / allowed / submitted / finished)。
{
"type": "REQUIRE_USER_CONFIRM",
"id": "6778899001122334455667788990011223",
"createdAt": "2026-09-18T02:30:45.750000Z",
"replyId": "reply-7f3a91",
"toolCalls": [
{
"id": "call_9f2c4d",
"name": "shell_execute",
"input": {
"command": "rm -rf /workspace/old/"
},
"content": null,
"metadata": {},
"state": "asking"
},
{
"id": "call_5a1b02",
"name": "http_post",
"input": {
"url": "https://api.example.com/orders",
"body": "{\"id\": 10086}"
},
"content": null,
"metadata": {},
"state": "asking"
}
]
}
5.24 USER_CONFIRM_RESULT — 用户确认结果回传
用户对 REQUIRE_USER_CONFIRM 的响应结果(同一会话的下一轮调用事件流中可能出现)。
| 字段 | 类型 | 说明 |
|---|---|---|
replyId |
String | 回复 ID |
confirmResults |
Array | ConfirmResult 列表 |
ConfirmResult 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
confirmed |
Boolean | 是否批准 |
toolCall |
Object | 对应的 ToolUseBlock(用户可修改入参) |
rules |
Array | 用户新增的权限规则(允许后续免确认),可为空 |
{
"type": "USER_CONFIRM_RESULT",
"id": "7889900112233445566778899001122334",
"createdAt": "2026-09-18T02:31:05.000000Z",
"replyId": "reply-7f3a91",
"confirmResults": [
{
"confirmed": true,
"toolCall": {
"id": "call_9f2c4d",
"name": "shell_execute",
"input": {
"command": "rm -rf /workspace/old/"
},
"content": null,
"metadata": {},
"state": "asking"
},
"rules": [
{
"tool_name": "shell_execute",
"rule_content": "rm -rf /workspace/*",
"behavior": "allow",
"source": "userSettings"
}
]
},
{
"confirmed": false,
"toolCall": {
"id": "call_5a1b02",
"name": "http_post",
"input": {
"url": "https://api.example.com/orders",
"body": "{\"id\": 10086}"
},
"content": null,
"metadata": {},
"state": "asking"
},
"rules": null
}
]
}
5.25 ALL_TOOLS_DENIED — 本轮所有工具均被拒绝
| 字段 | 类型 | 说明 |
|---|---|---|
deniedToolCalls |
Array | 被拒绝的 ToolUseBlock 列表 |
{
"type": "ALL_TOOLS_DENIED",
"id": "89900112233445566778899001122334455",
"createdAt": "2026-09-18T02:31:05.100000Z",
"deniedToolCalls": [
{
"id": "call_5a1b02",
"name": "http_post",
"input": {
"url": "https://api.example.com/orders",
"body": "{\"id\": 10086}"
},
"content": null,
"metadata": {},
"state": "asking"
}
]
}
5.26 REQUIRE_EXTERNAL_EXECUTION — 需要外部(进程外)执行工具
工具需由调用方在进程外执行,智能体暂停等待结果。
| 字段 | 类型 | 说明 |
|---|---|---|
replyId |
String | 回复 ID |
toolCalls |
Array | 待外部执行的 ToolUseBlock 列表 |
{
"type": "REQUIRE_EXTERNAL_EXECUTION",
"id": "9001122334455667788990011223344556",
"createdAt": "2026-09-18T02:30:45.900000Z",
"replyId": "reply-7f3a91",
"toolCalls": [
{
"id": "call_0f3e9a",
"name": "human_approval_flow",
"input": {
"title": "发布订单 10086 到生产环境"
},
"content": null,
"metadata": {},
"state": "pending"
}
]
}
5.27 EXTERNAL_EXECUTION_RESULT — 外部执行结果回传
| 字段 | 类型 | 说明 |
|---|---|---|
replyId |
String | 回复 ID |
toolResults |
Array | ToolResultBlock 列表 |
ToolResultBlock 字段:id、name、output(ContentBlock 数组)、metadata、state(success / error / interrupted / denied / running)。
{
"type": "EXTERNAL_EXECUTION_RESULT",
"id": "a112233445566778899001122334455667",
"createdAt": "2026-09-18T02:31:20.000000Z",
"replyId": "reply-7f3a91",
"toolResults": [
{
"id": "call_0f3e9a",
"name": "human_approval_flow",
"output": [
{
"type": "text",
"text": "审批人张三已批准,订单 10086 已发布。"
}
],
"metadata": {},
"state": "success"
}
]
}
5.28 REQUEST_STOP — 请求暂停执行
中间件 / 权限引擎要求智能体在当前步骤结束后暂停(如预算超限、合规审查点)。调用方可在下一轮使用相同 sessionId 继续该会话,待执行的工具调用会自动恢复。
| 字段 | 类型 | 说明 |
|---|---|---|
reason |
String | 停止原因(人类可读) |
generateReason |
String | 停止原因枚举名:MODEL_STOP / TOOL_CALLS / STRUCTURED_OUTPUT / TOOL_SUSPENDED / REASONING_STOP_REQUESTED / ACTING_STOP_REQUESTED / PERMISSION_ASKING / MIDDLEWARE_STOP_REQUESTED / ALL_TOOLS_DENIED / INTERRUPTED / MAX_ITERATIONS,默认 MIDDLEWARE_STOP_REQUESTED |
{
"type": "REQUEST_STOP",
"id": "b223344556677889900112233445566778",
"createdAt": "2026-09-18T02:30:49.000000Z",
"reason": "单轮 token 消耗超过预算上限 100K,已暂停"
}
{
"type": "REQUEST_STOP",
"id": "c334455667788990011223344556677889",
"createdAt": "2026-09-18T02:30:49.100000Z",
"reason": "权限引擎要求用户确认高风险操作",
"generateReason": "PERMISSION_ASKING"
}
5.29 SUBAGENT_EXPOSED — 子智能体对外暴露
通过 agent_spawn(expose_to_user=true) 生成的子智能体成为可寻址的独立会话入口,SSE 消费端据此在 UI 渲染新的会话卡片。
| 字段 | 类型 | 说明 |
|---|---|---|
subagentId |
String | 子智能体实例 ID |
agentId |
String | 子智能体定义 ID |
sessionId |
String | 子智能体会话 ID |
label |
String | 展示名称 |
{
"type": "SUBAGENT_EXPOSED",
"id": "d445566778899001122334455667788990",
"createdAt": "2026-09-18T02:31:02.000000Z",
"subagentId": "sub-0a1b2c3d",
"agentId": "data-analyst",
"sessionId": "sess-sub-88",
"label": "数据分析助手"
}
5.30 HINT_BLOCK — 一次性提示块
一次性完整下发(不流式),用途包括团队消息、后台工具结果、用户打断等。
| 字段 | 类型 | 说明 |
|---|---|---|
replyId |
String | 回复 ID |
blockId |
String | 提示块 ID |
hintSource |
String | 来源(团队消息发送者姓名、system 或 null) |
hint |
String | 完整提示内容 |
{
"type": "HINT_BLOCK",
"id": "e556677889900112233445566778899001",
"createdAt": "2026-09-18T02:31:03.000000Z",
"replyId": "reply-7f3a91",
"blockId": "blk-hint-01",
"hintSource": "alice",
"hint": "alice 加入了会话,可以开始协作。"
}
5.31 CUSTOM — 自定义扩展事件
业务中间件用于推送自有状态(未知 name 前端应跳过不报错)。约定 name:state_updated(任务/权限状态变化)、team_updated(团队变更)等。
| 字段 | 类型 | 说明 |
|---|---|---|
name |
String | 事件名 |
value |
Object | 任意 JSON 负载 |
{
"type": "CUSTOM",
"id": "f667788990011223344556677889900112",
"createdAt": "2026-09-18T02:31:04.000000Z",
"name": "task_progress",
"value": {
"taskId": "task-201",
"progress": 66,
"status": "RUNNING",
"detail": "正在生成页面截图"
}
}
{
"type": "CUSTOM",
"id": "a778899001122334455667788990011223",
"createdAt": "2026-09-18T02:31:04.500000Z",
"name": "team_updated",
"value": {
"action": "MEMBER_ADDED",
"member": "bob",
"teamId": "team-007"
}
}
6. 典型一轮完整事件流(SSE,按顺序)
以「用户要求整理任务清单并保存为 markdown」为例(含工具调用):
data:{"type":"AGENT_START","id":"...","createdAt":"...","sessionId":"sess-20260918-001","replyId":"reply-7f3a91","name":"assistant","role":"assistant"}
data:{"type":"MODEL_CALL_START","id":"...","createdAt":"...","replyId":"reply-7f3a91"}
data:{"type":"THINKING_BLOCK_START","id":"...","createdAt":"...","replyId":"reply-7f3a91","blockId":"blk-001"}
data:{"type":"THINKING_BLOCK_DELTA","id":"...","createdAt":"...","replyId":"reply-7f3a91","blockId":"blk-001","delta":"先读取任务源文件,再生成 markdown"}
data:{"type":"THINKING_BLOCK_END","id":"...","createdAt":"...","replyId":"reply-7f3a91","blockId":"blk-001"}
data:{"type":"MODEL_CALL_END","id":"...","createdAt":"...","replyId":"reply-7f3a91","usage":{"inputTokens":520,"outputTokens":80,"cachedTokens":0,"time":0.41,"totalTokens":600}}
data:{"type":"TOOL_CALL_START","id":"...","createdAt":"...","replyId":"reply-7f3a91","toolCallId":"call_9f2c4d","toolCallName":"shell_execute"}
data:{"type":"TOOL_CALL_DELTA","id":"...","createdAt":"...","replyId":"reply-7f3a91","toolCallId":"call_9f2c4d","toolCallName":"shell_execute","delta":"{\"command\":\"cat /tasks.json\"}"}
data:{"type":"TOOL_CALL_END","id":"...","createdAt":"...","replyId":"reply-7f3a91","toolCallId":"call_9f2c4d","toolCallName":"shell_execute"}
data:{"type":"TOOL_RESULT_START","id":"...","createdAt":"...","replyId":"reply-7f3a91","toolCallId":"call_9f2c4d","toolCallName":"shell_execute"}
data:{"type":"TOOL_RESULT_TEXT_DELTA","id":"...","createdAt":"...","replyId":"reply-7f3a91","toolCallId":"call_9f2c4d","toolCallName":"shell_execute","delta":"3 个任务待办..."}
data:{"type":"TOOL_RESULT_END","id":"...","createdAt":"...","replyId":"reply-7f3a91","toolCallId":"call_9f2c4d","toolCallName":"shell_execute","state":"success"}
data:{"type":"MODEL_CALL_START","id":"...","createdAt":"...","replyId":"reply-7f3a91"}
data:{"type":"MODEL_CALL_END","id":"...","createdAt":"...","replyId":"reply-7f3a91","usage":{"inputTokens":1600,"outputTokens":330,"cachedTokens":512,"time":1.8,"totalTokens":1930}}
data:{"type":"TEXT_BLOCK_START","id":"...","createdAt":"...","replyId":"reply-7f3a91","blockId":"blk-002"}
data:{"type":"TEXT_BLOCK_DELTA","id":"...","createdAt":"...","replyId":"reply-7f3a91","blockId":"blk-002","delta":"已完成,"}
data:{"type":"TEXT_BLOCK_DELTA","id":"...","createdAt":"...","replyId":"reply-7f3a91","blockId":"blk-002","delta":"任务清单已保存至 /workspace/tasks.md"}
data:{"type":"TEXT_BLOCK_END","id":"...","createdAt":"...","replyId":"reply-7f3a91","blockId":"blk-002"}
data:{"type":"AGENT_RESULT","id":"...","createdAt":"...","result":{"id":"550e8400-e29b-41d4-a716-446655440000","name":"assistant","role":"ASSISTANT","content":[{"type":"text","text":"已完成,任务清单已保存至 /workspace/tasks.md"}],"metadata":{"agentscope_generate_reason":"MODEL_STOP"},"timestamp":"2026-09-18 10:30:48.200","usage":{"inputTokens":1600,"outputTokens":330,"cachedTokens":512,"time":1.8,"totalTokens":1930}}}
data:{"type":"AGENT_END","id":"...","createdAt":"...","replyId":"reply-7f3a91"}
事件一般顺序:AGENT_START → (MODEL_CALL_* / THINKING_BLOCK_* / TOOL_CALL_* / TOOL_RESULT_* 可能多轮循环) → TEXT_BLOCK_* → AGENT_RESULT → AGENT_END。涉及 HITL 时会插入 REQUIRE_USER_CONFIRM(见 §5.23)。
7. 注意事项
- 延续会话:同一
(userId, sessionId)组合的上下文会自动累积;不同会话互不干扰。REQUEST_STOP或REQUIRE_USER_CONFIRM暂停后,用相同sessionId再发一次请求即可恢复执行。 - 事件 ID:
id为 32 位十六进制(无连字符 UUID),可用于调试与去重;createdAt为 ISO-8601(UTC)。 - 未知事件:前端对
type: CUSTOM中未知的name应静默跳过;对表外未知type应尽量容忍(服务端可能升级新增事件)。 - 空字段省略:顶层事件的
source、metadata及无值字段在 JSON 中缺省(NON_NULL策略);Msg内部字段(如name、usage)则为null或对象。