# Events reference

The envelope every run event shares, the event types a consumer can rely on, and the payload of each.

Run events are how your application watches a run. They arrive as server-sent events on
`GET /v1/sessions/{session_id}/runs/{run_id}/events`, each frame carrying one JSON event.

- Every event has the same envelope: `id`, `type`, `session_id`, `run_id`, `created_at`, `data`.
- Three types are **terminal**: `run_completed`, `run_cancelled`, `error`.
- Two types mean **a person is needed**: `permission_request` and `user_question`.
- Everything else is progress. Ignore unknown types and unknown fields; they are forward
  compatible and non-terminal unless this page names them.

## The envelope

```text
id: 14
event: message_delta
data: {"id":"14","type":"message_delta","session_id":"ses_7d4f9c","run_id":"run_a12bc3","created_at":"2026-09-03T09:00:00.014Z","data":{"text":"I found"}}
```

| Field | Meaning |
|---|---|
| `id` | Orders events within this run only. Opaque; store it with the session and run ids, and send it back as `Last-Event-ID` to resume. |
| `type` | The event type below. |
| `session_id`, `run_id` | The run the event belongs to. Deduplicate by run id plus event id. |
| `created_at` | RFC 3339 UTC. |
| `data` | The type-specific payload. |

## Lifecycle events

| Type | Terminal | Payload | Meaning |
|---|---|---|---|
| `run_started` | No | `run_id` | The run was dispatched to the agent. |
| `run_completed` | **Yes** | `run_id`, optional `recovered` | The run finished. Read the run resource for its authoritative status. |
| `run_cancelled` | **Yes** | `run_id`, optional `recovered` | The run ended after cancellation. |
| `error` | **Yes** | `message`, and an error code where one applies | The run ended with an error. The run resource carries `error_code` and `error_message`. |

`recovered: true` marks a terminal event emitted while the platform reconciled a run after a
restart, rather than by the agent process itself. Treat it exactly like the non-recovered form.

## Output events

| Type | Payload | Meaning |
|---|---|---|
| `message_delta` | `text`, `framework`, `model` | A chunk of the agent's response. Concatenate deltas in id order. |

Harness-specific events can appear alongside these, with their own payloads. Render what you
recognise and ignore the rest.

## Interaction events

| Type | Payload | Meaning |
|---|---|---|
| `permission_request` | `request_id`, `interaction_key`, `tool_name`, `tool_input`, optional `replayed` | The agent wants to run a tool listed in `approval_required_tools` and is waiting for a decision. |
| `permission_resolved` | `interaction_key` and the decision | A decision was recorded. |
| `user_question` | `request_id`, `interaction_key`, the question, optional `replayed` | The agent asked a person a question and is waiting. |
| `user_answered` | `interaction_key` and the answer | An answer was recorded. |

Answer by `interaction_key`, never by `request_id`, and never from the event alone: list the
session's pending interactions to get the durable record, then answer it. `replayed: true` marks an
interaction re-emitted after a reconnect or a restored runtime; it is the same interaction, not a
new one. See [Approval-required actions](/guides/run/approval-required-actions).

## Context events

| Type | Meaning |
|---|---|
| `context_file_loaded`, `context_file_changed` | A context file was read into the agent's context, or changed since. |
| `claude_md_loaded`, `claude_md_changed` | The same, for a project `CLAUDE.md` when `enable_claude_md` is on. |
| `agent_skills_loaded` | The agent's `skills/` directory was mirrored into the session workspace. Names the skills that loaded, and warns about directories that could not. |

## Rules a consumer can rely on

1. Ids order events within one run and are opaque strings. Never compare ids across runs.
2. Replay after `Last-Event-ID` starts strictly after that id when history is available. Store the
   id after processing the event, and deduplicate by run id plus event id.
3. A stream can close cleanly without a terminal event. Read the run resource, and reconnect only
   while it is non-terminal.
4. The three terminal names above are the contract. Harness-specific catalogs and payload fields
   can evolve; the envelope, the cursor behaviour, and the terminal names do not.

## Where to go next

- [Stream and replay events](/guides/run/stream-and-replay-events): the consumer loop with
  cursor storage and deduplication.
- [Stream run events](/api/runs/stream-run-events): the endpoint.
