Skip to content

会话生命周期

概览

创建会话 → 建立 WebSocket → 订阅 → 发送消息 → 接收流式响应 → 取消订阅 → 断开

下面以纯 HTTP + Socket.IO 协议描述完整流程,不依赖任何 SDK。


1. 创建会话

POST /api/sessions
Content-Type: application/json
Authorization: Bearer sk-blade-v2-xxx

{
  "intent": "帮我分析销售数据"
}

响应:

json
{ "session_id": "sess_abc123" }

记下 session_id,后续所有操作都需要它。


2. 建立 WebSocket 连接

使用 Socket.IO 客户端连接到服务端,握手时传递认证信息:

连接地址: wss://blade.example.com/socket.io/
auth: { "token": "sk-blade-v2-xxx" }

3. 订阅会话

连接建立后,发送 session:subscribe 事件:

事件: session:subscribe
数据: { "session_id": "sess_abc123" }

订阅成功后,你将收到该会话的所有实时事件。


4. 发送消息

发送 chat:send 事件触发智能体响应:

事件: chat:send
数据: {
  "session_id": "sess_abc123",
  "message": "请统计每月销售额"
}

带附件的消息

事件: chat:send
数据: {
  "session_id": "sess_abc123",
  "message": [
    { "type": "text", "text": "分析这张图片" },
    { "type": "image_url", "image_url": { "url": "data:image/png;base64,..." } }
  ]
}

5. 接收流式响应

发送消息后,你会依次收到以下事件:

chat:start          ← 聊天开始
  turn:start        ← user turn 开始
  turn:end          ← user turn 结束
  turn:start        ← assistant turn 开始(status: streaming)
    turn:patch      ← 文本增量 (patch_type: add_content, text_delta: "你")
    turn:patch      ← 文本增量 (patch_type: add_content, text_delta: "好")
    turn:patch      ← 新增工具调用 (patch_type: add_tool_call)
    turn:patch      ← 工具结果 (patch_type: tool_result)
    turn:patch      ← 更多文本...
  turn:end          ← assistant turn 结束(status: completed)
  [可能有更多 turn...]
chat:end            ← 聊天结束

一次 chat:send 可能触发多轮 turn(智能体循环调用工具时)。

如何渲染流式文本

监听 turn:patch 事件,当 patch_type = "add_content"data.text_delta 存在时,将增量文本追加到显示区域。

如何获取最终完整结果

chat:end 后,调用 REST 接口拉取完整 Turn 列表:

GET /api/sessions/sess_abc123/messages

6. 停止生成

用户想中断时,发送 chat:stop

事件: chat:stop
数据: { "session_id": "sess_abc123" }

7. 清理

使用完毕后:

事件: session:unsubscribe
数据: { "session_id": "sess_abc123" }

然后断开 Socket.IO 连接。

删除会话

如不再需要:

DELETE /api/sessions/sess_abc123

会话模式

会话有两种模式:

模式说明
planning智能体先制定结构化计划,不直接执行工具
executing智能体直接执行动作和工具(默认)

真实业务任务、工具调用和文件处理,建议显式传 executing,不要只依赖默认值:

事件: chat:send
数据: {
  "session_id": "sess_abc123",
  "message": "请读取刚上传的 report.md 并总结",
  "mode": "executing"
}

使用规划模式

只需要方案、不希望执行工具时,发送消息时覆盖为 planning

事件: chat:send
数据: {
  "session_id": "sess_abc123",
  "message": "制定实施计划",
  "mode": "planning"
}

检查点与回退

列出检查点

GET /api/sessions/sess_abc123/checkpoints

回退到检查点

POST /api/sessions/sess_abc123/rewind
{ "checkpoint_id": "cp_xxx" }

查看历史状态(不修改)

POST /api/sessions/sess_abc123/checkout
{
  "checkpoint_id": "cp_xxx",
  "position": "before"
}

What-If 重跑

从某一步开始,使用不同的输入重新运行:

事件: chat:send
数据: {
  "session_id": "sess_abc123",
  "message": "换一种方法实现",
  "whatif": {
    "from_step": 3,
    "quotes": [],
    "deprecate_entry_ids": ["entry_1", "entry_2"]
  }
}
  • from_step:保留前 N 步,从第 N+1 步开始重跑
  • deprecate_entry_ids:标记为废弃的条目 ID(UI 可过滤不显示)

上下文压缩(Compaction)

对话过长时系统会自动压缩历史。也可手动触发:

事件: chat:compact
数据: { "session_id": "sess_abc123" }

压缩完成后,Turn 列表中会出现 kind = "compaction" 的条目,包含摘要和压缩比信息。


完整交互时序图

客户端                              服务端
  │                                   │
  │── POST /api/sessions ───────────→│  创建会话
  │←── { session_id } ──────────────│
  │                                   │
  │══ Socket.IO connect ════════════→│  建立连接
  │── session:subscribe ────────────→│  订阅
  │                                   │
  │── chat:send { message } ────────→│  发消息
  │                                   │
  │←── chat:start ──────────────────│  聊天开始
  │←── turn:start (user) ──────────│
  │←── turn:end (user) ────────────│
  │←── turn:start (assistant) ─────│
  │←── turn:patch (text_delta) ────│  流式文本
  │←── turn:patch (text_delta) ────│
  │←── turn:patch (add_tool_call) ─│  调用工具
  │←── turn:patch (tool_result) ───│  工具结果
  │←── turn:patch (text_delta) ────│  继续输出
  │←── turn:end (assistant) ───────│
  │←── chat:end ────────────────────│  聊天结束
  │                                   │
  │── GET /api/sessions/{id}/messages→│  拉取完整历史
  │←── [TurnProjection[]] ──────────│
  │                                   │
  │── session:unsubscribe ──────────→│  取消订阅
  │══ Socket.IO disconnect ═════════→│  断开