Streaming

Display tokens as the model generates them for a responsive UI, rather than waiting for the complete response.

agent.streamText()

The simplest way to stream. Yields every visible token (both thinking and response) as a plain String:

Swift
for try await text in agent.streamText("Explain how TCP/IP works") {
    print(text, terminator: "")
}
print()

SwiftUI Example

Stream tokens into a @State variable for a typewriter effect:

ContentView.swiftSwift
import SwiftUI
import StrandsAgents

struct ContentView: View {
    @State private var response = ""
    @State private var isStreaming = false
    let agent = Agent(model: provider)

    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            ScrollView {
                Text(response)
                    .frame(maxWidth: .infinity, alignment: .leading)
                    .padding()
            }
            Button(isStreaming ? "Streaming..." : "Ask Agent") {
                Task { await ask() }
            }
            .disabled(isStreaming)
        }
    }

    func ask() async {
        isStreaming = true
        response = ""
        do {
            for try await text in agent.streamText("Write a short poem about Swift") {
                response += text
            }
        } catch {
            response = "Error: \(error.localizedDescription)"
        }
        isStreaming = false
    }
}

agent.stream()

For more control, agent.stream() returns an AsyncThrowingStream<AgentStreamEvent> with typed events for each stage of the agent loop:

CaseWhen it firesAssociated value
.textDelta(String)Each token of model text outputThe token string
.thinkingDelta(String)Each token inside a thinking blockThe token string
.toolResult(ToolResultBlock)Tool execution completesStatus + output content
.contentBlock(ContentBlock)A complete content block finishesText, tool use, or reasoning block
.modelMessage(Message)Full model message assembledThe complete message
.result(AgentResult)Final response readyFull result + metrics

Use this when you want to separate thinking from response, show tool activity, or collect metrics:

Swift
for try await event in agent.stream(prompt) {
    switch event {
    case .textDelta(let text):
        response += text
    case .thinkingDelta(let text):
        thinkingLog += text
    case .toolResult(let result):
        statusLine = "Tool \(result.status)"
    case .result(let final):
        print("Latency: \(final.metrics.totalLatencyMs)ms")
        print("Tokens: \(final.usage.totalTokens)")
    default:
        break
    }
}