Streaming
Streaming uses normalized ModelEvent objects. The runtime emits a start
event, then delegates native streaming to adapters when available.
from praval import Agent
agent = Agent("assistant", provider="openai", model="gpt-5.4-mini")
for event in agent.stream("Write one sentence.", stream_options={"include_usage": True}):
if event.type == "delta":
print(event.delta, end="")
elif event.type == "usage":
print(f"\nusage={event.usage.total_tokens}")
elif event.type == "final":
print("\ncomplete")
Async streaming:
async for event in agent.astream("Write one sentence."):
...
Streaming and conversation history
A streamed exchange enters the agent’s history the same way as chat() or
generate(). The user turn is added when stream() is called, or when
iteration of astream() begins. When the
final event is produced, the answer from final.response.content is added,
the history is trimmed, and with persist_state=True the state is saved, all
before the event reaches your loop. Breaking out of the loop after final
therefore keeps the answer.
A stream that raises, or that is closed or abandoned before final, leaves
only the user turn in history.
stream() and astream() accept the per-call options listed in
Model Runtime, including allowed_tool_names and
additional_system_message.
Native and fallback streaming
OpenAI, Anthropic, Gemini, OpenRouter, and OpenAI-compatible providers use native streaming
paths. If a profile advertises native_streaming=True but the adapter does not
implement streaming, the runtime raises a provider error before execution.
Fallback streaming is allowed only for providers that explicitly describe streaming as non-native or emulated.
When a request offers client tools, stream() and astream() complete the
runtime tool loop before emitting its tool-call/result events and final text.
These events describe completed work; they are not live progress notifications
before each handler runs. The final text is emitted as a complete delta rather
than a token-by-token stream, and text between tool rounds is not exposed.
Native text streaming applies to requests without client tools. To stream a
text-only turn from an agent that has tools registered, pass
allowed_tool_names=[].
If response_schema enables validate_locally, the runtime validates the answer
before emitting final or committing it to history. Text deltas remain
provisional until that final event; see Structured Outputs.