
On-Device Foundation Models
FreeIntegrate Apple's LLM for privacy-focused AI features.
Free · Opens the source repo
What On-Device Foundation Models does
The On-Device Foundation Models skill provides developers with a framework for integrating Apple's on-device language model into their applications. This skill is particularly useful for creating AI-powered features that operate without relying on cloud services, ensuring user data remains private and secure. By leveraging the FoundationModels framework, developers can implement functionalities such as text generation, structured output, and real-time data extraction directly on users' devices.
With this skill, developers can build applications that generate or summarize text, extract structured data from natural language inputs, and implement custom tool calls for specific domain-related tasks. The skill supports streaming responses for real-time UI updates, making it ideal for applications that require immediate feedback based on user interactions. The focus on on-device execution means that applications can function offline, providing a seamless experience for users regardless of their internet connectivity.
The skill also includes essential patterns for checking model availability and managing language model sessions. Developers can create single-turn or multi-turn sessions to maintain context in conversations, ensuring a more coherent interaction. The guided generation feature allows for defining structured types, enhancing the quality of generated data and ensuring it meets specific requirements. Additionally, the snapshot streaming capability enables developers to present partially generated results in real-time, enhancing user engagement and experience.
Overall, this skill is designed for developers looking to harness the power of on-device AI while prioritizing user privacy and data security. It is particularly suited for applications in domains such as personal assistants, content generation, and interactive user interfaces where real-time feedback is crucial.
When to use it
Use this skill when building AI features that require text generation, summarization, or data extraction on iOS devices.
When not to use it
Avoid this skill if your application needs extensive cloud-based processing or if you are targeting platforms other than iOS.
What you can build with it
Building a Personal Assistant
Develop a personal assistant app that generates responses to user queries using Apple's on-device language model.
Content Generation Tool
Create an app that summarizes articles or generates content based on user input without needing internet access.
Interactive Learning Application
Implement an educational app that extracts structured data from user inquiries, providing instant feedback and assistance.
How to install On-Device Foundation Models
View source1. Install with the skills CLI
npx skills add affaan-m/ecc/foundation-models-on-device --agent claude-code2. Or install it manually
Download the skill folder and drop it into ~/.claude/skills/ for all projects, or .claude/skills/ to scope it to one repo. Restart Claude Code so it picks up the new skill.
Anthropic's agentic coding CLI, and the reference implementation of Agent Skills. Drop a skill folder into ~/.claude/skills and Claude Code loads it automatically whenever a task matches the skill's description. Claude Code docs
Inside SKILL.md
Written by affaan-mFoundationModels: On-Device LLM (iOS 26)
Patterns for integrating Apple's on-device language model into apps using the FoundationModels framework. Covers text generation, structured output with @Generable, custom tool calling, and snapshot streaming — all running on-device for privacy and offline support.
When to Activate
- Building AI-powered features using Apple Intelligence on-device
- Generating or summarizing text without cloud dependency
- Extracting structured data from natural language input
- Implementing custom tool calling for domain-specific AI actions
- Streaming structured responses for real-time UI updates
- Need privacy-preserving AI (no data leaves the device)
Core Pattern — Availability Check
Always check model availability before creating a session:
struct GenerativeView: View {
private var model = SystemLanguageModel.default
var body: some View {
switch model.availability {
case .available:
ContentView()
case .unavailable(.deviceNotEligible):
Text("Device not eligible for Apple Intelligence")
case .unavailable(.appleIntelligenceNotEnabled):
Text("Please enable Apple Intelligence in Settings")
case .unavailable(.modelNotReady):
Text("Model is downloading or not ready")
case .unavailable(let other):
Text("Model unavailable: \(other)")
}
}
}
Core Pattern — Basic Session
// Single-turn: create a new session each time
let session = LanguageModelSession()
let response = try await session.respond(to: "What's a good month to visit Paris?")
print(response.content)
// Multi-turn: reuse session for conversation context
let session = LanguageModelSession(instructions: """
You are a cooking assistant.
Provide recipe suggestions based on ingredients.
Keep suggestions brief and practical.
""")
let first = try await session.respond(to: "I have chicken and rice")
let followUp = try await session.respond(to: "What about a vegetarian option?")
Key points for instructions:
- Define the model's role ("You are a mentor")
- Specify what to do ("Help extract calendar events")
- Set style preferences ("Respond as briefly as possible")
- Add safety measures ("Respond with 'I can't help with that' for dangerous requests")
Core Pattern — Guided Generation with @Generable
Generate structured Swift types instead of raw strings:
1. Define a Generable Type
@Generable(description: "Basic profile information about a cat")
struct CatProfile {
var name: String
@Guide(description: "The age of the cat", .range(0...20))
var age: Int
@Guide(description: "A one sentence profile about the cat's personality")
var profile: String
}
2. Request Structured Output
let response = try await session.respond(
to: "Generate a cute rescue cat",
generating: CatProfile.self
)
// Access structured fields directly
print("Name: \(response.content.name)")
print("Age: \(response.content.age)")
print("Profile: \(response.content.profile)")
Supported @Guide Constraints
.range(0...20)— numeric range.count(3)— array element countdescription:— semantic guidance for generation
Core Pattern — Tool Calling
Let the model invoke custom code for domain-specific tasks:
1. Define a Tool
struct RecipeSearchTool: Tool {
let name = "recipe_search"
let description = "Search for recipes matching a given term and return a list of results."
@Generable
struct Arguments {
var searchTerm: String
var numberOfResults: Int
}
func call(arguments: Arguments) async throws -> ToolOutput {
let recipes = await searchRecipes(
term: arguments.searchTerm,
limit: arguments.numberOfResults
)
return .string(recipes.map { "- \($0.name): \($0.description)" }.joined(separator: "\n"))
}
}
2. Create Session with Tools
let session = LanguageModelSession(tools: [RecipeSearchTool()])
let response = try await session.respond(to: "Find me some pasta recipes")
3. Handle Tool Errors
do {
let answer = try await session.respond(to: "Find a recipe for tomato soup.")
} catch let error as LanguageModelSession.ToolCallError {
print(error.tool.name)
if case .databaseIsEmpty = error.underlyingError as? RecipeSearchToolError {
// Handle specific tool error
}
}
Core Pattern — Snapshot Streaming
Stream structured responses for real-time UI with PartiallyGenerated types:
@Generable
struct TripIdeas {
@Guide(description: "Ideas for upcoming trips")
var ideas: [String]
}
let stream = session.streamResponse(
to: "What are some exciting trip ideas?",
generating: TripIdeas.self
)
for try await partial in stream {
// partial: TripIdeas.PartiallyGenerated (all properties Optional)
print(partial)
}
SwiftUI Integration
@State private var partialResult: TripIdeas.PartiallyGenerated?
@State private var errorMessage: String?
var body: some View {
List {
ForEach(partialResult?.ideas ?? [], id: \.self) { idea in
Text(idea)
}
}
.overlay {
if let errorMessage { Text(errorMessage).foregroundStyle(.red) }
}
.task {
do {
let stream = session.streamResponse(to: prompt, generating: TripIdeas.self)
for try await partial in stream {
partialResult = partial
}
} catch {
errorMessage = error.localizedDescription
}
}
}
Key Design Decisions
| Decision | Rationale |
|---|---|
| On-device execution | Privacy — no data leaves the device; works offline |
| 4,096 token limit | On-device model constraint; chunk large data across sessions |
| Snapshot streaming (not deltas) | Structured output friendly; each snapshot is a complete partial state |
@Generable macro | Compile-time safety for structured generation; auto-generates PartiallyGenerated type |
| Single request per session | isResponding prevents concurrent requests; create multiple sessions if needed |
response.content (not .output) | Correct API — always access results via .content property |
Best Practices
- Always check
model.availabilitybefore creating a session — handle all unavailability cases - Use
instructionsto guide model behavior — they take priority over prompts - Check
isRespondingbefore sending a new request — sessions handle one request at a time - Access
response.contentfor results — not.output - Break large inputs into chunks — 4,096 token limit applies to instructions + prompt + output combined
- Use
@Generablefor structured output — stronger guarantees than parsing raw strings - Use
GenerationOptions(temperature:)to tune creativity (higher = more creative) - Monitor with Instruments — use Xcode Instruments to profile request performance
Anti-Patterns to Avoid
- Creating sessions without checking
model.availabilityfirst - Sending inputs exceeding the 4,096 token context window
- Attempting concurrent requests on a single session
- Using
.outputinstead of.contentto access response data - Parsing raw string responses when
@Generablestructured output would work - Building complex multi-step logic in a single prompt — break into multiple focused prompts
- Assuming the model is always available — device eligibility and settings vary
When to Use
- On-device text generation for privacy-sensitive apps
- Structured data extraction from user input (forms, natural language commands)
- AI-assisted features that must work offline
- Streaming UI that progressively shows generated content
- Domain-specific AI actions via tool calling (search, compute, lookup)
Frequently asked questions about On-Device Foundation Models
Similar skills
Android App Development
Comprehensive guide for Android and cross-platform app development.
Add App Clip to Expo App
Integrate lightweight iOS App Clips into your Expo project.
APK Reverse
Streamline your Android APK reverse engineering process.
Swift Expert
Master iOS/macOS development with Swift and SwiftUI.
React Native Expert
Build and optimize mobile apps with React Native and Expo.
Kotlin Specialist
Master idiomatic Kotlin with expert patterns and practices.
