Skip to main content
3Nsofts logo3Nsofts
App IntentsUpdated · June 2026

Making Your App Siri-Actionable in iOS 27: App Intents as the Entry Point, Not an Afterthought

Author
Ehsan Azish · 3NSOFTS
Updated
June 2026
Read time
15 min read
Level
Intermediate
Platform
iOS 27+, SwiftUI, App Intents framework

Implementation Notes

  • ~/ What broke: Siri, Spotlight, Shortcuts, and Widgets cannot act on app features that are not modeled as intents and entities.
  • ~/ What to do: Model app actions as App Intents, expose content as App Entities, donate usage, and return snippets for visual results.
App IntentsAppIntent schemaApp EntitySiri App Intents iOS 27App Shortcuts

In iOS 27, Siri becomes a primary way people reach into apps — and the only door it can walk through is the App Intents framework. If your app doesn't expose its actions and content as app intents and app entities, Siri, Spotlight, Shortcuts, and interactive Widgets simply can't act on it. Apple's own framing is blunt: make adopting App Intents a core feature of every app you create, not a late add-on. This guide is the practical path to doing it well.

The mental model: intents are actions, entities are content

App Intents has two primitives, and getting the split right is most of the battle:

  • An app intent is one of your app's actions — start a workout, send a message, open a URL, create a bookmark. It declares the data it needs as parameters and does the work in a perform() method.
  • An app entity is a lightweight, system-facing version of one of your data objects — a workout session, a message, a browser tab, a song. Your real data model stays the source of truth; the entity is a gateway the system can reference.

The design rule for intents: one intent per unique action, parameterized for variation. Don't write PlaySongIntent and PlayAlbumIntent — write one PlayMusicIntent with a parameter that specifies song or album. Parameters are how a single action covers many cases.

The design rule for entities: expose only the subset of your data that people actually see and manipulate in your interface, not your whole model.

Defining an app intent

Every app intent, custom or schema-based, conforms to AppIntent and provides a minimum set of behaviors: it performs an action in perform(), returns a result or error, declares its parameters, and supplies a localized title and descriptive info the system can display.

struct PlayMusicIntent: AppIntent {
    static let title: LocalizedStringResource = "Play Music"

    @Parameter(title: "Item")
    var item: MediaEntity            // a song or album, as an app entity

    func perform() async throws -> some IntentResult {
        try await MusicPlayer.shared.play(item)
        return .result()
    }
}

perform() is async throws: return a result on success, throw to tell the system the action failed. The localized title and descriptions aren't optional polish — they're what Siri and Shortcuts display, so write them as user-facing copy.

Prefer built-in domain schemas over hand-rolled intents

This is the highest-leverage decision in the whole framework. The App Intents framework ships predefined schemas for actions and data types common across apps — music, email, and many more domains. When you use the AppIntent(schema:) macro and pick a domain schema, Xcode code completion generates the initial intent code including expected parameters, and — critically — Apple Intelligence and Siri AI work better for intents that conform to a known schema.

// Schema-based: the macro scaffolds the expected shape, and Siri understands it natively.
@AppIntent(schema: .playback.play)   // illustrative — use the actual domain schema for your app type
struct PlayMediaIntent: AppIntent {
    // Xcode completion fills in the schema's expected parameters.
}

Confirm the exact schema identifiers for your app's domain against the current SDK — the available schemas and their names evolve. The principle is stable: if a built-in schema fits your action, use it instead of a custom intent, because the system reasons about schema-conformant intents far better than bespoke ones.

The same applies to entities: AppEntity(schema:) scaffolds entities for common data types, and domain schemas define the properties the system expects.

Defining an app entity

An app entity conforms to AppEntity and carries: a unique identifier your app can use to find the underlying data, a query object so the system can locate instances, properties for key variables, and descriptive info to display.

struct MediaEntity: AppEntity {
    static let typeDisplayRepresentation: TypeDisplayRepresentation = "Media"

    let id: UUID
    @Property(title: "Title") var title: String

    static var defaultQuery = MediaQuery()
    var displayRepresentation: DisplayRepresentation { .init(title: "\(title)") }
}

The query object is what makes conversational requests resolve automatically. If someone asks Siri about "the workout from this morning," the system runs your entity's query to find the matching entity by name or value — you don't write that resolution logic, you provide the query and the system uses it.

One requirement that's easy to miss: make your entity types transferable (via Core Transferable) so they can be exchanged with other processes. Entities cross process boundaries; transferability is what lets them.

For finite option sets — sizes, statuses, RSVP states — use an app enum (AppEnum, String-backed, RawRepresentable) whose job is to give the system human-readable descriptions of each option so it can present them in system UI.

Foreground vs background execution

Many intents don't need your app on screen. Rather than launching the app every time, you can run intents in the background via an app extension, which minimizes disruption when another app is foregrounded (especially on iPhone, iPad, Apple TV, Vision Pro, and Watch).

Configure each intent's supportedModes to express foreground/background preferences. The pattern that scales: put shared intent code in a Swift package used by both your app and its app extension, so an intent can run in the background but transition to the foreground when it needs to present UI or ask for the user's attention.

Note the exception: some intents must run in the foreground and will auto-launch your app — for example, OpenIntent, which exists to launch the app and display a specific item. Keep that code in the app itself, not the extension.

App Shortcuts: the polished surface

Intents alone are usable; App Shortcuts make them feel native. An App Shortcut pairs an intent with extra data — notably the spoken phrases that trigger it in Siri. Conform a type to AppShortcutsProvider and create an AppShortcut per intent; the compiler extracts them and makes them available to Shortcuts and the rest of the system. Give each a localized title and description.

This is the difference between "the action exists" and "the user can say a natural phrase and it just works."

Donations make the system smarter

When someone runs an intent through Shortcuts or Siri, the system collects it to improve future suggestions. You should donate the same intents when the user performs those actions through your own UI — that gives the system a complete picture of what the user cares about and sharpens its suggestions.

Donate entities too. When indexing content with Core Spotlight, include app entities so the system knows where your data lives. And attach the relevant entity to the view currently showing it — if your music UI is displaying a song, attach that song's entity to the view, so "play this song" resolves from on-screen context without Siri asking which song.

Snippets for visual results

When Siri or Shortcuts surface an intent's result and the user is looking at their screen, a snippet — SwiftUI views you build programmatically and return from perform() — gives a richer result than spoken text alone. Snippets can also request confirmation for a value before acting. Return one from perform() and features like Siri can display it.

Production checklist

  • Treat App Intents as a core feature — in iOS 27 it's the gateway to Siri/Spotlight/Shortcuts/Widgets.
  • One intent per action, parameterized — never near-duplicate intents.
  • Prefer AppIntent(schema:) / AppEntity(schema:) — Siri reasons about schema-conformant types far better.
  • Give every entity a query object so conversational requests resolve automatically.
  • Make entities transferable (Core Transferable) — they cross processes.
  • Use supportedModes + a shared Swift package to run intents in the background, foreground only when needed.
  • Donate intents and entities from your own UI, and attach entities to the views showing them.
  • Return snippets for visually engaging results and confirmations.

Why this matters for shipped apps

For years App Intents was optional polish — nice for Shortcuts power users. In iOS 27 it's the integration layer: the richness of your intents and entities directly determines how much of your app Siri can actually drive. An app with thin or no App Intents support is invisible to the new Siri; an app with well-modeled, schema-conformant intents and queryable entities becomes something users can operate by voice and from system surfaces without ever opening it. That's a distribution and engagement advantage, and it's earned at the architecture level.

If you're modeling your app's actions and content for the new Siri surface and want the intent/entity architecture designed to scale, that's core to our Apple platform work at 3NSOFTS.

Authoritative References