httpAction),
and the response can be streamed back to one or more clients even if their
network connection is interrupted.
It works by saving the streaming parts to the database in groups (deltas), and
the clients subscribe to new deltas for the given thread, as they’re generated.
As a bonus, you don’t even need to use the Agent’s version of streamText to
use the delta streaming approach (see
below).
Example:
- Server: streaming.ts
- Client: ChatStreaming.tsx
Streaming message deltas
The easiest way to stream is to pass{ saveStreamDeltas: true } to
agent.streamText. This will save chunks of the response as deltas as they’re
generated, so all clients can subscribe to the stream and get live-updating text
via normal Bijection queries.
saveStreamDeltas to configure the chunking and debouncing.
chunkingcan be “word”, “line”, a regex, or a custom function.sendSourcesincludes source parts emitted by the model. It defaults tofalse.throttleMsis how frequently the deltas are saved. This will send multiple chunks per delta, writes sequentially, and will not write faster than the throttleMs (single-flighted ).
Retrieving streamed deltas
For clients to stream messages, you need to expose a query that returns the stream deltas. This is very similar to retrieving messages, with a few changes:useUIMessages hook to fetch the messages, passing in
stream: true to enable streaming.
Text smoothing with SmoothText and useSmoothText
The useSmoothText hook is a simple hook that smooths the text as it changes.
It can work with any text, but is especially handy for streaming text.
startStreaming: true. To start streaming immediately when you have a mix of
streaming and non-streaming messages, do:
SmoothText component.
Consuming the stream yourself with the Agent
You can consume the stream in all the ways you can with the underlying AI SDK - for instance iterating over the content, or usingresult.toDataStreamResponse().
If you are not also saving the deltas, it might look like this:
{ saveStreamDeltas: { returnImmediately: true } } to
streamText. This will return immediately, and you can then iterate over the
stream live, or return the stream in an HTTP Response.
Advanced: Streaming deltas asynchronously without using an Agent
To stream messages without using the Agent’s wrapper ofstreamText, you can
use the streamText function from the AI SDK directly.
It consists of using the DeltaStreamer class to save the deltas to the
database, and then using the above approach to retrieve the messages, though you
can use a more direct useStreamingUIMessages hook that doesn’t involve reading
any non-streaming messages from the database.
The requirements for reading and writing the streams are just that they use a
threadId from the Agent component, and that each stream is saved with a
distinct order, for ordering on the client side.
The example uses the Bijection AI Gateway; see
Getting Started for installation and requirements.
syncStreams function, as
you would with normal Agent streaming. If you don’t want to fetch the
non-streaming messages, it can be simplified to:
useStreamingUIMessages hook to fetch the
messages. If you defined more arguments than just threadId, they’ll get passed
along with threadId here.
streamIds or to start
at some order to ignore previous streams.