What Are App Intents in iOS 26? The Developer Guide to Apple Intelligence Integration

What Are App Intents in iOS 26? The Developer Guide to Apple Intelligence Integration

Your app has a problem it doesn't know about yet.

When a user holds up their iPhone camera to a bottle of wine, a pair of sneakers, or a dish at a restaurant, iOS 26's Visual Intelligence kicks in. It scans the scene, figures out what's there, and surfaces results from apps that participate. If your app sells wine, shoes, or recipes — and you haven't adopted the new App Intents APIs — your app doesn't show up. At all.

That's the shift. Apps in 2026 aren't just launched. They're queried. Siri, Spotlight, and now Visual Intelligence reach directly into your app's data and act on it. The question isn't whether this matters. It's whether your app is ready.

This guide covers everything from scratch. What App Intents are, how they work, what iOS 26 adds, and how to implement each piece. Whether you've never written an AppIntent in your life or you're upgrading an existing implementation, you're in the right place.

What you'll need: Xcode 26+, the iOS 26 SDK, and a basic grasp of Swift and SwiftUI. That's it.

Jump to what you need:


Part 1 — The Foundation

What Are App Intents? (And Why They Matter More Than Ever in iOS 26)

The Core Idea in Plain English

Here's the simplest way to think about it.

Your app is a restaurant. It has a menu of things it can do — log a workout, find a recipe, track a package, add something to a cart. Before App Intents, the only way to access that menu was to walk in the front door (open the app), find a table (navigate to the right screen), and order yourself (tap the button yourself).

App Intents puts the menu in the window. The system — Siri, Spotlight, Shortcuts, Apple Intelligence — reads the menu and places orders on the user's behalf. The user doesn't have to open the app at all.

The important detail: the menu is declared, not discovered. You describe what your app can do in code at compile time, and the system learns it before the user ever asks. That's what makes zero-UI actions and proactive suggestions possible.

The Problem App Intents Replaced

Before iOS 16, Siri integration meant SiriKit. And SiriKit was... a lot. It locked you into predefined domains: messaging, payments, workouts, restaurant bookings. If your app didn't fit a domain, you were out of luck. If it did fit, the API was still painful.

App Intents threw that out. Any app can expose any action. The system doesn't care what category your app is in — if you implement the protocol, your actions are available in the system.

Here's the quick comparison:

SiriKit App Intents
Flexibility Fixed domains only Any action, any data
Apple Intelligence support No Yes
Visual Intelligence No Yes (iOS 26+)
Code complexity High (Intent definitions, response objects, extension) Lower (Swift protocol conformance)
Availability iOS 10+ iOS 16+

App Intents is the present and the future. SiriKit is on maintenance mode.

SiriKit vs App Intents Migration ROI Calculator

Est. LoC (SiriKit)

2,500

Est. LoC (App Intents)

250

Every Surface Where App Intents Appear in iOS 26

One implementation, many surfaces. Here's where your App Intents show up once you've built them:

  • Siri — spoken requests ("Hey Siri, log my water") and follow-up conversation
  • Spotlight — search results with inline action buttons
  • Shortcuts app — user-composable automations that chain your intents together
  • Widgets — parameterized widget configurations (which project? which city?)
  • Action Button (iPhone 15 Pro+) — one-tap trigger for a named intent
  • Lock Screen Controls — quick-access system buttons
  • Apple Intelligence — the AI layer that routes natural language to the right intent automatically
  • Visual Intelligence (iOS 26 — NEW) — image-context queries that pull your entities into the camera overlay UI

💡 Not everything needs Apple Intelligence hardware. Shortcuts, Spotlight, and Siri work on all iOS 26 devices. Visual Intelligence requires iPhone 15 Pro or newer with Apple Intelligence enabled.

The Evolution of App Intents: iOS 16 Through iOS 26

If you're new to App Intents, this gives you context. If you've been using it since iOS 16, this is a quick "here's how we got here."

   [iOS 16] ── The Foundation 
      │        (AppIntent, AppEntity, AppShortcutsProvider)
      │
   [iOS 17] ── Widget Integration
      │        (AppIntentConfiguration, Smart Parameterization)
      │
   [iOS 18] ── Apple Intelligence Enters
      │        (ProvidesDialog, ShowsSnippetView, AI Routing)
      │
   [iOS 26] ── App Intents 2.0
               (IntentValueQuery, @DeferredProperty, SnippetIntent)
      

iOS 16 — The Foundation

This is where it started. Apple introduced the AppIntent protocol, AppEntity, AppShortcutsProvider, and Spotlight integration. The framework replaced SiriKit as the primary system integration API for new apps.

The limitation at this point: every property on an entity had to be fully computed before it was returned. No lazy loading. Everything upfront, every time.

iOS 17 — Widget Integration

iOS 17 brought AppIntentConfiguration, which made widgets smarter. Instead of a static widget, you could build a parameterized one — the user picks which project, which city, which habit to track. App Intents became the data bridge between your app and the home screen.

iOS 18 — Apple Intelligence Enters the Picture

This is when things got serious. Apple Intelligence launched with App Intents as its action surface — the layer through which AI-driven responses trigger real app behavior. Two new result types arrived: ProvidesDialog (a Siri response sentence) and ShowsSnippetView (attach a SwiftUI card to the response).

App Intents went from "nice to have for Shortcuts power users" to "your app's contract with Apple's AI."

iOS 26 — App Intents 2.0

Four additions. Same core model, extended into new surfaces:

  1. IntentValueQuery — Visual Intelligence integration
  2. @DeferredProperty — async-computed entity properties
  3. SnippetIntent — interactive pop-up UI with system refresh support
  4. Entity view annotations — context-specific rendering for your entities

The rest of this guide is mostly about these four. But first — the building blocks.

📌 Already shipping App Intents for iOS 18? Jump straight to Part 3. The iOS 26 additions are fully additive — your existing code doesn't break.


Part 2 — Core Primitives: The Building Blocks

The App Intents Framework: Core Concepts Every Developer Must Know

Before iOS 26 additions make sense, the core types need to click. This section is the "before we run, let's walk" part.

The AppIntent Protocol — Defining an Action

An AppIntent is a struct that represents one thing your app can do. It has a title (what the system calls it) and a perform() method (what happens when it runs).

import AppIntents

struct LogWaterIntakeIntent: AppIntent {
    static var title: LocalizedStringResource = "Log Water Intake"

    @Parameter(title: "Amount (ml)")
    var amount: Int

    func perform() async throws -> some IntentResult & ProvidesDialog {
        WaterTracker.shared.log(ml: amount)
        return .result(dialog: "Logged \(amount)ml of water.")
    }
}

That's the whole shape. A title, optional parameters, and a perform() that runs the action and returns a result.

The perform() return type uses composition. ProvidesDialog tells Siri to speak the result. Add & ShowsSnippetView and you get a SwiftUI card alongside the dialog. Add & ReturnsValue<Int> and the Shortcuts app can chain the output into another step.

AppEntity — Your App's Data as a System Citizen

If AppIntent is the verb, AppEntity is the noun. It's a piece of your app's data the system can reference and display.

struct Recipe: AppEntity {
    static var typeDisplayRepresentation = TypeDisplayRepresentation(name: "Recipe")
    static var defaultQuery = RecipeQuery()

    var id: RecipeID
    var displayRepresentation: DisplayRepresentation {
        DisplayRepresentation(
            title: "\(title)",
            subtitle: "\(cuisine) · \(cookTime) min",
            image: .init(named: imageName)
        )
    }

    @Property(title: "Title") var title: String
    @Property(title: "Cuisine") var cuisine: String
    @Property(title: "Cook Time") var cookTime: Int
}

Three things are required: a unique identifier, a typeDisplayRepresentation (what the type is called), and a displayRepresentation (how an individual instance looks in the system UI).

AppShortcutsProvider — Registering Your Actions with the System

This is the registry. It tells Siri and Apple Intelligence what your app can do, in plain English phrases.

struct RecipeAppShortcuts: AppShortcutsProvider {
    static var appShortcuts: [AppShortcut] {
        AppShortcut(
            intent: FindRecipeIntent(),
            phrases: [
                "Find a recipe in \(.applicationName)",
                "What can I cook in \(.applicationName)?",
                "Show me recipes in \(.applicationName)"
            ],
            shortTitle: "Find a Recipe",
            systemImageName: "fork.knife"
        )
    }
}

Phrases are how Siri finds your intent. Write them the way a real person would say them. The \(.applicationName) token disambiguates between apps — essential if your phrases are generic.

Common mistake: registering one phrase per intent. Siri needs variety to match natural speech. Aim for at least three phrases per intent.

@Parameter — Accepting Input

Parameters connect your intent to data. They can be entity types, simple values (String, Int, Bool), or system types (Date, Duration).

When a required parameter is missing, the system generates a follow-up question automatically using the parameter's title. You declare what you need; the system handles the conversation.

For dynamic options (a dropdown of your user's projects, for example), use DynamicOptionsProvider to return the list at query time.

IntentResult Composition

The return type of perform() describes what the system does with the result. Mix and match:

Result type What it does
ReturnsValue<T> Returns a typed value to Shortcuts or Intelligence pipelines
ProvidesDialog Returns a sentence for Siri to speak/display
ShowsSnippetView Attaches a SwiftUI view to the response

Compose them with &: some IntentResult & ProvidesDialog & ShowsSnippetView. All three together is perfectly valid.

EntityQuery and EntityStringQuery

Every AppEntity needs at least one query type so the system can fetch it.

  • EntityQuery — fetches entities by their identifiers. The system uses this internally to resolve a saved parameter reference.
  • EntityStringQuery — adds string-search, enabling Spotlight and Siri to find entities by name.

If users ever refer to an entity by name (which they almost always do), implement both. EntityQuery alone makes your entities invisible to name-based searches.

Setting Up App Intents in Your Xcode Project

Good news: this isn't complicated.

Project Configuration

  • No special entitlement needed for most App Intents features. Visual Intelligence (IntentValueQuery) is the same — no extra entitlement as of iOS 26.
  • No Info.plist keys required for basic App Intents. Xcode handles the metadata generation at build time.
  • Xcode 26+ is required. The build system generates App Intents metadata at compile time, which is why everything must be a compile-time declaration, not runtime registration.

Structuring Your App Intents Code

Keep it organized and you'll thank yourself later:

  • One file per intent (LogWaterIntakeIntent.swift)
  • One file per entity (Recipe.swift, RecipeQuery.swift)
  • One AppShortcutsProvider in the main app target

If an intent needs to run in the background without launching your app's UI, put it in an App Extension. But for most intents, the main app target is fine.

If you're using Swift Packages: entity and intent types can live in a package, but AppShortcutsProvider must be in the app target itself.

Your First AppIntent: The Minimal Working Version

Here's the fastest path from zero to a working intent:

  1. Create a struct conforming to AppIntent with a title and a perform() method
  2. Have perform() do one thing and return a ProvidesDialog result
  3. Register it in an AppShortcutsProvider with three natural-language phrases
  4. Build and run the app once (this indexes the intents)
  5. Open the Shortcuts app, find your intent, run it

That's your baseline. From here, you're adding entities, parameters, and iOS 26 features on top of a working foundation.


Part 3 — iOS 26 Additions: App Intents 2.0

Visual Intelligence Integration with IntentValueQuery

This is the headline feature. If your app has any kind of visual content — products, food, places, objects — this is the most valuable iOS 26 addition you can adopt.

How Visual Intelligence Works: The System Flow

Here's what happens when a user points their camera at something:

  1. User opens Visual Intelligence (photo, screenshot, or live camera)
  2. The system's Vision and ML layer extracts semantic context from the image
  3. The system queries every app that has registered an IntentValueQuery with that context
  4. Each app returns matching AppEntity instances
  5. The system aggregates results and surfaces them in the Visual Intelligence UI
  6. The user taps a result to deep-link directly into the originating app

Your app's job is step 4. Everything else the system handles.

Critically: your query runs in the background. It doesn't launch your app. It's silent, fast, and automatic.

Camera / Image System ML (Extracts Labels) IntentValueQuery (Your App Code) Visual Intel UI (Top Entity Results)

The IntentValueQuery Protocol

The protocol has one method:

import AppIntents

struct ProductLookupQuery: IntentValueQuery {
    func values(for descriptor: SemanticContentDescriptor) async throws -> [Product] {
        let candidates = try await catalog.search(labels: descriptor.labels)
        return candidates.map(Product.init)
    }
}

Register it on your entity:

struct Product: AppEntity {
    static var defaultIntentValueQuery = ProductLookupQuery()
    // ... rest of entity
}

That's the registration. One property. The system calls the query automatically when Visual Intelligence is active and your app is installed.

Understanding SemanticContentDescriptor

The descriptor the system passes to your query has two fields.

The labels Field — Semantic Tags from the System

An array of detected category and content tags. Think: ["wine bottle", "pinot noir", "label text", "red wine"]. The system's ML layer has already done the image recognition work. Your job is to map those tags to your own data.

Don't assume exact string equality. Fuzzy-match against your taxonomy, use synonyms, and handle partial matches. The labels are the system's best guess at what's in the image — work with them, not against them.

The pixelBuffer Field — Raw Visual Data

A CVReadOnlyPixelBuffer containing the actual image. Only use this if your app runs its own on-device vision model — a Core ML image classifier, a Vision framework request, something like that.

For most apps, labels is entirely sufficient and far cheaper to process. Save pixelBuffer for cases where the system's semantic tags aren't specific enough for your domain.

Implementing IntentValueQuery: Step-by-Step

  1. Confirm your entity is already registered as an AppEntity with a defaultQuery
  2. Create a struct conforming to IntentValueQuery
  3. Implement values(for:) — map descriptor.labels to your data source
  4. Declare the query on your entity: static var defaultIntentValueQuery = YourQuery()
  5. Unit test it — construct a SemanticContentDescriptor directly and call values(for:) to verify results before testing on hardware

Which Apps Should Implement IntentValueQuery?

If a user might ever point a camera at something and want your app to respond, implement it. That includes:

  • Shopping and e-commerce — product catalog lookup from a photo
  • Recipes and food — ingredient or dish identification
  • Wine and beverage — label recognition
  • Travel and navigation — landmark or place identification
  • Fitness and wellness — exercise equipment or movement identification
  • Any app where the answer to "what is this?" lives in your data

Scoping and Relevance: Returning Quality Results

This is where most first implementations go wrong.

The Visual Intelligence UI shows results from multiple apps side by side. If your app returns 20 loosely-matched results and another app returns 3 highly-relevant ones, users will trust the other app. Worse — the system may learn to deprioritize your results over time.

Return top 3–5 results, ranked by relevance. Good ranking signals:

  • Text similarity between labels and your product/content names
  • Recency of the user's interaction with that entity
  • Personalization data if you have it (browsing history, purchase history, favorites)

Three excellent results beat twenty mediocre ones. Every time.

@DeferredProperty — Async Entity Values

This one's less flashy but genuinely solves an annoying problem.

The Problem: All-or-Nothing Property Computation

Before iOS 26, every @Property on an AppEntity had to be computed before the entity was returned from a query. If even one property needed a network fetch, the entire entity was slow to return.

The workaround was ugly: expose a "thin" entity for query results, build a separate "detail" intent to load the full data, and wire them together. It worked, but it was a lot of plumbing for what should be a simple idea.

How @DeferredProperty Solves This

@DeferredProperty declares a property as async-computed. The getter runs only when the system actually needs that value.

In practice: your entity returns fast with its cheap properties (title, subtitle, thumbnail). If the user selects it and the system needs the full details, then the deferred getter runs.

struct Recipe: AppEntity {
    @Property(title: "Title") var title: String
    @Property(title: "Cuisine") var cuisine: String

    @DeferredProperty(title: "Full Instructions")
    var instructions: String {
        get async throws {
            try await RecipeAPI.loadInstructions(id: id)
        }
    }
}

The instructions property is never computed during a query. It loads on demand, when the system actually needs it for a detail view.

When to Use It (and When NOT To)

Use @DeferredProperty for:

  • Server-fetched fields (full descriptions, metadata, reviews)
  • Large text bodies that require a disk read
  • ML-computed scores or summaries
  • Media metadata that's expensive to load

Don't use @DeferredProperty for:

  • Fast in-memory lookups
  • Computed properties that take under a millisecond
  • Simple string formatting

The async overhead — task scheduling, awaiting, actor hops — is real. If your property is cheaper to compute than the overhead costs, you've made things slower, not faster.

Error Handling with @DeferredProperty

The getter is get async throws, so errors propagate naturally. If the getter throws, the system omits that property from the detail view. The entity still shows up — just without that field.

Best practice: throw typed errors so you can distinguish network failures from data-not-found. Log failures so you can diagnose them. Don't let errors silently vanish.

Interactive Snippets — Richer Responses in System Surfaces

One-line Siri responses are fine for simple actions. But for weather forecasts, package tracking, sports scores, or transit times — you need more than a sentence. That's what snippets are for.

What Is an App Intents Snippet?

A snippet is a small SwiftUI view the system displays alongside (or instead of) a dialog response. It appears in Spotlight, Visual Intelligence, and the Siri response surface.

Think of it as a card — compact, focused, interactive. The user can tap buttons, scroll content, and trigger follow-up actions without ever opening your app.

The golden rule: a snippet is a card, not an app. One primary result, one or two action buttons. That's the shape.

ShowsSnippetView vs. SnippetIntent — Choosing the Right Approach

AppIntent + ShowsSnippetView SnippetIntent
iOS availability iOS 18+ iOS 26+
Use case Attach a view to any intent's result Design an intent specifically as a snippet
System reload Not supported static func reload() — system refreshes content
Best for Adding snippets to existing intents New live-updating features (scores, forecasts, ETAs)

The decision is simple: upgrading an existing intent? Add ShowsSnippetView to its return type. Building a new intent designed to live as a refreshable card? Use SnippetIntent.

Building Your First Interactive Snippet

For a standard intent:

struct PackageTrackingIntent: AppIntent {
    static var title: LocalizedStringResource = "Track Package"

    @Parameter(title: "Tracking Number")
    var trackingNumber: String

    func perform() async throws -> some IntentResult & ProvidesDialog & ShowsSnippetView {
        let status = try await ShippingAPI.status(for: trackingNumber)
        return .result(
            dialog: "Your package is \(status.summary).",
            view: PackageStatusCard(status: status)
        )
    }
}

For a SnippetIntent with system refresh support:

struct LiveScoreSnippet: SnippetIntent {
    static var title: LocalizedStringResource = "Live Score"

    @Parameter(title: "Game")
    var game: Game

    func perform() async throws -> some IntentResult & ShowsSnippetView {
        let score = try await SportsAPI.currentScore(for: game)
        return .result(view: ScoreCard(score: score))
    }

    static func reload() async throws {
        // System calls this when it wants fresh data
        // Trigger a data refresh here
    }
}

Your ScoreCard view is a normal SwiftUI view. Keep it self-contained, pass in a model object, and use system typography modifiers.

What Makes a Good Snippet (and What Doesn't)

Do this:

  • ✅ One primary result per snippet
  • ✅ One or two action buttons ("Open in App", "Mark Delivered", "Add to Calendar")
  • ✅ System typography: .headline, .body, .caption
  • AsyncImage for images (non-blocking)
  • ✅ A clear "Open in App" escape hatch for complex flows

Avoid this:

  • ❌ Navigation stacks, tab bars, or any multi-screen UI inside a snippet
  • ❌ Login or onboarding flows inside a snippet
  • ❌ More than 4 interactive elements
  • ❌ Heavy images or video on initial render
  • ❌ Blocking the view's body on a network fetch

Snippets in Spotlight, Visual Intelligence, and Siri

Good news: one snippet view works everywhere.

  • Spotlight — snippet appears inline in the search result. The user never leaves the search UI.
  • Visual Intelligence — snippet appears below the entity card. Context before the user decides to open the app.
  • Siri — snippet is the visual component alongside the spoken dialog.

Build it compact and responsive and the system adapts it to each context automatically.

Entity View Annotations — How Your Entities Render

This is a quieter addition, but it fixes something that has always been a bit awkward.

The Old Single-Representation Model

Before iOS 26, DisplayRepresentation was one struct — one title, one subtitle, one image. The system used that same representation everywhere: a tight Spotlight list row, a Siri result card, a Visual Intelligence hero panel.

The problem: a compact list display looks anemic as a hero card. A hero card layout looks overcrowded in a list row. You had one shot and had to pick the least-bad option.

Context-Specific Rendering with iOS 26

iOS 26 lets entities declare multiple representation variants. The system picks the right one for the rendering context automatically. You don't detect the context in code — you just describe the variants and let the system decide.

Variant contexts:

  • Compact list — Spotlight rows, tightly packed
  • Standard card — Siri response surface
  • Hero card — Visual Intelligence panel, full-width

Implementing Multiple Variants

The mechanism extends displayRepresentation with context-specific variants:

struct Recipe: AppEntity {
    var displayRepresentation: DisplayRepresentation {
        DisplayRepresentation(
            title: "\(title)",
            subtitle: "\(cuisine) · \(cookTime) min",
            image: .init(named: thumbnailName)
        )
    }

    // iOS 26: add a richer hero variant for Visual Intelligence
    var heroDisplayRepresentation: DisplayRepresentation {
        DisplayRepresentation(
            title: "\(title)",
            subtitle: "\(cuisine) · \(cookTime) min · ⭐️ \(rating)",
            image: .init(named: heroImageName)
        )
    }
}

All variants share the same underlying entity data. Only the presentation layer changes.

When This Actually Matters

Entity view annotations make a real difference for apps with rich media content — recipes, products, locations, events. If your Visual Intelligence card previously felt sparse (just a title and a tiny thumbnail), annotations let you deliver a proper hero image and richer metadata there without affecting how the entity looks in Spotlight list rows.


Part 4 — Apple Intelligence Integration Deep Dive

How Siri and Apple Intelligence Route Requests to Your App

Understanding the routing pipeline is what separates intents that Siri finds reliably from ones that Siri never surfaces.

The Routing Pipeline

When a user says something to Siri, here's what happens:

  1. Apple Intelligence's natural language model parses the request
  2. It matches against registered AppShortcut phrases across all installed apps
  3. It resolves any parameters from context or by asking follow-up questions
  4. It calls perform() on the matching intent

What the model uses to match: the phrases you wrote in AppShortcutsProvider, the titles on your parameters, and the typeDisplayRepresentation of your entities.

What you can't control: the routing logic itself. You influence it through clarity — clear phrases, well-named parameters, descriptive entity representations.

Writing Effective AppShortcut Phrases

This is where most developers leave performance on the table. Phrases are your lever. Use it.

Write the way users actually speak. Not "Initiate Water Log Entry" — "Log my water." Not "Execute Recipe Search" — "Find me something to cook."

Write at least three variants per intent:

  • Imperative: "Log my water"
  • Question: "Can you log my water intake?"
  • Natural speech: "I want to add some water"

Use \(.applicationName) for disambiguation. If your phrase is generic ("set a reminder"), Siri might route it to the system instead. Specificity wins.

Avoid overlapping system phrases. Anything that sounds like "call," "message," "set a timer," or "navigate to" will lose to the OS. Go domain-specific.

Parameter Resolution and Follow-Up Disambiguation

When a required parameter is missing, the system generates a follow-up question from the parameter's title. You declared @Parameter(title: "Amount (ml)") — Siri asks "How many millilitres?"

For parameters that depend on each other (city → neighborhood, project → task list), use IntentParameterDependency. The system handles the branching conversation; your intent just declares the dependency.

Proactive Suggestions via Spotlight Donation

You don't need to manually donate interactions anymore. When you implement EntityStringQuery, the system automatically indexes your entities and surfaces them as proactive Spotlight suggestions.

The system learns from usage patterns. If a user logs water every morning, Siri will start suggesting it at that time. You get that for free — no extra code needed.

App Intents vs. MCP Tools — Which Should You Build?

With all the talk of AI agents lately, this question comes up constantly. Short answer: they're not competitors.

What App Intents Are Optimized For

  • Apple's first-party surfaces — Siri, Spotlight, Shortcuts, Visual Intelligence, Action Button
  • Privacy-first — all routing happens on-device; no data leaves Apple's stack without user consent
  • Zero user configuration — if your app is installed, your intents are available, automatically
  • Apple Intelligence orchestration — the system can chain your intents with other apps' actions

What MCP Tools Cover

  • Third-party AI agents — Claude, ChatGPT, any LLM running locally or remotely
  • Cross-app orchestration — "read my emails and create Jira tickets from the action items" (not something Apple Intelligence does today)
  • Developer-to-developer integrations — exposing your data to the broader agent ecosystem beyond Apple

Decision Framework

Goal Use
Show up in Siri, Spotlight, Visual Intelligence App Intents
Show up in Claude, ChatGPT, or other agents MCP Tools
Show up in both App Intents + local MCP server

The good news if you want both: they share the same underlying data model. You write your business logic once and expose it through two thin protocol layers — AppIntent for Apple's surfaces, MCP tool handlers for agent surfaces.


Part 5 — Testing, Debugging, and Shipping

Testing Your App Intents Implementation

Shipping App Intents without testing them thoroughly is how you end up with Siri telling users she "can't help with that" — which is equally frustrating for users and for you.

Testing in the Shortcuts App

The Shortcuts app is your primary manual test surface. It's free, always available, and exposes exactly how the system sees your intents.

  • Add your intent to a shortcut and run it
  • Inspect parameters, dialogs, and snippet output
  • Test parameter flows: remove a required parameter and verify the system prompts for it correctly
  • Test edge cases: empty values, invalid inputs, network failures

Make this part of your routine before any release.

Unit Testing Intents

AppIntent.perform() is a plain async throwing function. Test it directly with XCTest or Swift Testing — no special setup required.

For IntentValueQuery: construct a SemanticContentDescriptor in your test and call values(for:) directly. Inject a mock data provider so results are predictable and fast.

func testProductLookupReturnsResults() async throws {
    let query = ProductLookupQuery()
    let descriptor = SemanticContentDescriptor(labels: ["sneakers", "running shoe"])
    let results = try await query.values(for: descriptor)
    XCTAssertFalse(results.isEmpty)
}

Mock your data layer. Tests that depend on a live server are tests waiting to fail.

Testing Visual Intelligence

Here's the hard truth: the full Visual Intelligence flow requires real hardware. You need an iPhone 15 Pro or newer, iOS 26+, and Apple Intelligence enabled in Settings → Apple Intelligence & Siri.

For CI pipelines: unit test the query logic. Use physical devices for integration testing of the full Visual Intelligence flow.

A useful shortcut (literally): build a Shortcut that manually calls your IntentValueQuery with a test descriptor. Much faster dev loop than holding the camera up at a test image every iteration.

Debugging Common Failures

Problem Likely cause Fix
Intent not appearing in Siri or Spotlight AppShortcutsProvider in wrong target Move it to the app target; call updateAppShortcutParameters()
Entity not resolving in a parameter EntityQuery.entities(for:) isn't returning the entity Verify the query returns the entity for the identifier the system passes
Snippet not rendering Missing ShowsSnippetView in return type Add & ShowsSnippetView and verify the view doesn't throw during init
IntentValueQuery never called defaultIntentValueQuery missing on entity, or app not indexed Add the property; launch the app once on the device after a fresh install

Performance Best Practices

App Intents run in the system's context with real time budgets. Slow queries and heavy snippets don't just feel bad — they get skipped.

Keep Entity Queries Fast

The system expects results quickly. If your query is slow, it loses the race to other apps' results or times out entirely.

  • Cache frequently queried entities in memory
  • Persist that cache between launches so the first query after a cold start is still fast
  • For IntentValueQuery: pre-index visual labels against your catalog at app launch so the query is an in-memory lookup, not a live search request

Scope Results for Quality Over Quantity

Return 3–5 results, ranked by relevance. Not 20. Not "everything that matches."

Good ranking signals: text relevance, recency of user interaction, personalization data. If the user just viewed a product, surface it first.

Snippet Render Budget

Snippets render in the system's process with a strict memory and time budget.

  • Avoid heavy SwiftUI animations on initial render; save them for in-response interactions
  • Load images asynchronously with AsyncImage — never block the view's body
  • Target snippet init + first render under 100ms

App Store Submission Considerations

Privacy Manifest and App Intents

App Intents themselves don't require new privacy manifest entries. But:

  • If your IntentValueQuery processes the pixelBuffer (the raw camera image), document the relevant data category in your privacy manifest
  • If your intents access contacts, health data, or location, those existing permission flows apply — the system triggers the permission prompt before calling perform()

Nothing exotic here. If you're already handling permissions correctly, you're fine.

Communicating Apple Intelligence Requirements to Users

Visual Intelligence results (IntentValueQuery) only appear on Apple Intelligence-capable devices. On everything else, your other App Intents work fine — Siri, Shortcuts, Spotlight.

In your App Store description and onboarding: don't gate the whole app on Apple Intelligence. Present Visual Intelligence features as enhancements for supported devices, not core requirements.


Part 6 — The Six Most Common App Intents Mistakes

Consider this the "we learned these the hard way so you don't have to" section.

Mistake 1: IntentValueQuery Returning Unscoped Results

What happens: the query returns every catalog item that vaguely matches any descriptor label.

Why it hurts: Visual Intelligence shows multiple apps' results simultaneously. A wall of unranked results from your app pushes your best matches off-screen. Users stop trusting your results.

Fix: build a relevance scorer. Return top-N sorted by score. Your best 3 results are worth more than your worst 20.

Mistake 2: Using @DeferredProperty for Fast Values

What happens: a simple computed property gets marked as @DeferredProperty because it's technically computed.

Why it hurts: async overhead — task scheduling, awaiting, actor hops — costs more than the computation you were trying to avoid.

Fix: reserve @DeferredProperty for genuinely expensive work: network calls, large disk reads, ML inference. If the property takes under a millisecond, keep it synchronous.

Mistake 3: Building Mini-Apps Instead of Snippets

What happens: the snippet gets a navigation stack, tab bar, settings screen, and onboarding flow crammed in.

Why it hurts: snippets render in a constrained surface. Complex layouts look broken. Users abandon them.

Fix: one primary result. One or two action buttons. An "Open in App" button for anything complex.

Mistake 4: Too Few Shortcut Phrases

What happens: one phrase per intent, written in internal app language ("Log Entry", "Recipe Search").

Why it hurts: Siri can't match natural speech to phrases that don't sound like natural speech.

Fix: three to five variants per intent. Include imperative, question, and casual phrasings. Use words your users actually say.

Mistake 5: Missing EntityStringQuery

What happens: EntityQuery is implemented (identifier-based), but EntityStringQuery is skipped.

Why it hurts: Spotlight can't index your entities by name. Siri can't resolve "my [entity name]" in a spoken request.

Fix: implement both. EntityStringQuery is required for any entity users refer to by name — which is almost all of them.

Mistake 6: Not Testing on Real Hardware

What happens: IntentValueQuery is tested via unit tests only, and the developer assumes Visual Intelligence is covered.

Why it hurts: the full system flow — image capture, semantic extraction, query aggregation, UI display — only happens on real hardware with a real Apple Intelligence session.

Fix: keep at least one iPhone 15 Pro (or newer) in your test device pool. No substitute for the real thing.


Part 7 — Real-World Patterns by App Category

Not sure where to start? Here's the playbook for six common app types.

Shopping and E-Commerce Apps

Primary surface IntentValueQuery (product from camera), EntityStringQuery (product search in Spotlight)
Best snippet Product card: name, price, availability + "Add to Cart" / "Open in App"
Key intents "Search for [product]", "Check price of [product]", "Add [product] to cart"
@DeferredProperty targets Full product description, review summary, real-time inventory count

Shopping apps are arguably the biggest winners from Visual Intelligence. Point camera at a product → your app surfaces it. That's a direct path to purchase with zero friction.

Recipe and Food Apps

Primary surface IntentValueQuery (ingredient/dish ID), EntityStringQuery (recipe by name)
Best snippet Recipe card: title, cook time, difficulty + "Save Recipe" / "Start Cooking"
Key intents "Find a recipe with [ingredient]", "Start cooking [recipe]", "Add [ingredient] to shopping list"
@DeferredProperty targets Full ingredient list, step-by-step instructions

The full recipe is the perfect @DeferredProperty candidate. The query only needs title, cook time, and a thumbnail. The instructions only matter when the user starts cooking.

Productivity and Task Management Apps

Primary surface Siri and Shortcuts (task creation, status checks), Spotlight (task search)
Best snippet Task card: title, due date, priority + "Mark Complete" / "Reschedule"
Key intents "Add a task to [project]", "What's due today?", "Mark [task] as done"
Visual Intelligence fit Lower — task apps benefit less from image-based queries

Focus your energy here on Siri phrase quality and Spotlight indexing. That's where task app users actually look.

Travel and Navigation Apps

Primary surface IntentValueQuery (landmark/place ID), Siri (navigation commands)
Best snippet Location card: name, distance, rating, hours + "Navigate" / "Save Place"
Key intents "Navigate to [place]", "How far is [destination]?", "Save [location] to favorites"
@DeferredProperty targets Full business details, user reviews, operating hours fetched from API

Visual Intelligence is high-value for travel. Point camera at a landmark → surface it in your app with reviews, opening hours, and a "Navigate" button.

Health and Fitness Apps

Primary surface Siri (log workouts, check stats), Spotlight (exercise search), Action Button (start workout)
Best snippet Workout summary: stats + "Log Again" / "View Details"
Key intents "Log a [workout type]", "How many steps today?", "Start a run"
Note HealthKit permission triggers automatically before perform() runs

The Action Button is a natural fit for fitness apps. One tap → start a workout. Set it up.

Media and Entertainment Apps

Primary surface Siri (play content, search), Spotlight (content discovery)
Best snippet Content card: title, runtime + "Play" / "Add to Watchlist"
Key intents "Play [show name]", "Add [movie] to my watchlist", "What's new in [genre]?"
@DeferredProperty targets Full synopsis, cast details, streaming availability

Siri phrase quality is critical for media apps. Users speak naturally ("find something funny to watch") — your phrases need to match that range.


Frequently Asked Questions

Do I need Apple Intelligence enabled to test App Intents features?

Not for most things. Siri, Shortcuts, and Spotlight work on all iOS 26 devices with Apple Intelligence disabled.

Visual Intelligence — and therefore IntentValueQuery — is the exception. It requires an Apple Intelligence-capable device (iPhone 15 Pro or newer) with Apple Intelligence enabled in Settings.

For development, you can bypass the hardware requirement for your query logic: call values(for:) directly in a unit test with a manually constructed SemanticContentDescriptor.

I already implemented App Intents for iOS 18 — how much work is the iOS 26 upgrade?

Not much. The iOS 26 additions are purely additive. Your existing AppEntity, AppShortcutsProvider, and AppIntent types don't need to change.

You're adding new conformances on top of what already exists:

  • IntentValueQuery for Visual Intelligence
  • @DeferredProperty for expensive properties
  • A snippet view for richer responses (optional)
  • Entity view variants (optional)

Most teams adopt these incrementally, starting with whichever addition has the highest impact for their app category.

What's the difference between SnippetIntent and an AppIntent with ShowsSnippetView?

Both produce a snippet UI. The difference is refresh support.

SnippetIntent (iOS 26+) adds a static reload() method. The system can call it to update the snippet's content without re-invoking perform(). That makes it the right choice for live-updating content: sports scores, flight status, package tracking, weather.

AppIntent + ShowsSnippetView (iOS 18+) produces a snapshot of the result at the time perform() ran. Great for responses that don't need to update. If you're adding snippets to existing intents, start here.

Can IntentValueQuery and EntityQuery coexist on the same entity type?

Yes, and they should. They serve different contexts:

  • EntityQuery — resolves entities by identifier (Shortcuts, Siri parameter references)
  • EntityStringQuery — name-based search (Spotlight, spoken Siri)
  • IntentValueQuery — image-context queries (Visual Intelligence)

All three can be declared on the same AppEntity. The system picks the right one for the context automatically.

How do entity view annotations interact with widgets?

They don't — they're separate systems. Entity view annotations apply within App Intents contexts (Spotlight, Visual Intelligence, Siri). Widgets use WidgetKit's own view system.

If your app exposes the same data as both an AppEntity and a widget, you'll have two separate presentation layers: entity view annotations for system AI surfaces, and a WidgetKit TimelineEntry view for the home screen. They share the underlying data model; only the views differ.

My IntentValueQuery returns correct results in unit tests but doesn't appear in Visual Intelligence. What's wrong?

Check these in order:

  1. defaultIntentValueQuery not declared on the entity — add static var defaultIntentValueQuery = YourQuery() to your entity type
  2. App not indexed — launch the app on the test device at least once after installing the new build
  3. Apple Intelligence disabled — check Settings → Apple Intelligence & Siri
  4. Device not capable — requires iPhone 15 Pro or newer; simulators don't support Visual Intelligence

Is there a performance cost to registering lots of App Intents?

Registration itself is negligible. App Intents are loaded lazily — the system only invokes the intents and queries relevant to the current context.

The performance cost lives in execution: your perform() and values(for:) implementations. If those are slow (synchronous network calls, blocking disk reads), that cost is felt at query time. Profile them with Instruments and keep them async.


Conclusion

What We Covered

We went from zero to the full iOS 26 App Intents surface:

  • Part 1 — what App Intents are, every surface they appear on, and how the framework evolved from iOS 16 to today
  • Part 2 — the core primitives: AppIntent, AppEntity, AppShortcutsProvider, parameters, result types, and queries
  • Part 3 — the four iOS 26 additions in detail: IntentValueQuery for Visual Intelligence, @DeferredProperty for lazy entity loading, SnippetIntent/ShowsSnippetView for interactive response cards, and entity view annotations for context-aware rendering
  • Part 4 — how Apple Intelligence routes requests to your app, how to write phrases that actually work, and where MCP Tools fit versus App Intents
  • Part 5 — how to test, debug, and ship: the Shortcuts app, unit testing, hardware requirements, and the common failure modes
  • Part 6 — six mistakes and exactly how to avoid them
  • Part 7 — concrete starting points for six app categories

Key Takeaways

  1. App Intents are your app's contract with Apple Intelligence. Every surface — Siri, Spotlight, Visual Intelligence — depends on how well you implement them.
  2. iOS 26's additions are additive. Your existing implementation doesn't break. You extend it.
  3. IntentValueQuery is the highest-leverage new addition for apps with visual content. Visual Intelligence is new real estate. Claim it early.
  4. Quality beats quantity. Fewer, better phrases. Fewer, more relevant query results. Smaller, more focused snippets.
  5. Test on real hardware. Visual Intelligence, Siri routing, and snippet rendering all behave differently in the actual system context than in unit tests.

Your Next Three Steps

Pick the one that fits your situation and start there.

If you're new to App Intents: write one intent, register it with three phrases, and test it in the Shortcuts app. Get that baseline working before adding anything else.

If you're upgrading an iOS 18 implementation: audit your AppEntity types for @DeferredProperty candidates first — it's the fastest win with the least risk. Then evaluate whether your app category benefits from IntentValueQuery.

If you're going all-in on iOS 26: start with IntentValueQuery (it's the most visible addition), layer in @DeferredProperty for expensive properties, then add snippets to your highest-value intents.


For further reference, see the App Intents framework documentation on Apple's developer portal, and WWDC25 Session 275: Explore new advances in App Intents.