Swift @Generable and @Guide: Structured Output from On-Device Models
Apple's Foundation Models framework ships two macros that let language models generate typed Swift values directly — no JSON parsing, no schema drift, no post-processing.
Apple's Foundation Models framework ships with two Swift macros that change how on-device language models interact with app data: @Generable and @Guide. Without them, getting structured output from a language model requires manual parsing and validation. With them, the model generates typed Swift values directly — no JSON intermediary, no schema definition, no post-processing.
The problem these macros solve
Language models return text. Apps need typed data. The standard approach — prompt the model to return JSON, parse the response, validate it — works but fails in predictable ways: the model occasionally returns malformed JSON, field names drift from the schema, required fields get omitted. Every call site needs defensive parsing.
@Generable addresses this at the type level. Applied to a Swift struct, it synthesizes the schema the model needs to generate valid instances of that type. The model produces output that conforms to the struct's shape — enforced by the framework, not by the caller.
@Generable in practice
Marking a struct with @Generable is the only change required at the type definition. The macro generates the conformance code needed for LanguageModelSessionto target that type:
- The model receives a structured schema derived from the Swift type definition
- Output is constrained to valid instances — required fields are always present, types are enforced
- Nested @Generable types work recursively — a struct containing another @Generable struct generates a nested schema
- Enum cases are supported — the model chooses from the defined cases rather than generating free text
A shopping list is a representative example: a list of items, each with a name, quantity, and category. Without @Generable, parsing the model's response into that structure requires explicit JSON mapping. With it, the session call returns[ShoppingItem] directly.
@Guide: field-level steering
@Generable defines the shape. @Guide defines what each field means to the model. Applied to individual properties, it attaches a natural-language description that appears in the schema sent to the model. The description functions as an inline instruction: "this field should contain the aisle the item is found in, not a general category."
The practical effect is that field names — which the model can only guess at — are supplemented by explicit intent. A field named priority is ambiguous; a field annotated with "1 = buy today, 2 = buy this week, 3 = can wait" is not.
Streaming with @Generable types
LanguageModelSession supports streaming responses, and this extends to@Generable types. The session emits partially-constructed instances as the model generates output — fields populate progressively rather than the full struct appearing all at once.
In a SwiftUI view, this means binding directly to the streaming session's async sequence. A list populates incrementally as the model works. The framework handles partial deserialization; the view layer sees complete and partial instances on the same update path.
- Bind the session output to @State — SwiftUI re-renders on each partial update
- Partial instances have nil for fields not yet generated — handle this in the view, not the model layer
- Cancellation propagates through the async sequence — the task can be cancelled mid-stream without leaking resources
What this means for on-device AI features
The macros lower the cost of integrating structured model output into an app. Features that previously required a backend inference call — to handle output parsing in a controlled environment — become viable on-device candidates. No network call, no server-side schema validation, no inference cost.
The constraint is the same as the broader Foundation Models framework: Apple silicon devices only. The A17 Pro, M-series chips, and newer. Apps that need to support older hardware still require a fallback path — either a cloud model or a degraded feature experience.
Ready to build?
Tell us about your project
Free estimate within 48 hours. No commitment required.
Get a free estimate