Client SDK · Chat

Durable streaming.

Resume an interrupted stream from the last received event.

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

Durable streaming lifecycle

  1. Start a stream — chat.stream() emits a ResponseCreated event with a stream_id.
  2. Persist the stream_id and conversation_id immediately.
  3. If disconnected, call chat.active_stream(conversation_id) to check if the stream is still live.
  4. Call chat.resume(stream_id, last_event_id=...) to replay buffered events from last_event_id onwards.

chat.resume(stream_id, *, last_event_id=None, ...)

Resumes a previously detached stream by replaying buffered events from last_event_id. Returns an async generator of ChatEvent. Raises MatildaAPIError (404) when the stream buffer has expired.

Python
async for event in client.chat.resume(saved_stream_id, last_event_id=saved_last_event_id):
    if event.type == "response.output_text.delta":
        print(event.delta, end="", flush=True)
Fieldtypedescription
stream_idstrThe stream ID from response.created.
last_event_idstr | NoneThe last Redis stream entry ID received. Omit to replay from the start.
access_tokenstr | NoneOverride access token.
fingerprintstr | NoneDevice fingerprint.
stall_timeout_msint | NoneSSE stall watchdog timeout. Defaults to 45_000.

chat.active_stream(conversation_id)

Checks whether a conversation has an active stream.

Python
result = await client.chat.active_stream("conv-123")
# {"stream_id": "abc-123" | None, "status": "active" | "done" | "error" | None}

Returns a dict:

Python
# ActiveStreamLookup:
{"stream_id": "abc-123" or None, "status": "active" | "done" | "error" | None}

chat.notify_on_completion(stream_id, enabled=True)

Request a push notification when a backgrounded stream completes.

Python
await client.chat.notify_on_completion(stream_id, enabled=True)
Fieldtypedescription
stream_idstrThe stream to watch.
enabledboolEnable or disable the notification. Defaults to True.

Returns a dict (e.g. {"status": ...}).

Full resume example

Python
import asyncio
import os

from matilda_client import MatildaClient


async def main():
    async with MatildaClient(token=os.environ["MATILDA_ACCESS_TOKEN"]) as client:
        stream_id = None
        last_event_id = None

        # Start streaming
        async for event in client.chat.stream(
            input="Write a long essay about Australia.",
            conversation_id="conv-123",
        ):
            if event.type == "response.created":
                stream_id = event.stream_id
            if event.type == "response.cursor":
                last_event_id = event.last_event_id
            if event.type == "response.output_text.delta":
                print(event.delta, end="", flush=True)

        # Later — check if the stream is still active, then resume
        active = await client.chat.active_stream("conv-123")
        if active["status"] == "active" and stream_id:
            print("\n--- Resuming ---")
            async for event in client.chat.resume(stream_id, last_event_id=last_event_id):
                if event.type == "response.output_text.delta":
                    print(event.delta, end="", flush=True)


asyncio.run(main())