Skip to main content
受众:构建聊天 UI、多轮 assistant、或者任何需要给同一智能体发 多条消息而不重建上下文的工作流的 SDK 用户。
如果你只需要单次 request/reply带 deadline 的单个长任务, 请改看 调用智能体

1. 我该选哪个

任务和会话都骑在 Message Service 同一根底层消息通道上 —— 差别纯粹是 网关层的 UX 选择: 经验法则:
  • 聊天 UI → 会话
  • Cron 任务 / 后台进程 / 批处理报告 → 任务
  • 一次性问答 → 阻塞 invoke(最简)

2. 生命周期(会话)

:会话没有 chat_cancel 信封。没有单一飞行中的回合可中断 —— 如果想阻止智能体继续最近一轮,DELETE 整个会话(关闭通道)。 智能体收到正常通道关闭信号并停止流式输出。

3. 五个会话端点

全部需要 Authorization: Bearer <JWT or oag_...>oag_ key 是 user-scoped 的:任何 key 只要 owner 拥有底层会话,就能调用以下全部 端点(鉴权模型见 认证与 API Key —— v1.1.0 起 per-route scope 已下线)。 授权不变量:调用方只能看到 / 修改自己的会话。会话的 metadata.caller_owner_id 在 create 时写入;每次读写调用都检查。 所有权不匹配返回 403 forbidden"conversation is not owned by caller")。

4. since cursor(历史 + SSE)

since 是会话单调消息日志上的整数 offset。wire 把它当不透明值, 但模型如下方便你推理:
  • since=0(或省略)—— 从头开始。给晚到 SSE 客户端取完整 transcript 用。
  • since=N —— 从 offset N+1 续传。传入你成功观察到的最后一个 offset。

GET /messages

用上一页的 latest_offset 作为下一次 since。页大小:默认 200, 最大 500(Message Service 上限)。

GET /events(SSE)

流先回放所有 offset > 4 的消息,然后保持连接接收新消息。每个 frame:
  • offset 逐 frame:追踪最新一个,重连时作为 since=<latest> 传入。 崩溃后重连的 SSE 客户端不要since=0 —— 那会重放全部历史, 让你处理过的每个事件重复。
  • event: end(带 reason)在连接终止前发一次。可能的 reason:
    • channel_closed —— 你(或同认证的对端)对这个会话调了 DELETE
    • stream_closed —— Message Service 关了上游流(罕见;通常是服务重启 或会话 TTL 到了)。
会话上没有任务 SSE 的 task_terminal end reason 等价物 —— 开放式 模型里没有终止 frame。连接只在关闭 / 断开时结束。

Keepalive

空闲期连接没流量。浏览器和某些 HTTP 代理会在 ~60s 后关闭 idle 连接。 缓解:
  1. 把客户端放在不会杀 idle SSE 的代理后(大多数 CDN 原生处理 SSE);或
  2. socket 关闭就重连,把最新观察到的 offset 作为 since=<offset> 传入, 避免漏事件。

5. 实例 —— 聊天循环(Node.js fetch + EventSource)


6. 并发、幂等、附件

多个飞行中回合

会话 API 显式允许在智能体回复上一回合前排队多回合。回复按智能体 产出顺序到达;每个 agent_replyin_reply_to 字段回指最初的 用户 message_id,所以即使回合交错,客户端也能关联。

幂等

POST /messages 上传 idempotency_key。Message Service 在 (channel_id, idempotency_key) 上去重。网络重试同样 key 返回已存在 的 message_id 不重发 —— 可安全接入自动重试。 省略时网关生成新 UUID,所以不同 fetch 尝试的重试被当作不同消息。

附件

会话接受附件的方式与 invoketasks 一致 —— 通过 POST /api/v1/files/presign-upload 上传,然后把返回的 file_id 包到 下一个 POST /messages body:
网关把每个 file_id 解析成一个预签 download URL 嵌入 chat 信封, 让智能体带外取字节。完整流程见 调用智能体 § 附件

7. 删除语义

发生了什么:
  1. 通道以 reason=canceled 关闭。
  2. /events 上的任何 SSE 连接收到最后一个 event: end\ndata: {"reason":"channel_closed"}\n\n,流终止。
  3. 会话现在是 state=closed —— 后续 POST /messages 返回 409 conflict"channel closed")。
  4. 历史在关闭后 5 分钟的 MS 宽限窗口内仍可通过 GET /messages; 之后通道被驱逐,读返回 404 agent_not_found"conversation not found")。
如果想无限期保留 transcript,在调 DELETE 之前取出所有消息 —— 网关不是长期归档,只是 Message Service 受 TTL 约束的日志。

8. 错误

完整集合见 错误参考。此 API 上你最可能撞到的:

9. 另请参阅