Agent skills for iOS, iPadOS, Swift, SwiftUI, and modern Apple framework development.
80
100%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
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 app-managed API key, model hosting, or network round trip for generation; still handle Apple Intelligence and system model asset availability.
@GenerableSystemLanguageModel.default.contextSize for the current limitSystemLanguageModel.default.supportsLocale(_:) before generation;
use supportedLanguages only when listing broad language supportcontextSize: Returns the model's maximum context window in tokenssupportedLanguages: Set<Locale.Language> values the model supportssupportsLocale(_ locale: Locale) -> Bool: Preferred locale check before generating because it accounts for fallbacksAlways 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:
let candidates = [Locale.current] + Locale.preferredLanguages.map(Locale.init(identifier:))
guard let locale = candidates.first(where: SystemLanguageModel.default.supportsLocale) else {
// Route to fallback UI before generating
break
}
// Proceed with model usage
case .unavailable(.appleIntelligenceNotEnabled):
// Guide user to Settings > Apple Intelligence
case .unavailable(.modelNotReady):
// System model assets are downloading or unavailable for other system reasons
case .unavailable(.deviceNotEligible):
// Device cannot run Apple Intelligence
default:
// Graceful fallback for unknown or future unavailable reasons
}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?")@Generable output schemas also consume the shared context windowTool<Arguments, Output> conforms to Sendable; implement tools so captured
state is concurrency-safeArguments type must conform to ConvertibleFromGeneratedContentOutput 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.
.tessl-plugin
skills
accessorysetupkit
references
activitykit
references
adattributionkit
references
alarmkit
references
app-clips
app-intents
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-ettrace-performance
ios-localization
ios-memgraph-analysis
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
references
spritekit
references
storekit
swift-api-design-guidelines
swift-architecture
references
swift-charts
references
swift-codable
references
swift-concurrency
swift-formatstyle
references
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