app-intents · v1.3.0 · 2026-10-28 · sha256 72c32a25def29dad
app-intents v1.3.0A
Immutable. This exact content never changes and is served at /api/v1/blob/72c32a25def29dad.
---
name: app-intents
description: Use when adding AppIntent, AppEntity, OpenIntent, AppShortcutsProvider, EntityQuery, Focus Filters, AssistantEntity/AssistantIntent schemas, on-screen awareness, LongRunningIntent/CancellableIntent, EntityCollection, SyncableEntity, AppIntentsTesting, or when wiring SwiftData/networked data into…
license: MIT
metadata:
author: Anton Novoselov
version: 1.3.0
---
Write and review Swift code that exposes app functionality through the App Intents framework, ensuring correct protocol conformance, safe data flow, and idiomatic discoverability wiring.
Review process:
1. Check intent fundamentals (protocol, `perform()`, return types, dialog) using `references/fundamentals.md`.
1. Validate parameters and parameter options using `references/parameters.md`.
1. Validate entity types, display representations, and queries using `references/entities.md`.
1. Check the `AppShortcutsProvider` registration and discoverability UI using `references/shortcuts-and-siri.md`.
1. Validate `OpenIntent` navigation and snippet view return types using `references/open-and-snippet-intents.md`.
1. Check dependency injection and the data-controller pattern using `references/dependencies.md`.
1. Validate Spotlight indexing via `IndexedEntity`, `IndexedEntityQuery`, and attribute sets using `references/spotlight.md`.
1. Check `@AssistantEntity` / `@AssistantIntent` schema adoption using `references/assistant-schemas.md`.
1. Validate the Siri / Apple Intelligence integration (finding content, custom responses, donations, confirmation, ownership) using `references/siri-intelligence.md`.
1. Check on-screen awareness and content transfer (view annotations, `IntentValueRepresentation`, system-integration annotations) using `references/onscreen-awareness.md`.
1. For intents that run past 30 seconds, handle cancellation, or target a specific process, use `references/long-running-and-execution.md`.
1. If writing or reviewing tests for intents, use `references/testing-intents.md` (covers the new `AppIntentsTesting` framework).
1. Catch common mistakes using `references/anti-patterns.md`.
If doing partial work, load only the relevant reference files.
## Task-based routing
Match the user's goal to the read order. Load only what you need.
### "Create my first App Intent"
1. `references/fundamentals.md` - protocol, `perform()`, return types
2. `references/shortcuts-and-siri.md` - register it so it shows up
### "Add a parameter the user picks in Shortcuts"
1. `references/parameters.md` - `@Parameter`, prompts, disambiguation
2. `references/entities.md` - if the parameter is a domain entity
### "Make my app's data searchable from Siri / Spotlight"
1. `references/entities.md` - `AppEntity`, `IndexedEntity`, `@Property`
2. `references/spotlight.md` - indexing strategies, attribute sets
3. `references/shortcuts-and-siri.md` - flexible matching, phrase rules
### "Show a summary / interactive view when Siri runs my intent"
1. `references/open-and-snippet-intents.md` - inline vs indirect snippets, `SnippetIntent`, `Button(intent:)`
2. `references/fundamentals.md` - return types and snippet design rules
### "Open a specific thing in my app from Siri / Shortcuts"
1. `references/open-and-snippet-intents.md` - `OpenIntent`, `URLRepresentableIntent`, `TargetContentProvidingIntent`
2. `references/dependencies.md` - navigator / scene routing
### "Bring my app's content and actions to Siri / Apple Intelligence"
1. `references/siri-intelligence.md` - the integration model, finding content (semantic index / structured search / in-app search), custom responses, donations, confirmation/ownership
2. `references/assistant-schemas.md` - schema macros, domains, multi-schema requirements, Xcode snippets
3. `references/onscreen-awareness.md` - view annotations, content transfer, system-integration annotations
### "Integrate with Apple Intelligence"
1. `references/assistant-schemas.md` - schema macros, domains, Use Model action, onscreen content
2. `references/entities.md` - `@Property`, `Transferable` (required for several schemas)
### "Let Siri understand what's on screen"
1. `references/onscreen-awareness.md` - the 4 annotation APIs, content transfer, `displayRepresentations` fast path, annotations on notifications/Now Playing/AlarmKit
2. `references/siri-intelligence.md` - how onscreen context fits the larger Siri story
### "Make my intent run longer than 30 seconds or target a process"
1. `references/long-running-and-execution.md` - `LongRunningIntent`, `CancellableIntent`, `allowedExecutionTargets`, background GPU
2. `references/fundamentals.md` - `ProgressReportingIntent`, `supportedModes`
### "Handle large numbers of entities efficiently / sync across devices"
1. `references/parameters.md` - `EntityCollection` (identifiers-only parameters)
2. `references/entities.md` - `SyncableEntity` for cross-device identity, `RelevantEntities` for proactive suggestions
### "Support Visual Intelligence / image search"
1. `references/assistant-schemas.md` - `IntentValueQuery`, `SemanticContentDescriptor`, `@UnionValue`
2. `references/entities.md` - `Transferable` + `OpenIntent` pairing
### "Build an interactive widget or Control Center control"
1. `references/open-and-snippet-intents.md` - `Button(intent:)`, `WidgetConfigurationIntent`, `ControlConfigurationIntent`, `ControlWidgetButton`
2. `references/dependencies.md` - App Group shared storage, process boundaries
### "Structure my app around App Intents"
1. `references/fundamentals.md` - intents as canonical action layer
2. `references/dependencies.md` - `@Dependency`, cross-module `AppIntentsPackage`
3. `references/entities.md` - entity-as-bridge pattern
### "Test my App Intents"
1. `references/testing-intents.md` - the `AppIntentsTesting` framework (out-of-process integration), direct struct unit tests, mocking `@Dependency`, test-only intents, what you can't test
### "I'm hitting build errors or runtime bugs"
1. `references/anti-patterns.md` - 35+ catches with before/after fixes
## Decision trees
Quick orientation when you know the task but not the right API.
### Which intent protocol should I conform to?
```
Generic action?
→ AppIntent
Opens the app to a specific entity?
→ OpenIntent (+ TargetContentProvidingIntent on iOS)
→ on iOS 27+, @AppIntent(schema: .system.open) on the OpenIntent, with a legacy sibling intent for older OS
Renders an interactive view only, no business logic?
→ SnippetIntent
Needs to bring the app forward conditionally?
→ AppIntent with supportedModes (iOS 26+)
→ or ForegroundContinuableIntent (iOS 17-18)
Runs longer than 30 seconds (upload, sync, inference)?
→ LongRunningIntent + performBackgroundTask (iOS 27+)
Needs to clean up gracefully when cancelled (with the reason)?
→ CancellableIntent + withIntentCancellationHandler (iOS 26.4+)
Deletes entities with standard confirmation?
→ DeleteIntent
Routes a search query into the app?
→ ShowInAppSearchResultsIntent
Backs widget configuration?
→ WidgetConfigurationIntent (empty conformance, no perform)
Backs a Control Center control?
→ ControlConfigurationIntent
Has a universal-link URL representation?
→ URLRepresentableIntent + OpenIntent (no perform needed)
Matches an Apple Intelligence domain?
→ AppIntent + @AppIntent(schema: .domain.action)
```
### Which entity type should I use?
```
Fixed set known at compile time?
→ AppEnum
Dynamic data with a persistent id?
→ AppEntity
Entity must appear in Spotlight?
→ AppEntity + IndexedEntity
Entity IS a file (scan, voice memo, exported image)?
→ FileEntity
Computed / aggregated data with no stable id?
→ TransientAppEntity
Needs Apple Intelligence schema awareness?
→ AppEntity + @AppEntity(schema: .domain.type)
Supports cross-app sharing?
→ AppEntity + Transferable
```
### Which query should my entity use?
```
Small fixed set, enumerable?
→ EnumerableEntityQuery (also gets a basic Find intent)
Large dataset, searchable by name?
→ EntityQuery + EntityStringQuery
Many queryable properties, user should build predicates?
→ EntityPropertyQuery (auto-generates Find intent with comparators + sort)
Simple id-only lookup, no search?
→ UniqueIDEntityQuery
Indexed in Spotlight and want reindexing support?
→ IndexedEntityQuery (iOS 27+)
Structured Siri search you can't index ahead of time?
→ IntentValueQuery (structured input, returns 1+ entity types via @UnionValue)
Visual intelligence / image search?
→ IntentValueQuery + SemanticContentDescriptor
```
### How should Siri find my content?
```
Content is local and indexable?
→ IndexedEntity + indexAppEntities (semantic index) - the primary path
→ add IndexedEntityQuery for reindexing support (iOS 27+)
Too large / server-side / too volatile to index?
→ IntentValueQuery (structured search input)
User wants to search inside your own UI?
→ @AppIntent(schema: .system.searchInApp) + ShowInAppSearchResultsIntent
Content nobody has found or used yet, but relevant right now?
→ RelevantEntities.updateEntities(_:for:) (iOS 27+)
Teach the system how people use the app (patterns)?
→ IntentDonationManager (donate UI interactions)
```
### Which property wrapper should I use on entity fields?
```
Stored on the entity struct, should appear in Shortcuts/Find/summary?
→ @Property
Derived from an underlying model object (cheap to compute)?
→ @ComputedProperty (preferred over @Property for wrappers around models)
Derived AND should be indexed in Spotlight?
→ @ComputedProperty(indexingKey: \.keyName)
Expensive to compute (network, ML inference, heavy query)?
→ @DeferredProperty (async getter, only runs when system asks)
Internal to the entity, not shown anywhere?
→ plain stored property (no wrapper)
```
## Core Instructions
- Target iOS 16+ / macOS 13+ minimum for App Intents. `IndexedEntity`, `OpenIntent`, focus filters, and control widgets require iOS 16+; `@AssistantEntity` / `@AssistantIntent` schemas require iOS 18.2+; anchored relative date styles and many assistant schemas require iOS 18.4+. The **27 releases** (WWDC 2026, iOS 27 / macOS 27) add `LongRunningIntent`, `EntityCollection`, `SyncableEntity`, `RelevantEntities`, `IndexedEntityQuery`, `OwnershipProvidingEntity`, `allowedExecutionTargets`, the `AppIntentsTesting` framework, and native `Duration`/`PersonNameComponents` parameters; `CancellableIntent` and `IntentValueRepresentation` are iOS 26.4+; `supportedModes` is iOS 26+. Apple's own naming for the WWDC 2026 cohort is "the 27 releases" - use that, not "iOS 19".
- **Never** make a SwiftData `@Model` class or other reference-type data model conform to `AppEntity`. `AppEntity` requires `Sendable`; `@Model` classes are not sendable. Create a separate `struct` entity that shadows the fields you want to expose.
- **Never** pass `ModelContext` across actor boundaries. `ModelContext` is not sendable. Pass `ModelContainer` (which is sendable) and create a local context inside the actor that needs one.
- **Never** expose an intent to Siri/Spotlight only by writing its type, always register it through an `AppShortcutsProvider`. Types not registered there will not appear in Shortcuts, Siri suggestions, or the action button picker.
- **Never** write a Siri activation phrase without interpolating `\(.applicationName)`. The App Intents macro rejects phrases without it at compile time, because phrases without the app name would collide with other apps' commands.
- **Never** reach back into a SwiftUI `@Query` from inside an intent. `@Query` only works inside a `View`. Run a one-shot `FetchDescriptor` through a `ModelContext` instead, or route through a centralized data controller.
- **Never** instantiate services, data stores, or authentication managers inside `perform()`. Inject them through `@Dependency` and register them once in `App.init()` with `AppDependencyManager.shared.add(dependency:)`.
- **Never** use `String(format:)` or manual concatenation for localized intent dialog. Use `LocalizedStringResource`, and use Foundation's grammar-agreement markdown (`^[\(count) item](inflect: true)`) inside an `AttributedString` for pluralization.
- When an intent can fire before the app's store / navigation exists (cold launch, splash, store built in the root view), dispatch through a main-actor router that queues the action until the UI attaches, and send Spotlight `CSSearchableItemActionType` user activities through the same action. See `references/open-and-snippet-intents.md`.
- Prefer `OpenIntent` for "take me to this thing" actions, `AppIntent & ShowsSnippetView` for self-contained one-shot summaries, and `AppIntent & ShowsSnippetIntent` + a paired `SnippetIntent` when the snippet contains `Button(intent:)` and needs to re-render after buttons fire.
- Always set `static let isDiscoverable: Bool = false` on helper intents that only back a widget button, snippet button, or other intent - otherwise they pollute the user's Shortcuts library.
- When an intent mutates data that widgets or control widgets display, call `WidgetCenter.shared.reloadAllTimelines()` inside `perform()` before returning.
- When `Button(intent:)` lives inside a widget view, share state between the intent (runs in the app process) and the widget's timeline provider (runs in the extension process) via App Group `UserDefaults(suiteName:)` or a shared `ModelContainer` URL - never `UserDefaults.standard` or in-memory `@Dependency` state.
- When entity data that appears in a shortcut phrase's key path changes (creation, rename, deletion), call `YourShortcutsProvider.updateAppShortcutParameters()` to invalidate the cached candidate list.
- Prefer `EnumerableEntityQuery` when the whole set is small and cheap to load; implement `EntityQuery` + `EntityStringQuery` when the dataset is large or searchable; add `EntityPropertyQuery` to get a system-generated Find intent for free. `entities(for identifiers:)` is mandatory on every query; without it, parameter resolution breaks.
- Mark entity fields that users might filter, sort, or reference in parameter summaries with `@Property` (stored) or `@ComputedProperty` (derived). Plain stored properties are invisible to the App Intents framework.
- Use `TransientAppEntity` for return data that's computed on the fly (summaries, aggregates). Don't try to shoehorn it into `AppEntity` with a fake id.
- When the entity already has a universal-link URL, conform it to `URLRepresentableEntity` and conform the open intent to `URLRepresentableIntent` - the system routes opens through your existing link handler without a `perform()`.
- For entities visible onscreen that Siri should be able to understand, combine `.userActivity(_:element:)` on the view with `Transferable` conformance on the entity. Identification alone is not enough; Siri needs exportable content.
- `SnippetIntent.perform()` is called multiple times per user interaction (initial show, after each button tap, on appearance changes, on `reload()`). Keep it pure: read state, assemble the view, return. Never mutate app state or kick off slow work inside a snippet intent's `perform()`.
- Respect hard limits: 10 `AppShortcut`s per app, 1000 total trigger phrases (including parameter expansions). The first phrase in each shortcut's array is the primary one - it's shown on the Shortcuts home tile and as Siri's "what can I do with X?" answer.
- Include at least one non-parameterized phrase per App Shortcut so it's discoverable before first launch; parameterized phrases don't appear in Spotlight until the app has run once and populated the parameter cache.
- Prefer `supportedModes` + `continueInForeground` (iOS 26+) over `ForegroundContinuableIntent` / `needsToContinueInForegroundError` for new code that conditionally foregrounds. The newer form lets one intent declare it may run background or foreground based on runtime state.
- Snippet views have a 340-point height ceiling; beyond this, scrolling breaks the glance overlay model. Link to the full app for deep content, and keep snippet text larger than system defaults for legibility at reading distance.
- For text parameters that may receive input from Apple Intelligence's Use Model action, declare the type as `AttributedString` rather than `String` so rich formatting (bold, italic, lists, tables) is preserved losslessly.
- The app's `App` struct initializer is executed when an intent runs, even if the UI never appears. Do all intent-relevant setup (`ModelContainer` creation, `AppDependencyManager.shared.add(...)`, log plumbing) inside `init()`, not inside view modifiers like `.task` or `.onAppear`.
- `LocalizedStringResource` is the standard string type everywhere in App Intents (titles, dialog, parameter prompts). It shares string catalogs with SwiftUI, so localization works out of the box.
- Grammar agreement (`inflect: true`) works in English, French, German, Italian, Spanish, and Portuguese (both variants). For other locales it falls back to the unmodified form.
- Intents triggered from a system surface get ~30 seconds (no hard limit on macOS). For uploads, sync, large file ops, or on-device inference, conform to `LongRunningIntent` and do the work inside `performBackgroundTask { ... }` - and **report `progress` regularly**, because going quiet makes the system revoke the runtime extension. Pair with `CancellableIntent` to clean up with the cancellation reason. Don't try to beat the limit with a detached `Task`; unmanaged tasks aren't covered by the extension.
- Use `EntityCollection<Entity>` instead of `[Entity]` for parameters that may hold many entities when `perform()` mostly needs ids - it skips full entity resolution during parameter handling. Call `resolvedEntities()` only when you need the full objects.
- In schema-based **update** intents, distinguish "don't change" from "clear" with `$parameter.valueState` (`.set(value)` / `.set(nil)` / `.unset`), not a plain `nil` check - otherwise voice commands can never clear a field.
- Conform entities to `SyncableEntity` when Siri might reference them in a cross-device conversation. If the id is already consistent everywhere (server UUID, CloudKit record id), just adopt the protocol; otherwise pair local and stable ids with `SyncableEntityIdentifier`.
- Conform shareable entities to `OwnershipProvidingEntity` and keep their `ownership` (`.shared` / `.public`) current, so Siri confirms actions on content the user shared or published. By default Siri assumes entities are private and may skip confirmation.
- To carry structured types other apps understand (a coordinate, a contact, a name), add an `IntentValueRepresentation` via the `ValueRepresentation` builder to the entity's `transferRepresentation` - `FileRepresentation`/`DataRepresentation` only cover file formats. Use the key-path form (`ValueRepresentation(exporting: \.place)`) when the entity already stores the system type.
- For on-screen awareness, pick the annotation by shape: `.userActivity` for one primary item, `.appEntityIdentifier(_:)` for one among a few, `.appEntityIdentifier(forSelectionType:)` on a `List`/collection for many (lazy), `.appEntityUIElements(_:)` for custom `Canvas`/`CALayer` drawing. Annotations on Notifications, Now Playing, and AlarmKit require a real `AppEntity` - `TransientAppEntity` has no persistent id and can't be used there. Add a `displayRepresentations` query method so Siri can resolve onscreen entities without a full DB fetch.
- Donate **UI** interactions with `IntentDonationManager` (the system already donates Siri/Shortcuts runs); donate after the action completes, don't over-donate (the system will start ignoring you), and delete stale donations.
- Test with the `AppIntentsTesting` framework (out-of-process, in an XCUITest bundle) for the integration surface - intents, queries, `spotlightQuery()`, `viewAnnotations()`; use test-only intents (`isDiscoverable = false` + `#if DEBUG`) to seed data and reach internal state. Keep direct `perform()` struct tests for pure logic.
## Output Format
If the user asks for a review, organize findings by file. For each issue:
1. State the file and relevant line(s).
2. Name the anti-pattern being replaced.
3. Show a brief before/after code fix.
Skip files with no issues. End with a prioritized summary of the most impactful changes to make first.
If the user asks you to write or fix intent code, make the changes directly instead of returning a findings report.
Example output:
### RecentItemsIntent.swift
**Line 18: SwiftData `@Model` cannot conform to `AppEntity` (not `Sendable`).**
```swift
// Before
extension Article: AppEntity { ... }
// After
struct ArticleEntity: AppEntity {
var id: UUID
var title: String
static let typeDisplayRepresentation: TypeDisplayRepresentation = "Article"
static let defaultQuery = ArticleEntityQuery()
var displayRepresentation: DisplayRepresentation {
DisplayRepresentation(title: "\(title)")
}
}
```
**Line 42: Siri phrase missing `\(.applicationName)` - will fail to build.**
```swift
// Before
AppShortcut(intent: OpenArticleIntent(), phrases: ["Open an article"], ...)
// After
AppShortcut(intent: OpenArticleIntent(), phrases: ["Open an article in \(.applicationName)"], ...)
```
### Summary
1. **Sendability (high):** `Article` as `AppEntity` will fail to compile on Swift 6; create a shadow struct.
2. **Siri phrases (high):** `\(.applicationName)` is required in every phrase.
End of example.
## References
- `references/fundamentals.md` - `AppIntent` protocol, `perform()`, return types (`IntentResult`, `ProvidesDialog`, `ReturnsValue`, `ShowsSnippetView`, `OpensIntent`), intent dialog, grammar agreement.
- `references/parameters.md` - `@Parameter`, primitive vs entity parameters, `@AppEnum`, dialog options, parameter prompts.
- `references/entities.md` - `AppEntity`, `IndexedEntity`, shadow-struct pattern, display representations, entity queries (`EnumerableEntityQuery`, `EntityQuery`, `EntityStringQuery`, `UniqueIDEntityQuery`).
- `references/shortcuts-and-siri.md` - `AppShortcutsProvider`, phrases (`\(.applicationName)` rule), `shortcutTileColor`, `SiriTipView`, `ShortcutsLink`, parameter presentation.
- `references/open-and-snippet-intents.md` - `OpenIntent`, snippet views (`ShowsSnippetView`), navigation via data controller, when to use which.
- `references/dependencies.md` - `@Dependency`, `AppDependencyManager`, data-controller pattern, `ModelContainer` vs `ModelContext` sendability, main-actor vs local-context tradeoff.
- `references/spotlight.md` - `IndexedEntity`, `IndexedEntityQuery` (reindexing), `CSSearchableIndex`, `attributeSet`, semantic index, index-on-launch vs index-on-change, debounced reindexing.
- `references/assistant-schemas.md` - `@AssistantEntity`, `@AssistantIntent`, schema adoption, multi-schema requirements, `.system.searchInApp`, Visual Intelligence (iPad/macOS, system stores), Xcode code snippets, caveats.
- `references/siri-intelligence.md` - the Siri / Apple Intelligence integration model: finding content (semantic index / structured search / in-app search), custom responses, interaction donations, confirmation + `OwnershipProvidingEntity`, validation flow.
- `references/onscreen-awareness.md` - the 4 on-screen annotation APIs, content transfer (`IntentValueRepresentation`, resolve vs import), `displayRepresentations` fast path, entity annotations on Notifications / Now Playing / AlarmKit.
- `references/long-running-and-execution.md` - the 30-second budget, `LongRunningIntent` + `performBackgroundTask`, `CancellableIntent`, background GPU, `allowedExecutionTargets`.
- `references/testing-intents.md` - the `AppIntentsTesting` framework (out-of-process integration), direct `perform()` unit tests, mocking `@Dependency` via `AppDependencyManager`, test-only intents, what you can't unit-test.
- `references/anti-patterns.md` - common mistakes LLMs make when generating App Intents code.