Compare commits

..

3 Commits

Author SHA1 Message Date
V-LiuShuang eee6640952 add 2026-09-18 10:23:50 +08:00
V-LiuShuang 37ebd8715f Merge branch 'main' of https://git.jkwlstv.cn/doc/tmp 2026-09-16 15:32:40 +08:00
V-LiuShuang 55d8ed8e28 add 2026-09-16 15:32:28 +08:00
2 changed files with 1023 additions and 38 deletions
+993
View File
@@ -0,0 +1,993 @@
# 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`
>
> ```java
> @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 请求示例
```json
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 数组,随事件产生逐个写出:
```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"` |
```json
{
"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 |
```json
{
"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 | 增量文本 |
```json
{
"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 — 思考块结束
```json
{
"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 |
```json
{
"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` 结构:
```json
{
"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 | 工具名 |
```json
{
"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 片段 |
```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 > "
}
```
```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 — 工具调用结束
```json
{
"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` 等转发元数据(缺省) |
```json
{
"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 | 结果文本片段 |
```json
{
"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"
}
```
```json
{
"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`
```json
{
"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` |
```json
{
"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):**
```json
{
"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 |
```json
{
"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 数据分片 |
```json
{
"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 — 二进制数据块结束
```json
{
"type": "DATA_BLOCK_END",
"id": "8f9001122334455667788990011223344",
"createdAt": "2026-09-18T02:30:48.100000Z",
"replyId": "reply-7f3a91",
"blockId": "blk-003"
}
```
### 5.17 TEXT_BLOCK_START — 文本块开始
```json
{
"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 | 文本增量 |
```json
{
"type": "TEXT_BLOCK_DELTA",
"id": "a011223344556677889900112233445566",
"createdAt": "2026-09-18T02:30:47.510000Z",
"replyId": "reply-7f3a91",
"blockId": "blk-002",
"delta": "已完成,"
}
```
```json
{
"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 — 文本块结束
```json
{
"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 | 消息 IDUUID |
| `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` |
```json
{
"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` 举例(图片 + 文本混排):
> ```json
> "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 — 智能体结束处理
```json
{
"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 | 实际到达的迭代次数 |
```json
{
"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`)。
```json
{
"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 | 用户新增的权限规则(允许后续免确认),可为空 |
```json
{
"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` 列表 |
```json
{
"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` 列表 |
```json
{
"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`)。
```json
{
"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` |
```json
{
"type": "REQUEST_STOP",
"id": "b223344556677889900112233445566778",
"createdAt": "2026-09-18T02:30:49.000000Z",
"reason": "单轮 token 消耗超过预算上限 100K,已暂停"
}
```
```json
{
"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 | 展示名称 |
```json
{
"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 | 完整提示内容 |
```json
{
"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 负载 |
```json
{
"type": "CUSTOM",
"id": "f667788990011223344556677889900112",
"createdAt": "2026-09-18T02:31:04.000000Z",
"name": "task_progress",
"value": {
"taskId": "task-201",
"progress": 66,
"status": "RUNNING",
"detail": "正在生成页面截图"
}
}
```
```json
{
"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」为例(含工具调用):
```text
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. 注意事项
1. **延续会话**:同一 `(userId, sessionId)` 组合的上下文会自动累积;不同会话互不干扰。`REQUEST_STOP``REQUIRE_USER_CONFIRM` 暂停后,用相同 `sessionId` 再发一次请求即可恢复执行。
2. **事件 ID**`id` 为 32 位十六进制(无连字符 UUID),可用于调试与去重;`createdAt` 为 ISO-8601UTC)。
3. **未知事件**:前端对 `type: CUSTOM` 中未知的 `name` 应静默跳过;对表外未知 `type` 应尽量容忍(服务端可能升级新增事件)。
4. **空字段省略**:顶层事件的 `source``metadata` 及无值字段在 JSON 中缺省(`NON_NULL` 策略);`Msg` 内部字段(如 `name``usage`)则为 `null` 或对象。
+30 -38
View File
@@ -27,43 +27,35 @@ CREATE TABLE `mis-debugging`.`work_sheet` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='工单表': ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='工单表':
``` ```
## Nacos ## 集成Harness
```yml ### Nacos
agents:
filesystem: 参见`qas`环境的`se-harness-agent.yml`配置文件。
# SESSION/USER/AGENT/GLOBAL
isolationScope: USER ### 新建的表
# 当上下文没有用户ID时使用的默认值
anonymousUserId: "sys_uid" `agentscope-java`源码提取而来。
workspace:
localRootPath: ${user.home}/.se-agent ```sql
shell: false CREATE TABLE IF NOT EXISTS agent_skill (
# https://java.agentscope.io/v2/zh/docs/harness/compaction.md id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
compaction: name VARCHAR(255) NOT NULL UNIQUE,
triggerMessages: 50 description TEXT NOT NULL,
triggerTokens: 0 skill_content LONGTEXT NOT NULL,
reserved: 20000 source VARCHAR(255) NOT NULL,
keepMessages: 20 metadata_json LONGTEXT NULL,
keepTokens: -1 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
keepTokensMin: 2000 updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
keepTokensMax: 8000 ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
keepTokensRatio: 0.25
# 设置为default表示使用默认值 CREATE TABLE IF NOT EXISTS agent_skill_resource (
summaryPrompt: "default" id BIGINT NOT NULL,
flushBeforeCompact: true resource_path VARCHAR(500) NOT NULL,
offloadBeforeCompact: true resource_content LONGTEXT NOT NULL,
prune: created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
protectTokens: 40000 updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
protectTokens: 20000 PRIMARY KEY (id, resource_path),
maxOutputChars: 2000 FOREIGN KEY (id) REFERENCES agent_skill (id) ON DELETE CASCADE
excludedTools: ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
- "read_file"
- "memory_search"
- "memory_get"
- "session_search"
model:
name: "gpt-oss-120b"
stream: true
temperature: 0.2
``` ```