---
title: Event のストリーミング
description: Session の Event を追い、切断後に再開します。
---

Session のログには、その Session で起きたことがすべて記録されます。ログを見ていなくてもかまいません。誰も接続していなくても Run は進み続け、再接続すれば、見逃した出来事はすべてログからわかります。

## 2 つの読み方

```http
GET /v1/sessions/{session_id}/events          # ページ単位
GET /v1/sessions/{session_id}/events/stream   # SSE でライブ配信
```

どちらも Session token か、**Session** › **読み取り** の権限を持つ API key で呼び出せ、同じ Event を返します。各 Event は 1 つのフラットな JSON オブジェクトで、シーケンス番号、時刻、`type` を持ちます。

```json
{ "seq": 5, "created_at": "2026-09-09T18:49:02Z", "type": "message_assistant", "message": { "role": "assistant", "content": [ ... ] } }
```

Event の種類は [Event リファレンス](/ja/reference/events) にまとめています。

### ページ

ページ単位のエンドポイントは、`limit` (1~200、既定は 50)、`order` (新しい順の `desc` が既定で、古い順は `asc`)、カーソルとして `before_seq` か `after_seq` を受け取ります。どちらのカーソルも、指定した番号自体は含みません。ページの `next_cursor` はシーケンス番号で、新しい順に読むときは `before_seq` に、古い順に読むときは `after_seq` に渡します。

### ストリーム

```bash
curl -N "https://api.us.cloud.subako.ai/v1/sessions/$SESSION_ID/events/stream?after_seq=0" \
  -H "Authorization: Bearer $SUBAKO_SESSION_TOKEN"
```

```txt
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 が優先されます。

```bash
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` がなく、保存もされず、失われることもあります。正しい内容は、その後に届く保存済みのメッセージです。

```txt
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 が始まります。

:::note
すべてがログに残るので、正しい状態を保つためにストリームを開き続ける必要はありません。数秒ごとにページ単位のエンドポイントを読むワーカーでも、ストリームで受け取るクライアントとまったく同じ内容を、少し遅れて受け取れます。
:::
