SwiftyAISwiftyAI

Search documentation

Find a docs page by title or section

1

Agent UI Stream

createAgentUIStream exposes the tool loop as typed UI events. It is built for timelines, progress views, and debug panels where the app needs to show what the agent is doing.

EventUI use
agentStartedInitialize timeline state
stepStarted and stepFinishedGroup model and tool work by loop step
modelChunkAppend assistant text returned for that loop step
toolCallStartedShow the requested tool and arguments
toolCallFinishedRender tool output, status, or error
agentFinishedCommit the final AIStepResult
failedRender an error before the stream throws

Event Stream

let events = createAgentUIStream(
    model: model,
    prompt: "Check the order and draft a support reply.",
    tools: [lookupOrderTool],
    maxSteps: 4
)
 
for try await event in events {
    switch event {
    case .agentStarted:
        print("agent started")
    case .stepStarted(let event):
        print("step started:", event.stepIndex)
    case .modelChunk(let chunk):
        print(chunk.text, terminator: "")
    case .toolCallStarted(let event):
        print("calling:", event.toolCall.name)
    case .toolCallFinished(let event):
        print("tool finished:", event.toolResult.name)
    case .stepFinished(let event):
        print("step finished:", event.stepIndex)
    case .agentFinished(let event):
        print("final:", event.result.text)
    case .failed(let error):
        print("failed:", error.localizedDescription)
    }
}

The stream yields events in the same order the loop executes them. modelChunk is emitted after a model step completes; it is not token-by-token provider streaming.

Callbacks For State Stores

You can also receive events through callbacks while still iterating the stream.

let stream = createAgentUIStream(
    model: model,
    prompt: "Plan the refund workflow.",
    tools: [lookupOrderTool, policyTool],
    onEvent: { event in
        timeline.append(event)
    },
    onStepFinish: { step in
        finishedStepIDs.append(step.index)
    },
    onFinish: { result in
        finalText = result.text
    }
)

This is useful in SwiftUI view models where onEvent updates observable state and the for await loop only keeps the task alive.

When To Use This

Use streamWithTools when your UI only needs per-step text plus tool call/result chunks. Use createAgentUIStream when the UI needs a full activity timeline: agent start, each step, each tool call, each result, final success, and failure.

Related docs

Agent UI streams use the same tools and stop conditions described in tools and tool calling.