工作流启用会话记忆后,每次携带 session_id 发送的轮次都会保存在 ModelRiver 中(见端点中的会话记忆)。会话 API 让你的后端读取这些对话并向其中追加轮次,因此你无需自己再保存一份聊天记录。
典型用途:
- 在你的应用中展示用户过去的对话。
- 将对话转交给人工客服:把用户的消息和客服的回复保存在同一个会话中,这样 AI 重新接手时能看到客服说过的话。
- 通过实时更新,在你的应用或客服后台中即时显示新的轮次。
- 删除会话以重置对话。
所有端点都使用与 /v1/ai 相同的项目 API 密钥(Authorization: Bearer mr_live_…),并且只能看到该密钥所属项目中的会话。其他项目的会话,或不是 UUID 的 id,都会返回 404 {"error": "Session not found"}。
列出会话
1GET /v1/sessions?workflow=support_bot&limit=20&page=1| 参数 | 默认值 | 说明 |
|---|---|---|
workflow | 全部 | 只返回该名称工作流的会话 |
limit | 20 | 每页数量,最多 100 |
page | 1 | 页码,从 1 开始 |
会话按最近活动时间倒序排列。
1{2 "data": [3 {4 "id": "9f8c2c1e-5b8a-4d0e-9a51-2f6f0f1d7a10",5 "workflow": "support_bot",6 "message_count": 6,7 "last_activity_at": "2026-10-25T09:14:03.512Z",8 "inserted_at": "2026-10-25T08:58:41.007Z",9 "last_message": {10 "role": "assistant",11 "content": "Your refund was issued today.",12 "at": "2026-10-25T09:14:03.498Z"13 }14 }15 ],16 "page": 1,17 "limit": 2018}message_count 统计已保存的轮次:每条 AI 回复和每条追加的消息各计一次。最新轮次没有可读文本时,last_message 为 null。
读取会话
1GET /v1/sessions/:id1{2 "id": "9f8c2c1e-5b8a-4d0e-9a51-2f6f0f1d7a10",3 "workflow": "support_bot",4 "inserted_at": "2026-10-25T08:58:41.007Z",5 "last_activity_at": "2026-10-25T09:14:03.512Z",6 "messages": [7 {8 "id": "4b1d…:user",9 "role": "user",10 "author": "user",11 "author_name": null,12 "content": "I was charged twice for order 1234",13 "created_at": "2026-10-25T08:58:40.112Z"14 },15 {16 "id": "4b1d…:assistant",17 "role": "assistant",18 "author": "ai",19 "author_name": null,20 "content": "Sorry about that. Let me connect you with our billing team.",21 "created_at": "2026-10-25T08:58:41.007Z"22 },23 {24 "id": "7e02…:assistant",25 "role": "assistant",26 "author": "agent",27 "author_name": "Dana",28 "content": "Hi, I'm Dana. I've refunded the duplicate charge.",29 "created_at": "2026-10-25T09:14:03.498Z"30 }31 ],32 "truncated": false33}消息按时间正序排列(最早的在前)。
| 字段 | 说明 |
|---|---|
id | 稳定的消息 id,请将其视为不透明字符串。 |
role | user 或 assistant |
author | user、ai(模型回复)或 agent(通过此 API 追加的人工回复) |
author_name | 追加消息时传入的 author_name,否则为 null |
created_at | 该轮次的保存时间 |
truncated | 当会话超过此处返回的最近 100 个轮次时为 true |
只返回对话本身。系统提示词、注入的会话记忆以及 ModelRiver 内置的安全指令都不会返回,失败请求的回复也不会返回。轮次会按照你所在套餐的日志保留期限保存。
追加消息
在会话中保存一个轮次,不调用模型。不会产生费用,也不计入请求次数。
1POST /v1/sessions/:id/messages2Content-Type: application/json3 4{ "role": "assistant", "content": "Hi, I'm Dana. I've refunded the duplicate charge.", "author_name": "Dana" }| 字段 | 必填 | 说明 |
|---|---|---|
role | ✅ | user 保存一条用户消息;assistant 保存一条人工客服的回复(author: "agent") |
content | ✅ | 非空文本,最多 100,000 个字符 |
author_name | ❌ | 显示名称,最多 200 个字符 |
响应 201:
1{2 "id": "7e02…:assistant",3 "role": "assistant",4 "author": "agent",5 "author_name": "Dana",6 "content": "Hi, I'm Dana. I've refunded the duplicate charge.",7 "created_at": "2026-10-25T09:14:03.498Z"8}追加的轮次会成为会话记忆的一部分。下一次携带该 session_id 的 /v1/ai 请求会把这些用户消息和客服回复当作之前的对话,AI 可以从客服停下的地方继续。
缺少字段或字段无效时返回 400 和 error 信息。如果项目已停止保存请求正文,追加同样会返回 400,因为会话内容无法保存。
实时更新
无需轮询即可实时跟踪会话:新的轮次、你的应用发送的事件以及删除操作,都会通过与异步响应流式传输相同的 WebSocket 送达。
-
你的后端为该会话申请一个一次性令牌:
HTTP1POST /v1/sessions/:id/subscribeJSON1{2 "session_id": "4b1d…",3 "ws_token": "Qm9i…",4 "websocket_url": "wss://api.modelriver.com/socket",5 "websocket_channel": "session:7c2e…:4b1d…",6 "expires_in": 3007} -
你的前端使用
ws_token加入websocket_channel。客户端 SDK 会完成这一步,并在每次重新连接时向你的后端申请新令牌:TYPESCRIPT1import { subscribeToSession } from '@modelriver/client';23const subscription = subscribeToSession({4 // Your backend route that calls POST /v1/sessions/:id/subscribe5 getSubscription: () => fetch(`/api/chat/${chatId}/live`, { method: 'POST' }).then((r) => r.json()),6 onMessage: (message) => addToChat(message),7 onSignal: (signal) => { if (signal.name === 'agent.joined') showAgent(signal.data); },8 onDeleted: () => closeChat(),9});1011// Later12subscription.close();
令牌只能使用一次,只对该会话有效,未使用时五分钟后过期。连接会在一小时后关闭,SDK 会用新令牌重新连接。由于该频道会传输对话内容,请只为有权查看该对话的用户申请令牌。
事件
| 事件 | 载荷 | 触发时机 |
|---|---|---|
message | 与“读取会话”中格式相同的一条消息,外加 session_id | 会话中的一次 /v1/ai 请求成功(先是用户消息,然后是回复),或有轮次被追加 |
signal | { "session_id", "name", "data", "sent_at" } | 你的后端发送了信号 |
deleted | { "session_id" } | 会话被删除 |
失败的请求和测试模式运行不会推送。消息 id 与 GET /v1/sessions/:id 返回的一致,因此客户端可以把实时消息合并到之前加载的历史中而不会重复。客户端断开期间发送的事件不会补发:重新连接后,请再次读取会话以补齐内容(SDK 的 onLive 回调会告诉你时机)。
发送信号
信号用于告知订阅者那些不属于对话轮次的事情,例如“客服已加入”“对话已关闭”或“对方正在输入”。信号只会发送给当前已连接的订阅者,且从不保存,因此不会出现在对话记录或会话记忆中。
1POST /v1/sessions/:id/signals2Content-Type: application/json3 4{ "name": "agent.joined", "data": { "name": "Dana" } }| 字段 | 必填 | 说明 |
|---|---|---|
name | ✅ | 1–64 个字符:小写字母、数字以及 _ . : - |
data | ❌ | 任意 JSON,最大 4 KB |
响应 202:{ "status": "sent" }。
删除会话
1DELETE /v1/sessions/:id1{ "message": "success", "status": "deleted" }删除会话会移除其 id 和记忆,并向其实时订阅者发送 deleted,效果与在控制台的日志 → 会话中删除相同。请求日志会保留以供审计。下一次 /v1/ai 请求不带 session_id 即可开始新的对话。在受保护的项目中,删除会返回 403 project_protected;请改由组织所有者或管理员在控制台中删除该会话。