Agent skills for iOS, iPadOS, Swift, SwiftUI, and modern Apple framework development.
71
89%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Advisory
Suggest reviewing before use
Complete reference for Apple's Foundation Models framework (iOS 26+ / macOS 26+). On-device language model optimized for Apple Silicon. No API keys, no network, no cost.
@GenerableSystemLanguageModel.default.contextSize for the current limitSystemLanguageModel.default.supportedLanguages for supported localescontextSize: Returns the model's maximum context window in tokenssupportedLanguages: Array of locale identifiers the model supportssupportsLocale(_ locale: Locale) -> Bool: Check if a specific locale is supported before generatingAlways check before using. Never crash on unavailability.
import FoundationModels
// Quick boolean check
if SystemLanguageModel.default.isAvailable {
// Proceed
}
// Detailed availability
switch SystemLanguageModel.default.availability {
case .available:
// Proceed with model usage
case .unavailable(.appleIntelligenceNotEnabled):
// Guide user to Settings > Apple Intelligence
case .unavailable(.modelNotReady):
// Model downloading; show progress indicator
case .unavailable(.deviceNotEligible):
// Device cannot run Apple Intelligence
default:
// Graceful fallback
}Foundation Models supports specialized use cases:
// General purpose (default)
let model = SystemLanguageModel(useCase: .general, guardrails: .default)
// Content tagging (optimized for categorization)
let model = SystemLanguageModel(useCase: .contentTagging, guardrails: .default)// Basic session (uses SystemLanguageModel.default)
let session = LanguageModelSession()
// Session with system instructions
let session = LanguageModelSession {
"You are a helpful cooking assistant."
"Focus on quick, healthy recipes."
}
// Session with tools
let session = LanguageModelSession(
tools: [weatherTool, recipeTool]
) {
"You are a helpful assistant with access to tools."
}
// Session with specific model
let model = SystemLanguageModel(useCase: .general, guardrails: .default)
let session = LanguageModelSession(model: model, tools: []) {
"You are a helpful assistant."
}session.isResponding before new
requests.session.prewarm() before user interaction for faster first
response.LanguageModelSession(model: model, tools: [], transcript: savedTranscript).// Prewarm before user interaction
session.prewarm()
// Prewarm with a prompt prefix for faster specific responses
session.prewarm(promptPrefix: Prompt("Summarize the following text:"))// Simple text response
let response = try await session.respond(to: "Summarize this article: \(text)")
print(response.content) // String
// With generation options
let options = GenerationOptions(
sampling: .random(top: 40),
temperature: 0.7,
maximumResponseTokens: 512
)
let response = try await session.respond(to: prompt, options: options)let stream = session.streamResponse(to: "Tell me a story")
for try await snapshot in stream {
print(snapshot.content, terminator: "")
}
// Or collect the full response
let response = try await stream.collect()@GenerableThe @Generable macro creates compile-time JSON schemas for type-safe output.
@Generable
struct Recipe {
@Guide(description: "The name of the recipe")
var name: String
@Guide(description: "A brief description of the dish")
var summary: String
@Guide(description: "Cooking steps", .count(3))
var steps: [String]
@Guide(description: "Prep time in minutes", .range(1...120))
var prepTime: Int
}
let response = try await session.respond(
to: "Suggest a quick pasta recipe",
generating: Recipe.self
)
let recipe = response.content
print(recipe.name)
print(recipe.steps)@Generable PropertiesStringInt, Double, FloatBool[Element] where Element is Generable or a supported scalarOptional<T> where T is Generable or a supported scalar@Generable structs (nested)@Generable@Guide Constraints@Generable
struct ProductReview {
@Guide(description: "Product name")
var product: String
@Guide(description: "Rating", .range(1...5))
var rating: Int
@Guide(description: "Sentiment", .anyOf(["positive", "neutral", "negative"]))
var sentiment: String
@Guide(description: "Key themes", .count(3))
var themes: [String]
@Guide(description: "Summary in one sentence", .pattern(/^[A-Z].*\.$/))
var summary: String
@Guide(description: "Always English", .constant("en"))
var language: String
}Complete constraint list:
| Constraint | Type | Purpose |
|---|---|---|
description: | All | Natural language hint for generation |
.anyOf([values]) | String | Restrict to enumerated values |
.count(n) | Array | Fixed array length |
.minimumCount(n) | Array | Minimum array length |
.maximumCount(n) | Array | Maximum array length |
.range(min...max) | Numeric | Closed numeric range |
.minimum(n) | Numeric | Lower bound |
.maximum(n) | Numeric | Upper bound |
.constant(value) | String | Always returns this value |
.pattern(regex) | String | Regex format enforcement |
.element(guide) | Array | Guide applied to each element |
Properties are generated in declaration order. Place foundational data before dependent data:
@Generable
struct Summary {
var title: String // Generated first
var keyPoints: [String] // Generated with title context
var conclusion: String // Generated with full context
}let stream = session.streamResponse(
to: "Suggest a recipe",
generating: Recipe.self
)
for try await snapshot in stream {
// snapshot.content is Recipe.PartiallyGenerated (all properties optional)
if let name = snapshot.content.name { updateNameLabel(name) }
if let steps = snapshot.content.steps { updateStepsList(steps) }
}@Generable
enum Priority: String {
case low, medium, high, critical
}
@Generable
struct Task {
var title: String
var priority: Priority
}struct WeatherTool: Tool {
let name = "weather"
let description = "Get current weather for a city."
@Generable
struct Arguments {
@Guide(description: "The city name")
var city: String
}
func call(arguments: Arguments) async throws -> String {
let weather = try await fetchWeather(arguments.city)
return weather.description
}
}let session = LanguageModelSession(
tools: [WeatherTool()]
) {
"You are a helpful assistant."
}
// The model decides autonomously when to invoke tools
let response = try await session.respond(to: "What's the weather in Tokyo?")Tool protocol's associated Output type must conform to PromptRepresentable (e.g., String, [String], custom types)includesSchemaInInstructions: Boolean property on Tool (default true). Set to false to omit the tool's JSON schema from the system prompt, saving context tokens when the model already knows the schema.ToolCallError: Struct on LanguageModelSession representing a tool invocation failure. Properties: tool (the tool name), underlyingError (the original error).DynamicGenerationSchema: Build generation schemas at runtime for dynamic use cases where compile-time @Generable is insufficient. Construct schemas programmatically and pass to respond(to:schema:).do {
let response = try await session.respond(to: prompt)
} catch let error as LanguageModelSession.GenerationError {
switch error {
case .guardrailViolation:
// Content triggered safety filters; rephrase and retry
case .exceededContextWindowSize:
// Too many tokens; summarize earlier turns and create new session
case .concurrentRequests:
// Another request is already in progress on this session
case .rateLimited:
// Too many requests; back off and retry
case .unsupportedLanguageOrLocale:
// Current locale not supported by the model
case .unsupportedGuide:
// A @Guide constraint is not supported
case .assetsUnavailable:
// Model assets not available on device
case .decodingFailure:
// Failed to decode structured output
case .refusal(let refusal, _):
// Model refused the request
let explanation = try await refusal.explanation.content
print("Refused: \(explanation)")
default: break
}
}let options = GenerationOptions(
sampling: .greedy, // Deterministic output
temperature: nil, // Use default
maximumResponseTokens: 256 // Limit response length
)
// Random sampling with top-k
let options = GenerationOptions(
sampling: .random(top: 40),
temperature: 0.7
)
// Random sampling with probability threshold
let options = GenerationOptions(
sampling: .random(probabilityThreshold: 0.9)
)Sampling modes accept an optional seed parameter for reproducible output:
.random(top: 40, seed: 42), .random(probabilityThreshold: 0.9, seed: 42).
// Default guardrails (recommended)
let model = SystemLanguageModel(useCase: .general, guardrails: .default)
// Permissive content transformations (for text rewriting tasks)
let model = SystemLanguageModel(
useCase: .general,
guardrails: .permissiveContentTransformations
)Load fine-tuned LoRA adapters for specialized model behavior:
// Requires com.apple.developer.foundation-model-adapter entitlement
let adapter = try SystemLanguageModel.Adapter(name: "my-adapter")
try await adapter.compile()
let model = SystemLanguageModel(adapter: adapter, guardrails: .default)
let session = LanguageModelSession(model: model)
let response = try await session.respond(to: "Generate styled text")// Check compatible adapters
let ids = SystemLanguageModel.Adapter.compatibleAdapterIdentifiers(name: "my-adapter")
// Remove obsolete adapters
try SystemLanguageModel.Adapter.removeObsoleteAdapters()When conversations grow long:
SystemLanguageModel.default.contextSizeSystemLanguageModel.default.tokenCount(for:) to estimate usageif transcript.estimatedTokenCount > 3000 {
let summary = try await summarizeSession(session)
session = LanguageModelSession {
"Previous conversation summary: \(summary)"
"Continue helping the user."
}
}When multiple parts of an app need the model:
actor FoundationModelCoordinator {
private var session: LanguageModelSession?
func respond(to prompt: String) async throws -> String {
if session == nil {
session = LanguageModelSession()
}
guard let activeSession = session else {
throw FoundationModelError.sessionUnavailable
}
let response = try await activeSession.respond(to: prompt)
return response.content
}
}Serialize all Foundation Model access through a single coordinator to prevent Neural Engine contention.
SystemLanguageModel.default.contextSize for the current limit.[descriptive example].SystemLanguageModel.default.tokenCount(for:)
to avoid exceeding the context window.Log feedback for model improvement:
let data = session.logFeedbackAttachment(
sentiment: .negative,
issues: [
LanguageModelFeedback.Issue(
category: .didNotFollowInstructions,
explanation: "Ignored the word count constraint"
)
],
desiredOutput: nil
)Issue categories: .didNotFollowInstructions, .incorrect,
.stereotypeOrBias, .suggestiveOrSexual, .tooVerbose,
.triggeredGuardrailUnexpectedly, .unhelpful, .vulgarOrOffensive.
skills
accessorysetupkit
references
activitykit
references
adattributionkit
references
alarmkit
references
app-clips
app-intents
references
app-store-optimization
app-store-review
apple-on-device-ai
appmigrationkit
references
audioaccessorykit
references
authentication
references
avkit
references
background-processing
references
browserenginekit
references
callkit
references
carplay
references
cloudkit
references
contacts-framework
references
core-bluetooth
references
core-data
core-motion
references
core-nfc
references
coreml
references
cryptokit
references
cryptotokenkit
references
debugging-instruments
device-integrity
references
dockkit
references
energykit
references
eventkit
references
financekit
references
focus-engine
gamekit
references
healthkit
references
homekit
references
ios-accessibility
ios-localization
ios-networking
ios-simulator
references
mapkit
metrickit
references
musickit
references
natural-language
references
paperkit
references
passkit
references
pdfkit
references
pencilkit
references
permissionkit
references
photokit
push-notifications
realitykit
references
relevancekit
references
scenekit
references
sensorkit
references
speech-recognition
spritekit
references
storekit
swift-api-design-guidelines
swift-architecture
swift-charts
references
swift-codable
swift-concurrency
swift-formatstyle
swift-language
swift-security
references
swift-testing
swiftdata
swiftlint
swiftui-animation
swiftui-gestures
references
swiftui-layout-components
swiftui-liquid-glass
references
swiftui-patterns
swiftui-performance
swiftui-uikit-interop
swiftui-webkit
tabletopkit
references
tipkit
references
vision-framework
weatherkit
references
widgetkit
references