Skip to content
Before you stream
Public Preview

Stream free-text answers and replace with the final result

Stream free-text answers from Duale AI, display ordered chunks by generation and sequence, then replace the stream with the final result from model().

This guide covers streaming prerequisites, ordered chunk display with generation handling, and replacing streamed text with the final result.

  • Streaming prerequisites and eligible answer formats.
  • Ordered chunk display with generation and sequence handling.
  • Replacing streamed text with the validated final result.

Summaries were generated by AI.

Stream a free-text answer to show it while Duale AI writes it, then replace the streamed text with the final result from await response.model().

Before you stream

  • Complete Install the SDK and the first typed request.
  • Only free-text answers stream. Pass no res or response_format, or pass the text or markdown format.
  • The example submits a real Task and can incur Platform and model-provider usage. Use non-sensitive input.

Show the chunks in order

Chunks can arrive out of order. Each BridgeContentDeltaResponse carries a generation and a sequence, and a BridgeContentResetResponse starts a new generation. A new generation starts when Duale AI restarts the answer, for example after it retries a provider request. A reset can also withdraw the answer for good: when a safety check blocks the request, any part of the answer already shown is withdrawn and the Task fails with REQUEST_BLOCKED.

  1. Keep only events from the highest generation. A higher generation replaces everything shown from earlier ones.
  2. Show that generation’s deltas sorted by sequence.
import asyncio

from dualeai import BridgeContentDeltaResponse, ask, create_sdk


async def main() -> None:
    async with create_sdk() as sdk:
        response = await ask("Write a short poem", streaming=True, sdk=sdk)
        print(response.task_id)

        generation, parts = 0, {}
        async for event in response.stream():
            if event.generation < generation:
                continue
            if event.generation > generation:
                generation, parts = event.generation, {}
            if isinstance(event, BridgeContentDeltaResponse):
                parts[event.sequence] = event.delta
            # Display "".join(parts[sequence] for sequence in sorted(parts)).

        print(await response.model())


asyncio.run(main())

Save the example as stream_answer.py, then run it:

python stream_answer.py

The script prints the Task identifier, consumes the stream, then prints the final answer. Your display shows the ordered text of the highest generation while the stream runs.

Replace the stream with the final result

Streamed text is a live view of the answer, for display only. When the stream ends, replace it with await response.model(), the validated final result. For an answer with no format or the text format, the final result is the only copy that can carry the content mark. Do not store, index, or forward the streamed text.

Check. After the stream ends, the text your application keeps is the value that model() returned, not the assembled chunks.

Streaming events lists the event types and their fields.