Skip to content

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.failed event 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.