# 实时（WebSocket）

Source: https://docs.simail.ai/zh/realtime/

> 服务端 agent 用 WebSocket 接收 simail 事件：订阅、限额、吊销，以及重连时不丢事件。

长时间运行的 agent 可以保持一条连接，事件发生时就收到。

`GET wss://api.simail.ai/v0/ws`

需要 `event_read`。升级请求用 `Authorization: Bearer <key>` 认证。这只给**服务端** agent：不要把 API key 放进浏览器。

```ts
import WebSocket from "ws";

const ws = new WebSocket("wss://api.simail.ai/v0/ws", {
  headers: { Authorization: `Bearer ${process.env.SIMAIL_API_KEY}` },
});
ws.on("open", () => {
  ws.send(JSON.stringify({ type: "subscribe", inbox_ids: ["shop-helper@simail.email"], event_types: ["message.received", "thread.locked"] }));
});
ws.on("message", (raw) => {
  const msg = JSON.parse(raw.toString());
  if (msg.type === "event") handle(msg.event); // de-duplicate on msg.event.event_id
});
ws.on("close", (code) => scheduleReconnect(code));
```

## 消息

客户端到服务器，可选，任何时候：

```json
{ "type": "subscribe", "inbox_ids": ["shop-helper@simail.email"], "event_types": ["message.received"], "include_non_wake": false }
```

订阅只能收窄 key 能看到的范围。没有订阅时，你会收到 key 作用域里每一条唤醒了 agent 的事件。

服务器到客户端：

```json
{ "type": "event", "event": { "event_id": "evt_…", "event_type": "message.received", "occurred_at": "2026-10-18T17:02:12Z", "inbox_id": "shop-helper@simail.email", "thread_id": "thr_…", "message_id": "msg_…", "data": { "wake": true } } }
```

`event` 对象和其他地方一样是薄载荷；见[事件类型](/zh/event-types/)。没有唤醒 agent 的事件会被跳过，除非订阅时带 `include_non_wake: true`。

## 寿命和限额

- 一条连接**最多 1 小时**（key 更早过期则更短）。然后关闭，你重连，重连会再检查 key。
- 吊销或收窄 key、移除成员、退出控制台会话或暂停组织，会立刻关掉受影响的连接，码为 **`4401`**（`revoked`）。
- 每个组织 50 条连接，每把 key 10 条，每分钟 10 次握手。
- 客户端落后超过 1 MiB 会被断开。
- 服务器回答 ping，不会因此唤醒任何东西；空闲连接很便宜。

## 重连时不丢

WebSocket 是快路径，不是日志。要不漏事件，记住你处理过的最后一条 `event_id`，重连后用存下的游标走 [`GET /v0/events`](/zh/events/) 补上。按 `event_id` 去重。重连之间退避（例如 1 秒、2 秒、4 秒……直到 60 秒）。`4401` 之后不要用同一把 key 重连：它已被吊销或收窄。
