← Back to tech blog

How to Build an iOS 27 AI App: Foundation Models to App Intents

iOS 27 AI app flow from Foundation Models sessions to App Intents and Siri AI
Design the loop first: on-device session, tools, then App Intents for Siri AI.

As of 14 September 2026, iOS 27 is in the fall ship window. An “iOS 27 AI app” is not another hosted chat box. Apple’s developer path is two rails: Foundation Models to plan, extract, and call tools inside your process; App Intents so the same actions show up in Siri AI, Spotlight, and Shortcuts. Design the loop first, then pick a model—on-device, Private Cloud Compute, and third-party LLMs share one Swift session API, but review, privacy copy, and regional availability do not.

What an iOS 27 AI app actually is

Plenty of teams still define “AI feature” as a text field that forwards a sentence to OpenAI or Gemini and pastes the reply. That still compiles on iOS 27. It is no longer the shape Apple is shipping toward. WWDC 2026 was blunt: system models, Siri AI, and partner models should enter the app through a Foundation Models session; anything the user starts from Lock Screen, Siri, or on-screen content should go through App Intents—not a leftover SiriKit extension.

In product language: Foundation Models “figures it out” (natural language → typed draft, tool calls, local vs cloud swap). App Intents “does the thing” (create a task, open an entity, edit a record, let Siri say “the third one”). A chat UI is only one skin. Chat without Intents is invisible to Siri. Intents without a session layer make in-app planning and multi-turn edits brittle.

This piece is a build guide, not a consumer feature tour. Pricing and free-vs-paid limits live in Apple Intelligence pricing: free vs paid. What Siri can do on a Mac is in Siri AI on Mac (macOS 27). Below is the engineering path from a blank target to a loop you can demo, test, and submit.

One line: iOS 27 AI app = session layer (Foundation Models) + action layer (App Intents).

Before code: Xcode 27, device tiers, regions

Pin the toolchain before the first import FoundationModels. The iOS 27 SDK ships with Xcode 27. The simulator is fine for session plumbing. Private Cloud Compute, real tool-call rates, and speech-heavy paths often diverge on device. Apple’s iOS 27 release notes already call out PCC gaps in Simulator and excessive tool calling when you mix on-device tools with guided generation. Budget calendar time for that—it is not trivia.

Do not plan AI on “devices that install iOS 27.” iPhone 11 and later get the OS. Apple Intelligence and on-device Foundation Models still start at iPhone 15 Pro / iPhone 16. The heavier on-device stack (often described as AFM 3 Core Advanced—expressive Siri voice and higher-accuracy dictation) sits mainly on iPhone 17 Pro / Air. iPad is roughly M1 for Apple Intelligence, with newer on-device models needing more RAM. Write three rows, not one “min iOS 27” cell:

TierTypical hardwareWhat you can promise
OS only, no Apple IntelligenceiPhone 11–15 (non-Pro)Do not make AI the critical path; degrade or use your own cloud
Standard Apple IntelligenceiPhone 15 Pro, iPhone 16 familyOn-device sessions, baseline Siri AI, most App Intents
Full on-device modeliPhone 17 Pro / Air classSample advanced speech and heavier local inference—never claim it for every user

Region is the second gate. Siri AI and some system features can still be blocked by account, language, or regulation—most visibly in mainland China and parts of the EU under DMA-era constraints. US/UK teams should still ship a kill switch: keep App Intents stable, and make the Foundation Models backend swappable so an EU build can sit on a partner LanguageModel while a US build prefers on-device + PCC. Do not record App Store previews on a US Apple ID and caption them as global Siri AI.

Keep Xcode 27 off the same laptop that owns your stable App Store train. Split “gold” CI from the SDK-27 scratch machine. The same isolation idea is in Xcode beta vs production runner isolation.

Foundation Models: one API, three placements

Foundation Models arrived in iOS 26. iOS 27 turns it into a single native Swift API: on-device models take image input, a session can target server models, and you can attach custom Skills. Apple’s recap is in the June 2026 Newsroom post. The real decision is not “AI: on/off.” It is where this inference runs.

PlacementTypical typeUse it forDo not use it for
On-deviceSystemLanguageModelSummaries, rewrite, form extract, short plans, offline draftsHuge docs, open-web Q&A that needs live retrieval
Apple cloudPrivate Cloud Compute modelsHeavier reasoning without bringing your own keysData that must stay in your VPC with your auditors
Partner / customLanguageModel + LanguageModelExecutorClaude, Gemini, MLX, Core AIRaw API keys in a client initializer

The iOS 27 change that matters: swapping models should not rewrite the session. Providers implement public protocols (WWDC26 session Bring an LLM provider to the Foundation Models framework), ship a Swift package, and map Transcript entries in the executor—including prewarm, streaming, and KV cache. Your app still talks to LanguageModelSession.

Cost has a new lever: developers in the App Store Small Business Program with under two million first-time downloads can use the next-generation Apple Foundation Models on Private Cloud Compute without a cloud API bill (confirm current terms). That is a trial ramp, not infinite inference. Above the cap—or if you need Claude/Gemini—you pay the provider.

Rule of thumb: stay on-device when you can; leave the device via PCC next; add a third-party executor only when PCC is weak or unavailable in that storefront.

Step 1: LanguageModelSession and structured output

The session is the spine. See LanguageModelSession: one object holds a Transcript; blow the window and you get LanguageModelError.contextSizeExceeded. Do not allocate a new session on every Send. Do not append forever either. Short sessions for planning, a fresh one for commit, beats a single god-object chat.

Minimum useful path: a typed draft, not free prose
import FoundationModels

@Generable
struct TaskDraft {
    @Guide(description: "Task title, max 20 characters")
    var title: String
    @Guide(description: "ISO-8601 due date, or none if the user omitted it")
    var dueISO8601: String
    var priority: Priority
}

@Generable
enum Priority {
    case low, normal, high
}

let session = LanguageModelSession {
    """
    You are the planner inside a to-do app.
    Emit TaskDraft only. Never invent calendar events the user did not mention.
    """
}

let response = try await session.respond(
    generating: TaskDraft.self,
    to: Prompt("File the weekly report by 3pm tomorrow, high priority")
)
let draft = response.content

The product win is the type, not the syntax. @Generable turns “a model that chats” into “a model that fills a form.” SwiftData, an App Intent, or the next planning turn all consume a value—not Markdown you re-parse. Release notes also warn that @Generable on an enum can emit a sticky GenerationError warning. Check the notes before you debug your store.

Use image input for receipts, shelf SKUs, and on-screen objects—not an entire photo library. When the window fills, drop old tool payloads first, not the current user turn.

Step 2: Tools, Skills, Dynamic Profiles

Structured output is not enough. The model must touch your domain. A Foundation Models Tool is not automatically an App Intent. Tools serve the session; Intents serve the system. Share a Store. Do not assume “we shipped an Intent, therefore the model can see it.”

iOS 27 adds Dynamic Profiles for multi-phase agents. WWDC26 session Build agentic app experiences walks a craft app through brainstorm / plan / review: the same session can swap model, temperature, and reasoning depth—PCC + deeper reasoning for planning, on-device for review. The profile body re-evaluates on each prompt, so keep I/O out of it.

Same session, phase-specific model and tools (sketch)
enum PlanPhase { case brainstorm, plan, review }

func makeProfile(_ phase: PlanPhase) -> LanguageModelSession.DynamicProfile {
    LanguageModelSession.DynamicProfile {
        switch phase {
        case .brainstorm, .plan:
            return .init(model: .privateCloudCompute, tools: [SearchNotesTool(), ListCalendarTool()])
        case .review:
            return .init(model: SystemLanguageModel.default, tools: [ValidateDraftTool()])
        }
    }
}

Two performance traps. Rewriting transcript history invalidates KV cache and latency jumps—append when you can. On-device models can spam tools when guided generation and tools are combined; cap consecutive calls and stop after repeated failures. Use the Foundation Models Instrument plus 20–30 real utterances before you treat a keynote-style demo as coverage.

Skills are for tone, banned terms, and domain dictionaries you want ops to edit without a resubmit. They are not a second backend. They stay inside the session boundary and share the same audit rules as Tools.

Step 3: App Intents for Siri AI

App Intents are not “a Shortcuts extra.” On iOS 27 they are the only supported door from Siri into a third-party app. SiriKit was deprecated at WWDC 2026 with a roughly two-to-three-year runway. Migrating a live SiriKit surface outranks polishing chat copy. Start from AppIntent.

Use this generation’s Intents on purpose: system schemas for open/create/search instead of cute unique titles; on-screen awareness so Siri can resolve “this” and “the third one”; streaming or long-running results; multi-turn parameter fill. Index entities with IndexedEntity when Spotlight should see them. Visual Intelligence search uses SemanticContentDescriptor and IntentValueQuery—not a jammed LanguageModelSession.

An Intent Siri and Shortcuts can both invoke
import AppIntents

struct CreateTaskIntent: AppIntent {
    static var title: LocalizedStringResource = "Create Task"
    static var description = IntentDescription("Save a to-do in the app.")

    @Parameter(title: "Title")
    var title: String

    @Parameter(title: "Priority")
    var priority: String?

    func perform() async throws -> some IntentResult & ProvidesDialog {
        try await TaskStore.shared.create(title: title, priority: priority ?? "normal")
        return .result(dialog: "Created \(title)")
    }
}

Split human copy from the machine contract: title / description are for Siri and the Shortcuts gallery; perform() should be idempotent and auditable. Destructive work needs an explicit confirm. If a parameter cannot be resolved, let the system ask again—do not let the model improvise a dialog that writes data.

Wire the model to an Intent

Default architecture: the model drafts, the Intent commits.

  1. The user speaks or types in-app, or Siri arrives with a natural-language phrase.
  2. LanguageModelSession emits a @Generable draft, calling Tools to read calendar, notes, or inventory first if needed.
  3. UI shows the draft. The user confirms—or you auto-confirm only low-risk shapes.
  4. Build the matching AppIntent and perform(). The same Store serves Shortcuts and Spotlight.
  5. Write the result back into the Transcript as tool output so the next edit is not a cold start.
Commit only after confirm—never let the model write the store
func commit(_ draft: TaskDraft) async throws {
    var intent = CreateTaskIntent()
    intent.title = draft.title
    intent.priority = String(describing: draft.priority)
    _ = try await intent.perform()
}

Why not let a Tool insert rows? App Review, the Shortcuts gallery, Siri suggestions, and your undo stack all understand Intents. A hallucinated due date is cheap if UI can block it. It is expensive if a Tool already created ten reminders.

Keep model swaps in a session factory. Put region switches there too: a US build can prefer on-device + PCC; an EU or CN build can default to a reviewed partner executor. The Intent stays CreateTaskIntent either way.

Test, privacy, App Review checklist

AI features fail review and support more often than ordinary CRUD. Walk this table before you flip GA:

CheckHowFail = not GA
No Apple IntelligenceiPhone 15 non-Pro or AI disabledBlank critical path or crash
PCC unavailableSimulator, Airplane Mode, signed outInfinite spinner, no fallback
Region / languageCN Apple ID, EU account, non-English localeCopy promises system Siri that is not there
Hallucinated writesVague prompt + baited due datesCalendar or payments without confirm
SiriKit leftoversOld path still compiles“We’ll migrate later” as the plan
SecretsSearch the IPA for sk- / provider keysThird-party keys in the client

Privacy strings must match the bits. On-device can say “stays on the phone.” PCC or a partner model must be named in Settings. Provider docs want Keychain (and often App Attest)—not a key in the session initializer. Log draft schemas and Intent IDs, not full transcripts, to your analytics host.

For review, pack three artifacts: a 30-second “speak → draft → confirm → row appears” capture in the same locale as the screenshots; a written degrade path for non-Intelligence hardware; a one-page model-placement table (on-device / PCC / partner). Keep marketing inside the envelope in the WWDC 2026 Siri AI guide.

If every engineer’s laptop is also the Xcode 27 box, the device matrix, and the nightly eval host, orchestration will cost more than tokens. A always-on Apple Silicon node is usually cheaper than a fleet of new notebooks.

Keep the iOS 27 AI loop on a cloud Mac mini

Foundation Models sessions, Simulator, device proxies, and the Xcode 27 toolchain all want RAM, SSD, and a machine that does not sleep. A Nuvcloud Mac mini is dedicated Apple Silicon bare metal: unified memory for compile + local evals, SSH that stays up, and a box you can rent by the day for the iOS 27 SDK instead of fighting Slack and Figma on the same lid.

If LanguageModelSession and App Intents are about to become a daily regression, check Nuvcloud plans and regions and keep the builder online—close the laptop without closing the session.

Further reading

FAQ

Can I ship an iOS 27 AI app without Swift?

The supported Foundation Models and App Intents path is Swift. Flutter or React Native can still own UI, but the session, Tools, and Intents belong in a native module. Otherwise Siri AI and on-device models will not see you.

How is Foundation Models different from calling the ChatGPT API?

Foundation Models is a system session API: on-device, PCC, or a protocol-backed partner, with Tools, guided generation, and system privacy prompts. A raw ChatGPT call is your HTTPS. It is flexible, but you lose on-device models and Siri distribution, and you own keys and review risk.

Do App Intents become model Tools automatically?

No. Intents are for Siri, Shortcuts, and suggestions. Tools are for LanguageModelSession. Share one Store; do not wait for a magic bridge.

Does Foundation Models work in mainland China?

It depends on device, system language, and Apple ID region. System Apple Intelligence / Siri AI may still be unavailable on mainland iPhones. Treat system models as optional and keep a compliant partner LanguageModel so the critical path is never empty.

Is Private Cloud Compute mandatory?

No. Short summaries, form extract, and local drafts should stay on-device. Step up to PCC when quality is not enough and you accept Apple’s PCC boundary. Small Business Program eligibility may waive PCC cloud API fees—re-read the current terms.

How long will SiriKit keep working?

Deprecated at WWDC 2026, with a commonly cited two-to-three-year compatibility window. Do not add new SiriKit surfaces. Schedule the migration inside the iOS 27 train, before warnings become hard errors.

Is Simulator enough for App Review?

No. PCC, some tool-call behavior, and speech paths differ on device. Keep at least one standard Intelligence handset; sample the top tier separately. Do not represent every user with a 17 Pro screen recording.

Do we have to buy new Macs for Xcode 27?

Not necessarily new office laptops. You need Apple Silicon that can run the iOS 27 SDK without sleeping. Many teams rent a cloud Mac mini to split beta builds from production CI instead of refreshing every desk.

Limited offer →