Inputs and Outputs
This page explains how to structure input, consume output, and handle streaming and cancellation. Start with the inputs you need, then choose how you want to receive results.
Inputs
Pick the input style that matches your use case. You can mix text and images in a single turn.
Text input
You can pass a single string:
var turn = await thread.RunAsync("Describe the failing tests");
If you need to compose a prompt from multiple segments, use UserInput entries. Text segments are joined with a double newline.
var turn = await thread.RunAsync(new[]
{
UserInput.TextInput("Describe the failures"),
UserInput.TextInput("Focus on impacted tests"),
});
Image input
Add images as UserInput.LocalImage entries. Text segments become the prompt, while images are forwarded to the CLI using --image.
var turn = await thread.RunAsync(new[]
{
UserInput.TextInput("Describe these screenshots"),
UserInput.LocalImage("./ui.png"),
UserInput.LocalImage("./diagram.jpg"),
});
Outputs
Use the output mode that fits your workflow. You can keep it simple with RunAsync or stream events in real time.
Structured output (JSON Schema)
When you need JSON you can validate, provide a schema per turn. The SDK writes the schema to a temporary file and forwards it to the CLI.
var schema = new
{
type = "object",
properties = new
{
summary = new { type = "string" },
status = new { type = "string", @enum = new[] { "ok", "action_required" } }
},
required = new[] { "summary", "status" },
additionalProperties = false
};
var turn = await thread.RunAsync("Summarize the repo", new TurnOptions { OutputSchema = schema });
Streaming output
Use streaming when you want to react to intermediate activity (tool calls, file changes, or partial output).
var streamed = await thread.RunStreamedAsync("Diagnose the test failure");
await foreach (var evt in streamed.Events)
{
switch (evt)
{
case ItemCompletedEvent itemCompleted:
Console.WriteLine($"item: {itemCompleted.Item.Type}");
break;
case TurnCompletedEvent completed:
Console.WriteLine($"output tokens: {completed.Usage.OutputTokens}");
break;
}
}
If you only need the final response, prefer RunAsync.
Output items
Each completed turn returns a collection of items (Turn.Items) and a FinalResponse. For a catalog of item types, see API Reference.
Cancellation
Every turn accepts a cancellation token via TurnOptions. Cancel the token to stop the turn and terminate the CLI process.
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
var turn = await thread.RunAsync("Long task", new TurnOptions { CancellationToken = cts.Token });
Streaming behaves the same way: cancel the token to stop iteration.
Errors
A turn can fail in two main ways:
- The CLI process exits with a non-zero code. The SDK throws an exception with stderr content.
- A
turn.failedevent is emitted. The SDK throws an exception with the error message.
If you are streaming, you can decide whether to stop consuming events based on the event types you receive.