Event のストリーミング
Session の Event を追い、切断後に再開します。
Session のログには、その Session で起きたことがすべて記録されます。ログを見ていなくてもかまいません。誰も接続していなくても Run は進み続け、再接続すれば、見逃した出来事はすべてログからわかります。
2 つの読み方
GET /v1/sessions/{session_id}/events # ページ単位
GET /v1/sessions/{session_id}/events/stream # SSE でライブ配信
どちらも Session token か、Session › 読み取り の権限を持つ API key で呼び出せ、同じ Event を返します。各 Event は 1 つのフラットな JSON オブジェクトで、シーケンス番号、時刻、type を持ちます。
{ "seq": 5, "created_at": "2026-09-09T18:49:02Z", "type": "message_assistant", "message": { "role": "assistant", "content": [ ... ] } }
Event の種類は Event リファレンス にまとめています。
ページ
ページ単位のエンドポイントは、limit (1~200、既定は 50)、order (新しい順の desc が既定で、古い順は asc)、カーソルとして before_seq か after_seq を受け取ります。どちらのカーソルも、指定した番号自体は含みません。ページの next_cursor はシーケンス番号で、新しい順に読むときは before_seq に、古い順に読むときは after_seq に渡します。
ストリーム
curl -N "https://api.us.cloud.subako.ai/v1/sessions/$SESSION_ID/events/stream?after_seq=0" \
-H "Authorization: Bearer $SUBAKO_SESSION_TOKEN"
id: 0
id: 2
event: message_user
data: {"seq":2,"created_at":"...","type":"message_user","source":"client","message":{...}}
id: 5
event: message_assistant
data: {"seq":5,"created_at":"...","type":"message_assistant","message":{...}}
id: 6
event: run_completed
data: {"seq":6,"created_at":"...","type":"run_completed","run_id":"01a08780-..."}
- カーソルを指定しないと、ストリームはログの現在の先頭から始まり、これから起きることだけを配信します。
after_seq=0を指定すると、まずログ全体を再生してからライブ配信に移ります。 - 最初のフレームには、ストリームの開始位置を示す
idだけが入っています。そのため、何も起きないうちに切断しても、再接続に使うカーソルがあります。 - 各 Event のフレームの
idはシーケンス番号で、eventは Event の種類です。 - 何も起きていない間も接続が切れないよう、15 秒ごとにコメントが送られます。
- ストリームは Session が存在する限り続きます。Run が終わっても閉じないので、Run の終了は Run 自身の終了 Event で判断してください。
履歴とこれから起きることの両方を表示するには、先にストリームを開いてから、ページを新しい順に読みます。すでに受け取った seq の Event は捨ててください。
切断後の再開
最後に処理したシーケンス番号を Last-Event-ID (または after_seq) に指定して再接続します。ストリームはその番号の直後から再生し、続けてライブ配信に移ります。両方を指定した場合は Header が優先されます。
curl -N "https://api.us.cloud.subako.ai/v1/sessions/$SESSION_ID/events/stream" \
-H "Authorization: Bearer $SUBAKO_SESSION_TOKEN" \
-H "Last-Event-ID: 42"
- カーソルは Event を処理し終えてから進めてください。 カーソルが示すのは、受け取った位置ではなく処理し終えた位置です。
- 同じ Event が再び届くことを前提にしてください。 届いた順にそのまま追加するのではなく、
seqをキーにして状態を管理します。
生成途中のテキスト
deltas=true を指定すると delta フレームが加わり、完成した message_assistant が届く前に、モデルのテキスト、思考、Tool の呼び出しの引数を生成されるそばから受け取れます。delta フレームには id がなく、保存もされず、失われることもあります。正しい内容は、その後に届く保存済みのメッセージです。
event: delta
data: {"run_id":"...","target":{"type":"model_call","data":{"model_call_id":"..."}},"n":0,"delta":{"type":"append","data":{"parts":[{"type":"text","data":{"index":0,"text":"Order 10"}}]}}}
パーツは text、thinking、tool_call のいずれかです (tool_call の arguments は JSON テキストの断片です)。{"type": "discard"} の delta が届いたら、その対象についてそれまでに受け取った内容を破棄します。対象ごとの delta は、同じ model_call_id を持つ message_assistant が届いた時点で終わります。
Run が終わったとき
Run は必ず run_completed、run_failed (error 付き)、run_cancelled のいずれか 1 つで終わり、どれも run_id を持ちます。実行中の Run がない Session は、終了したのではなく待機中です。次の入力があれば、同じログに続けて新しい Run が始まります。