# Stream resume

> Durable handles and resuming interrupted agent runs.

Source: https://maincode.com/docs/agent-sdk-stream-resume
Section: Agent SDK · Matilda documentation

---

Durable streaming lets a client disconnect mid-stream and resume from where it left off. The server buffers events, keyed by a `streamId` advertised at stream start.

## `resumeAgentStream(streamId, lastEventId, handlers, options?)`

Resumes a previously detached stream by replaying buffered events from `lastEventId`. Returns the accumulated `AgentRunResult`.

```ts
import { resumeAgentStream, type AgentRunEvent } from '@maincode-ai/matilda-agent-sdk';

const result = await resumeAgentStream(
  savedStreamId,
  savedLastEventId,
  {
    onEvent: (event: AgentRunEvent) => {
      if (event.type === 'message.delta') process.stdout.write(event.delta);
    },
  },
);
console.log('Resumed output:', result.finalOutput);
```

## Parameters

| Field | Type | Description |
| - | - | - |
| `streamId` | `string` | The stream ID from stream.started event (or result.streamId). |
| `lastEventId` | `string \| undefined` | The last cursor received (from cursor event or result.lastEventId). Omit to replay from the start. |
| `handlers` | `{ onEvent?: (event: AgentRunEvent) => void }` | Event handler callback. |
| `options` | `RequestOptions & { signal?: AbortSignal; core?: MatildaCore }` | Request options. |

Returns `Promise<AgentRunResult>`.

## 401 auto-refresh

If the resume request returns 401 and the core has a `getToken` provider, the SDK automatically refreshes the token and retries once.

## Full resume example

```ts
import { stream, resumeAgentStream } from '@maincode-ai/matilda-agent-sdk';

let streamId: string | undefined;
let lastEventId: string | undefined;
let receivedText = '';

// Start streaming — capture IDs for potential resume
for await (const event of stream({ name: 'resumable-agent' }, 'Tell me a fact.')) {
  if (event.type === 'stream.started') streamId = event.streamId;
  if (event.type === 'cursor') lastEventId = event.lastEventId;
  if (event.type === 'message.delta') {
    receivedText += event.delta;
    process.stdout.write(event.delta);
  }
}

console.log('\n[Stream completed — streamId:', streamId, 'cursor:', lastEventId, ']');

// Later — resume from the last cursor if the stream was interrupted
if (streamId) {
  const result = await resumeAgentStream(streamId, lastEventId, {
    onEvent: (event) => {
      if (event.type === 'message.delta') process.stdout.write(event.delta);
    },
  });
  console.log('\n[Resumed — output:', result.finalOutput.slice(0, 60), '...]');
}
```
