---
name: apple-foundation-models-on-device-llm
description: "On-device LLM in Swift — LanguageModelSession, @Generable guided generation, tool calling, streaming, fallback. Build on-device AI with Apple's Foundation Models framework: LanguageModelSession with instructions and prewarm, @Generable/@Guide structured output via guided generation, streaming partial responses with PartiallyGenerated, Tool protocol for tool calling, and SystemLanguageModel.availability checks for graceful fallback when Apple Intelligence is unavailable."
license: MIT
---

# Apple Foundation Models

This skill helps Swift developers build features on top of Apple's Foundation Models framework — the on-device large language model that ships with Apple Intelligence on iOS, iPadOS, and macOS. It covers the practical surface area you actually call: creating a `LanguageModelSession`, getting typed output with `@Generable`, streaming partial results, exposing app functions through the `Tool` protocol, and gating everything behind availability checks. It's for people writing real Swift code, not prompt experiments.

## When to use it

- You want a chat, summarization, classification, or extraction feature that runs locally with no network call and no per-token cost.
- You need the model to return a Swift struct you can use directly, not a string you have to parse.
- You want to let the model call into your app (search a database, fetch the weather) via tool calling.
- You're handling the cases where the model isn't ready — device unsupported, Apple Intelligence off, or assets still downloading.

## How it works

The entry point is `SystemLanguageModel.default`. Always branch on `model.availability`, which returns `.available` or `.unavailable(reason)` (cases include `.deviceNotEligible`, `.appleIntelligenceNotEnabled`, `.modelNotReady`).

A `LanguageModelSession` holds the conversation and is created with `instructions:`. Call `session.prewarm()` early to load assets before the first request. Use `session.respond(to:)` for a full reply, or `session.streamResponse(to:)` to get an async sequence of snapshots.

For structured output, annotate a type with `@Generable` and constrain fields with `@Guide(description:)` (and constraints like ranges or `.count`). Pass `generating: MyType.self` to `respond`, and the framework uses guided generation to guarantee the output conforms. Streaming yields a `MyType.PartiallyGenerated` whose properties fill in incrementally. Tools conform to the `Tool` protocol with a `@Generable` `Arguments` type and a `call(arguments:)` method, then are handed to the session via `tools:`.

```swift
curl -fsSL --create-dirs -o ~/.claude/skills/apple-foundation-models-on-device-llm/SKILL.md https://claudeskil.com/skills/apple-foundation-models-on-device-llm/SKILL.md

import FoundationModels

@Generable struct Recipe {
    @Guide(description: "Dish name") var title: String
    @Guide(.count(3...8)) var steps: [String]
}

let model = SystemLanguageModel.default
guard case .available = model.availability else { return }

let session = LanguageModelSession(instructions: "You are a concise chef.")
let recipe = try await session.respond(to: "Quick pasta", generating: Recipe.self).content
```

## Tips & gotchas

- A session is single-threaded for requests — check `session.isResponding` before sending another; concurrent calls throw.
- The context window is limited; long histories raise `exceededContextWindowSize`. Start a fresh session and carry over a summary.
- `GenerationOptions` lets you set `temperature` and sampling; pass it to `respond`.
- Guided generation only guarantees shape, not facts. Validate values yourself.

## FAQ

**Which devices run it?** Apple-Intelligence-capable hardware (e.g. A17 Pro / M-series) with the feature enabled. Everything else reports `.unavailable`.

**Can I fine-tune it?** No weight training, but you steer behavior with `instructions`, `@Guide`, and an optional adapter via `SystemLanguageModel(adapter:)`.

**Does it work offline?** Yes — inference is fully on-device once assets are downloaded.
