Skip to content

Streaming

Gunpal Jain edited this page Nov 15, 2026 · 4 revisions

Streaming returns a response in pieces while the model is still generating, so you can show text as it arrives. Every StreamContentAsync overload returns IAsyncEnumerable<GenerateContentResponse>, which you read with await foreach.

Package: Google_GenerativeAI. Setup: Initialization.

using GenerativeAI;
using GenerativeAI.Types;

var model = new GoogleAi("YOUR_API_KEY").CreateGenerativeModel(GoogleAIModels.Gemini38Flash);

StreamContentAsync Overloads

StreamContentAsync(GenerateContentRequest request)

This is the most general overload. Build the request as described in Generate Content.

var request = new GenerateContentRequest();
request.AddText("Write a story about a robot learning to love.");

await foreach (var chunk in model.StreamContentAsync(request))
{
    Console.Write(chunk.Text());
}

StreamContentAsync(string prompt)

await foreach (var chunk in model.StreamContentAsync("Generate a list of 10 creative project ideas."))
{
    Console.Write(chunk.Text());
}

StreamContentAsync(string prompt, string fileUri, string mimeType)

Streams a response for a prompt and a remote file URI, such as a Files API URI, a gs:// URI on Vertex AI or a public URL.

await foreach (var chunk in model.StreamContentAsync(
                   "Describe what is happening in this image.",
                   remoteFile.Uri!,           // e.g. from FileClient.UploadFileAsync
                   "image/jpeg"))
{
    Console.Write(chunk.Text());
}

To stream with a local file path, use GeminiModel.StreamContentAsync(prompt, filePath). See Multimodal Features.

StreamContentAsync(IEnumerable<Part> parts)

var parts = new List<Part> { new Part { Text = "Translate 'Hello, world!' to Spanish." } };

await foreach (var chunk in model.StreamContentAsync(parts))
{
    Console.Write(chunk.Text());
}

StreamContentAsync(IEnumerable<Content> contents)

var contents = new List<Content>
{
    new Content("Explain the concept of quantum entanglement.", Roles.User)
};

await foreach (var chunk in model.StreamContentAsync(contents))
{
    Console.Write(chunk.Text());
}

Cancellation

Every overload takes a CancellationToken. Pass it directly or use WithCancellation:

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));

await foreach (var chunk in model.StreamContentAsync("Write a long essay.", cts.Token))
{
    Console.Write(chunk.Text());
}

Collecting the Full Text

Each chunk holds only part of the output. Join the chunks to get the full text:

var sb = new System.Text.StringBuilder();
await foreach (var chunk in model.StreamContentAsync("Tell me a joke."))
{
    sb.Append(chunk.Text());
}
Console.WriteLine(sb.ToString());

Behavior Notes

  1. Function calling: When the last chunk asks for a function call and the model has function tools with auto-calling enabled, the SDK runs the function and keeps streaming the model's follow-up. See Function Calling.
  2. Automatic continuation: If a stream ends with FinishReason.CONTINUATION, or fails after a continuation checkpoint, the SDK resumes it with the continuation token. This is controlled by EnableAutomaticContinuation and MaxContinuations (see Generate Content).
  3. Chat sessions: ChatSession.StreamContentAsync adds the joined response to the history when the stream completes. See Chat Session.
  4. Thinking: With ThinkingConfig.IncludeThoughts = true, chunks can contain thought parts (Part.Thought == true).
  5. Errors: An API error is thrown as ApiException while you iterate. Wrap the await foreach in try/catch.

Related Pages

API Reference

Clone this wiki locally