> ## Documentation Index
> Fetch the complete documentation index at: https://agentrail.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Stream AgentRail task events with the TypeScript SDK

> Use client.streamEvents to receive real-time task lifecycle events over SSE, with AbortController cancellation and cursor-based reconnection.

The `streamEvents` method opens a server-sent event (SSE) connection and yields `TaskLifecycleEvent` objects as they arrive. You can filter by event type, control reconnection with a cursor, and cancel the stream with an `AbortController`.

## Basic usage

```typescript theme={null}
const controller = new AbortController();

for await (const event of client.streamEvents({
  eventTypes: ["task.updated", "task.reviewed", "task.shipped"],
  heartbeatSeconds: 30,
  signal: controller.signal,
})) {
  console.log(event.id, event.type);
}
```

The `for await` loop runs until the stream closes or the signal is aborted. Each `event` object carries `id`, `type`, and `data` fields.

## Stop the stream

Call `abort()` on the controller to close the stream from the consumer side:

```typescript theme={null}
const controller = new AbortController();

// Stop after 60 seconds
setTimeout(() => controller.abort(), 60_000);

for await (const event of client.streamEvents({
  eventTypes: ["task.updated"],
  signal: controller.signal,
})) {
  console.log(event.id, event.type);
}
```

## Reconnect with a cursor

After a disconnect, pass the last received event ID as `cursor` to resume the stream without missing events:

```typescript theme={null}
let lastEventId: string | undefined;

for await (const event of client.streamEvents({
  eventTypes: ["task.updated", "task.reviewed", "task.shipped"],
  heartbeatSeconds: 30,
  cursor: lastEventId,
  signal: controller.signal,
})) {
  lastEventId = event.id;
  console.log(event.id, event.type);
}
```

The server replays any events that occurred after the cursor position.

## Event types

| Event type      | When it fires                                  |
| --------------- | ---------------------------------------------- |
| `task.updated`  | The task's status, branch, or metadata changed |
| `task.reviewed` | A review decision was posted                   |
| `task.shipped`  | The task was shipped (merged and deployed)     |

<Tip>
  Set `heartbeatSeconds` to a value lower than your load balancer's idle connection timeout. A value of `30` works well for most deployments.
</Tip>

## Required scope

Streaming events requires the `events:read` scope on your API key. A missing scope returns a `403` response before the stream opens.
