搜尋完整文件

輸入關鍵字,例如 idempotency、proposal lifecycle 或權限。

選擇 開啟
English
瀏覽文件

Relay · Messages

傳送可安全重試的訊息

每次邏輯傳送都需要 client 產生的 nonce。重試結果不確定的 request 時,必須沿用原 nonce。Relay 透過 (channel_id, nonce) 回傳第一次寫入的結果,不建立第二則訊息。

傳送前提

你需要:

  • 有效的 host-signed bearer token
  • 與 token 屬於相同 tenant 的 channel
  • Token 內的 user_id 必須是 channel member
  • 這次邏輯傳送專用的新 nonce

Browser 或 Node.js runtime 可以使用 crypto.randomUUID() 產生 nonce。

第一次 request

NONCE="client-generated-uuid"

curl -i \
  -X POST "https://relay.example.com/api/channels/$CHANNEL_ID/messages" \
  -H "Authorization: Bearer $RELAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"body\":\"hello\",\"nonce\":\"$NONCE\",\"parent_message_id\":null,\"mentions\":[],\"attachment_ids\":[]}"

新 message 會回傳 201 Created

{
  "data": {
    "id": "message-uuid",
    "channel_id": "channel-uuid",
    "sender_id": "user-uuid",
    "body": "hello",
    "nonce": "client-generated-uuid",
    "seq": 41,
    "parent_message_id": null,
    "mentions": [],
    "attachments": []
  }
}

Relay 在 database transaction 內分配 seq。排列 channel message 時,應使用 seq,不能使用 client timestamp。

結果不確定時重試

Timeout 或 client disconnected 不代表 write 一定失敗。使用相同的 channel 與 nonce 重送同一次邏輯傳送:

curl -i \
  -X POST "https://relay.example.com/api/channels/$CHANNEL_ID/messages" \
  -H "Authorization: Bearer $RELAY_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"body\":\"hello\",\"nonce\":\"$NONCE\",\"parent_message_id\":null,\"mentions\":[],\"attachment_ids\":[]}"

如果第一次 request 已經建立 message,retry 會回傳 200 OK 與原 message。它的 idseq 不會改變,也不會產生第二則 message 或第二筆 post-commit handoff。

只有在 user 或 agent 確實要建立另一則邏輯訊息時,才產生新 nonce。Nonce 的 scope 是單一 channel,不是 global message ID。

失敗行為

條件結果
Token 缺少或無效401,錯誤為 invalid_or_missing_token
User 不是 channel member403,錯誤為 forbidden
Channel 已關閉422 validation response
bodynonce 缺少或無效422 validation response
Attachment 不存在、不屬於 sender,或尚未完成 upload整個 message transaction 失敗

成功回應的共同格式是 { "data": ... },失敗格式是 { "errors": [...] }

Commit 之後

REST 與 WebSocket send 會呼叫同一個 Relay write action。因此,membership validation、nonce idempotency、sequence assignment、attachment binding 與 message serialization 遵循同一份契約。

Message transaction commit 後才會開始 delivery work。沿用相同 nonce 的 retry 只會回傳既有 message,不會建立另一筆 delivery intent。

Reconnect 後,使用最後保存的 sequence 補回後續 message:

GET /api/channels/{channel_id}/messages?after_seq=41&limit=100
Authorization: Bearer <jwt>

Relay 依 seq 升冪回傳 channel history。這個 endpoint 的 limit 最大值為 100。

下一步:接收即時事件,並在重新連線後補齊訊息