Build a private AI feature in Swift with Foundation Models, SwiftUI and App Intents
A production-focused Apple developer guide to Foundation Models, SwiftUI, App Intents, Swift Testing, privacy, evaluation, fallbacks, and accessible AI experiences.

- What Apple changed for developers
- 1. Design one focused user outcome
- 2. Build the SwiftUI model layer
- 3. Connect actions with App Intents
- 4. Test behavior, not phrasing
- 5. Treat availability as a product state
- 6. Prefer structured generation over fragile text parsing
- 7. Put strict trust boundaries around tools
- 8. Make App Intents useful outside the app
- 9. Build an evaluation dataset before tuning prompts
- 10. Design privacy and security into the data flow
- 11. Build accessibility into every generated state
- 12. Localize behavior, not only interface strings
- 13. Set a performance and energy budget
- 14. Observe failures without recording private prompts
- 15. Release checklist for a production team
- Official learning resources
- Final verdict
Apple's Foundation Models framework can place language-model features inside a native Swift application while App Intents exposes useful actions to system experiences. This guide shows a production-minded architecture with SwiftUI, structured output, privacy checks, testing, accessibility, and measurable fallbacks.
What Apple changed for developers
At WWDC26, Apple described new Foundation Models capabilities including additional model options, vision workflows, context management, semantic search, evaluations, and server-side paths. Review Apple's official session before adopting APIs because SDK names and availability can change.

1. Design one focused user outcome
Do not begin with a generic chatbot. Choose a task with a clear success condition: summarize release notes, classify feedback, extract structured fields, or propose a draft that the user reviews.
Final score
Pros
- Native Swift integration and system-aware experiences
- Privacy-preserving on-device paths where supported
- Structured generation, tools, sessions, and evaluation workflows
- App Intents can surface actions beyond the app interface
Cons
- Availability differs across devices, languages, and regions
- Generative output still requires validation and product safeguards
- New SDK capabilities can evolve between beta and final releases
2. Build the SwiftUI model layer
import FoundationModelsimport Observation @MainActor@Observablefinal class ReleaseNotesModel { private let session = LanguageModelSession() var summary = "" func summarize(_ notes: String) async throws { let response = try await session.respond( to: "Summarize these release notes for an iOS developer: \(notes)" ) summary = response.content }}A deliberately small model layer suitable for progressive enhancement.
3. Connect actions with App Intents
Use App Intents to describe actions and entities in a structured way so supported system experiences can discover them. Start from the official App Intents documentation , keep parameter summaries understandable, and avoid hiding essential confirmation steps.
4. Test behavior, not phrasing
Generated wording can change while the product requirement remains stable. Test required facts, prohibited content, structured constraints, cancellation, unavailable-model behavior, and the manual fallback.
import Testing@testable import DeveloperAssistant @Test("Generated summaries keep the essential migration warning")func summaryContainsMigrationWarning() async throws { let result = try await fixtureSummary() #expect(result.localizedCaseInsensitiveContains("migration"))}Swift Testing assertion focused on an essential product requirement.
| Concern | Preferred approach | Fallback |
|---|---|---|
| Privacy | On-device processing when available | Explicitly disclosed server path |
| Availability | Runtime capability checks | Deterministic non-AI workflow |
| Quality | Evaluation set and structured constraints | Human review and retry |
5. Treat availability as a product state
A model-powered feature should never be represented by a single enabled or disabled flag. Build an explicit state machine for supported, temporarily unavailable, restricted, downloading, failed, and fallback modes. That state belongs in the view model so SwiftUI can explain what is happening instead of presenting a spinner that never resolves.
import FoundationModels enum AssistantAvailability { case ready case unavailable(reason: String)} func assistantAvailability() -> AssistantAvailability { let model = SystemLanguageModel.default switch model.availability { case .available: return .ready case .unavailable(let reason): return .unavailable(reason: String(describing: reason)) }}Convert framework availability into a user-facing product state.
- Show the reason when a capability is unavailable, using plain language.
- Keep core navigation, saved data, and manual workflows usable without the model.
- Recheck availability when the app becomes active or relevant settings change.
- Log aggregate availability states without collecting prompt or private user content.
6. Prefer structured generation over fragile text parsing
Free-form text is useful for drafts, but product logic should consume constrained values whenever possible. Apple documents generation and task workflows in its Foundation Models guide . Define a small output contract, validate every field, and reject values that do not satisfy business rules.
For a release-note assistant, a useful contract might contain a short summary, affected platforms, migration urgency, required actions, and source citations. The UI can then render predictable sections, localize labels independently, and prevent generated prose from controlling navigation or permissions.
| Use case | Recommended output | Validation |
|---|---|---|
| Editorial draft | Constrained prose with citations | Length, source coverage, prohibited claims |
| UI fields | Typed structured output | Schema, ranges, enums, required fields |
| Search suggestions | Short ranked list | Deduplication, relevance, safe destinations |
| Destructive action | Never execute directly | Preview plus explicit user confirmation |
7. Put strict trust boundaries around tools
Tool calling can connect the model to calendars, local databases, network services, or app actions. Treat model-proposed arguments as untrusted input. Validate types and ranges, enforce authorization outside the model, rate-limit expensive operations, and require confirmation for purchases, deletion, publishing, messaging, or account changes.
- Expose the minimum tool surface needed for the current task.
- Return compact, typed tool results rather than entire private records.
- Separate read-only tools from tools that mutate data or contact other people.
- Record the tool name, result category, latency, and error class for debugging.
- Never place API keys, authentication tokens, or hidden policy text in prompts.
8. Make App Intents useful outside the app
App Intents can make a focused capability available to supported system experiences. Follow Apple's first App Intent guidance , provide localized titles and descriptions, keep parameters understandable, and return a result that remains useful when the full app interface is not visible.
import AppIntents struct SummarizeReleaseNotesIntent: AppIntent { static let title: LocalizedStringResource = "Summarize Release Notes" static let description = IntentDescription( "Creates a concise draft while preserving migration warnings." ) @Parameter(title: "Release notes") var notes: String func perform() async throws -> some IntentResult & ReturnsValue<String> { let summary = try await ReleaseNotesService.shared.summarize(notes) return .result(value: summary) }}A small App Intent that delegates business logic to a testable service.
The intent should not duplicate model orchestration. Keep prompting, validation, persistence, and telemetry in an application service that can also be called from SwiftUI and tests. This prevents different entry points from producing contradictory behavior.
9. Build an evaluation dataset before tuning prompts
A useful evaluation set represents the real distribution of inputs, including short notes, long notes, mixed languages, missing context, malformed text, sensitive data, and adversarial instructions. Store expected facts and unacceptable claims rather than one exact reference paragraph.
struct EvaluationCase: Codable { let id: String let input: String let requiredFacts: [String] let prohibitedClaims: [String]} func score(_ output: String, against test: EvaluationCase) -> Double { let required = test.requiredFacts.filter(output.localizedCaseInsensitiveContains) let violations = test.prohibitedClaims.filter(output.localizedCaseInsensitiveContains) let recall = Double(required.count) / Double(max(test.requiredFacts.count, 1)) return max(0, recall - Double(violations.count) * 0.25)}A deterministic scoring layer for required facts and prohibited claims.
- Keep a frozen regression set for every released version.
- Add failed real-world cases only after removing personal or confidential data.
- Compare the AI path with the manual fallback, not only with an earlier prompt.
- Track median, tail latency, cancellation rate, and fallback completion rate.
10. Design privacy and security into the data flow
Draw the complete data path before implementation: user input, app memory, local storage, model session, tools, analytics, crash reports, server calls, and deletion. Classify every field and decide which data must never leave the device. A privacy claim is credible only when the architecture and logging configuration enforce it.
| Data class | Default treatment | Required control |
|---|---|---|
| Public documentation | May be processed for the feature | Keep source and version metadata |
| Account data | Minimize and isolate | Purpose limitation and access control |
| Secrets and credentials | Never include in prompts | Keychain or server-side secret storage |
| Telemetry | Aggregate by default | Consent, retention limit, deletion process |
11. Build accessibility into every generated state
Generated content must remain readable with Dynamic Type, VoiceOver, increased contrast, reduced motion, keyboard navigation, and switch control. Announce meaningful state changes, keep focus stable when results arrive, and identify generated drafts as drafts. Never encode confidence using color alone.
- Use semantic headings and concise accessibility labels for generated sections.
- Let users pause media, animation, and automatic updates.
- Provide text alternatives and transcripts for images, audio, and video.
- Test the longest French and English strings at accessibility text sizes.
- Preserve selection and focus when a result is regenerated or rejected.
12. Localize behavior, not only interface strings
English and French versions need separate evaluation cases because names, dates, units, punctuation, terminology, and acceptable summaries differ. Keep the user language explicit in the request, use localized App Intent resources, and never silently translate private content through an undisclosed service.

Official Apple Developer learning material used to validate the implementation path.
13. Set a performance and energy budget
Measure cold start, time to first meaningful token, total completion time, memory pressure, cancellation, and battery impact on the oldest supported device. Debounce repeated requests, cancel work when the view disappears, cache only content that is safe to retain, and stream results only when progressive rendering improves comprehension.
14. Observe failures without recording private prompts
Operational dashboards should answer whether the capability was available, which version ran, whether validation passed, whether the user accepted the result, and whether the fallback completed. Use redacted error categories and synthetic test identifiers instead of raw prompts or generated responses.
- Availability rate by operating system, device class, language, and region.
- Validation failure and retry rate by feature version.
- P50, P95, and P99 latency plus user cancellation rate.
- Fallback completion rate and user-reported correction rate.
- Crash-free sessions and memory warnings around model operations.
A measured development loop
Transcript
Supporting visual: a developer workflow representing implementation, testing, measurement, and iteration. No spoken instruction is required to understand this media.
15. Release checklist for a production team
Before TestFlight
- Verify runtime availability on every supported device family.
- Run the frozen evaluation set in English and French.
- Test offline, cancellation, backgrounding and low-memory states.
- Review tool permissions and destructive-action confirmations.
- Audit analytics, retention and deletion behavior.
- Complete VoiceOver, Dynamic Type and reduced-motion checks.
- Confirm source links against the current SDK documentation.
Editorial rule: update this guide when Apple changes API names, availability or platform requirements.
Frequently asked questions
Can every supported iPhone run Foundation Models features?
No. Availability depends on the operating system, compatible hardware, language, region, Apple Intelligence state, and the specific model or capability. Check availability at runtime and provide a complete fallback.
Should generated text be stored automatically?
Usually not before validation and user review. Store only what the product requires, explain retention, protect sensitive fields, and give users a way to edit or delete saved results.
How should a team test nondeterministic output?
Test required facts, forbidden claims, schema validity, safety rules, latency, and fallback behavior across a representative dataset. Avoid comparing every response with one exact sentence.
When should an App Intent require confirmation?
Require explicit confirmation before destructive, financial, privacy-sensitive, publishing, messaging, or account-changing actions. Authorization and validation must live outside the model.
Official learning resources
Start with the Foundation Models documentation .
Review App Intents documentation for system integration.
Use Swift Testing documentation to build repeatable suites.
When an application requires another model provider, review Apple's provider integration session and disclose the resulting data path clearly.

A practical Mac for Xcode and Swift development
Check memory, storage, and current Xcode requirements before buying.
Production checklist
- Provide an accessible non-AI fallback.
- Test supported languages and regions.
- Measure latency, cancellation and failure states.
- Keep source links and an update log.
Final verdict
Our verdict
A strong native foundation when the fallback is equally well designed
Foundation Models, SwiftUI, App Intents, and Swift Testing form a credible Apple-native stack. The quality of the result still depends on narrow product scope, availability checks, evaluations, accessibility, and transparent data handling.
Community rating
8.8/10
How would you rate this verdict?
Community score 8.8/10 from 5 votes

Aya Mensah
Senior Editor · iPhoneAya has covered Apple since the original iPhone. She specialises in hands-on iPhone reviews and smartphone comparisons for African readers.
Continue reading

iPhone 18 Pro event preview: what Apple has confirmed for September 9, 2026
A source-first bilingual guide to Apple’s September 9, 2026 event, separating confirmed information from expectations and explaining how to verify iPhone 18 Pro pricing, availability and specifications by market.


iOS 26: every big new feature worth knowing before you update
From a redesigned lock screen to deeper Apple Intelligence, here is everything new in iOS 26 — and which iPhones support it.
0 comments
Loading…
Comments are submitted for moderation before publication.