Skip to content

Structured output

Use structured output when your app needs a Swift value rather than free-form prose.

Examples/Sources/StructuredOutput/main.swift
import SwiftAISDK
struct Summary: Decodable, Sendable {
var title: String
var bullets: [String]
}
@main
struct StructuredOutputExample {
static func main() async throws {
let schema = AIJSONSchema<Summary>(
[
"type": "object",
"properties": [
"title": ["type": "string"],
"bullets": [
"type": "array",
"items": ["type": "string"],
],
],
"required": ["title", "bullets"],
],
name: "summary"
)
let provider = try AIProviders.openAI()
let model = try provider.languageModel("gpt-4.1-mini")
let result = try await model.generateObject(
"Summarize the SwiftAISDK README.",
schema: schema
)
print(result.object.title)
}
}

SwiftAISDK also mirrors the upstream-style Output entry point on generateText and streamText.

let result = try await model.generateText(
"Return a compact summary.",
output: Output.object(
schema: schema.jsonSchema,
name: schema.name,
as: Summary.self
)
)
print(result.output.bullets)

Use generateObject when you want the most direct Swift API. Use Output when you want one facade for text, object, array, choice, and JSON strategies.

  • Output.text() returns plain text through the same result wrapper used by the other strategies.
  • Output.object(schema:as:) validates JSON, decodes a Decodable Swift value, and keeps the raw output.
  • Output.array(element:minItems:maxItems:as:) expects an elements envelope, publishes optional array bounds in the generated JSON Schema, and rejects a final result outside those bounds.
  • Output.choice(choices:) constrains output to one of the provided strings.
  • Output.json() returns schema-free JSONValue.

All strategies preserve text, reasoning, usage, warnings, provider metadata, response metadata, and the underlying TextGenerationResult.

let labels = Output.array(
element: ["type": "string"],
minItems: 2,
maxItems: 4,
as: String.self
)

For source compatibility, the constructor remains nonthrowing. A negative bound or minItems > maxItems is rejected when generation or streaming begins, before the model performs work.

streamText(..., output:) maps language stream parts into AIOutputStreamPart:

  • textDelta for raw text deltas
  • partialOutput for incremental structured values when available
  • output for the final validated output
  • source, warning, metadata, responseMetadata, finish, and raw for surrounding stream state

Partial object and array parsing uses the Swift partial JSON repair path, so incomplete trailing fragments can be ignored while already-complete fields or elements continue to stream.

Typed object and array streams accept the same streamRetries option as raw streamText. A retryable in-band provider error can restart the whole typed output pipeline with failed-attempt parsing state isolated. JSON/schema/decoding failure after a complete provider response is not a provider-stream retry and does not consume this budget.

The object facades and Output strategies can use repairText to make one model output repair attempt after invalid JSON, schema validation, or decoding failures. Errors carry AIObjectGenerationError context including the strategy, failure kind, generated text, and whether repair was attempted.