> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dartantic.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Streaming Output

> Watch your AI think in real-time. It's like watching paint dry, but faster.

## Basic Streaming

```dart theme={null}
final agent = Agent('openai');

// Like watching a typist with 200 WPM
await for (final chunk in agent.sendStream('Tell me your best joke')) {
  stdout.write(chunk.output); 
}
// "Why don't scientists trust atoms?"
// (dramatic pause as it streams...)
// "Because they make up everything!"
```

## With Messages

```dart theme={null}
final agent = Agent('openai');

final history = [ChatMessage.system('You are a comedian.')];

await for (final chunk in agent.sendStream(
  'Tell me your best joke',
  history: history,
)) {
  // Stream the output
  stdout.write(chunk.output); 

  // Add new messages to the history
  history.addAll(chunk.messages);
}
```

## With Tools

```dart theme={null}
// Tool calls stream alongside text
await for (final chunk in agent.sendStream(
  'Weather in NYC?',
  tools: [weatherTool],
)) {
  // Tool results integrated into stream
  stdout.write(chunk.output);
}
```

## Extended Thinking

```dart theme={null}
final agent = Agent(
  'anthropic:claude-sonnet-4-5',
  enableThinking: true,
);

final result = await agent.send('Explain quicksort.');
final thinking = result.messages
    .expand((m) => m.parts)
    .whereType<ThinkingPart>()
    .map((p) => p.text)
    .join();
if (thinking.isNotEmpty) {
  stdout.write('[[${thinking.trim()}]]');
}
stdout.write(result.output);
```

Thinking is available via `ThinkingPart` in message parts so you can show a live
"thought bubble" without polluting the message stream. See [Extended
Thinking](/thinking) for more options.

## With Typed Output

```dart theme={null}
// Stream structured JSON
await for (final chunk in agent.sendStream(
  'List 3 facts',
  outputSchema: factsSchema,
)) {
  stdout.write(chunk.output); // Streams JSON chunks
}
```

## Usage Tracking & Tool Metadata

```dart theme={null}
var usage = const LanguageModelUsage();

await for (final chunk in agent.sendStream('Story time')) {
  stdout.write(chunk.output);
  if (chunk.usage.totalTokens != null) {
    usage = chunk.usage; // Final chunk contains usage
  }

  // Inspect server-side tool events (OpenAI Responses)
  final web = chunk.metadata['web_search'] as List?;
  if (web != null) {
    stdout.writeln('\nSearch stage: ${web.last['type']}');
  }
}

print('\nTokens used: ${usage.totalTokens}');
```

## Examples

* [Chat with
  streaming](https://github.com/csells/dartantic_ai/blob/main/packages/dartantic_ai/example/bin/chat.dart)
* [Multi-turn
  streaming](https://github.com/csells/dartantic_ai/blob/main/packages/dartantic_ai/example/bin/multi_turn_chat.dart)
* [Agent with
  streaming](https://github.com/csells/dartantic_ai/blob/main/packages/dartantic_ai/example/bin/agent.dart)

## Next Steps

* [Tool Calling](/tool-calling) - Stream with tools
* [Usage Tracking](/usage-tracking) - Monitor streaming costs
* [Server-Side Tools](/server-side-tools) - Stream provider-hosted tool output
