# How to Implement App Intents and App Shortcuts in iOS Applications

> Learn how to implement App Intents and App Shortcuts in iOS applications. Define Swift structs, register them, and execute logic for seamless user experiences and enhanced app functionality.

- Repository: [OpenAI/plugins](https://github.com/openai/plugins)
- Tags: how-to-guide
- Published: 2026-07-04

---

**Implement App Intents and App Shortcuts in iOS applications by defining Swift structs that conform to `AppIntent`, registering them via `AppShortcutsProvider`, and executing logic either inline through `perform()` or via an app hand-off routed by an observable manager.**

The `openai/plugins` repository provides production-ready reference implementations for integrating App Intents into iOS projects, specifically within `plugins/build-ios-apps/skills/ios-app-intents/`. According to the source code in [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md) and [`code-templates.md`](https://github.com/openai/plugins/blob/main/code-templates.md), the architecture separates intent definitions, entity models, and shortcut registration into three distinct layers. This guide demonstrates how to expose high-value app actions to Shortcuts, Siri, Spotlight, and widgets without requiring users to navigate your full UI.

## Core Architecture of App Intents

The implementation consists of three primary layers that work together to bridge your app with iOS system surfaces.

**Intent definitions** are lightweight Swift structs conforming to `AppIntent` (or `WidgetConfigurationIntent`) that declare a title, description, parameters, and the `openAppWhenRun` property. **Entity and query models** are optional `AppEntity` types representing domain objects like workspaces or projects, paired with `EntityQuery` implementations that supply suggestions to the system. **App shortcuts providers** are types conforming to `AppShortcutsProvider` that register `AppShortcut` objects linking intents to user-facing phrases and system images.

This architecture is documented in [`plugins/build-ios-apps/skills/ios-app-intents/SKILL.md`](https://github.com/openai/plugins/blob/main/plugins/build-ios-apps/skills/ios-app-intents/SKILL.md) and illustrated with concrete Swift templates in [`plugins/build-ios-apps/skills/ios-app-intents/references/code-templates.md`](https://github.com/openai/plugins/blob/main/plugins/build-ios-apps/skills/ios-app-intents/references/code-templates.md).

## Creating Open-App Handoff Intents

When an action requires UI presentation or navigation to a specific screen, set `openAppWhenRun = true` and use a hand-off pattern. This allows the intent to execute lightweight validation before transferring control to your app's scene.

The following implementation from [`code-templates.md`](https://github.com/openai/plugins/blob/main/code-templates.md) (lines 5-33) demonstrates an intent that opens the app to a composer view:

```swift
import AppIntents

struct OpenComposerIntent: AppIntent {
    static let title: LocalizedStringResource = "Open composer"
    static let description = IntentDescription("Open the app to compose content")
    static let openAppWhenRun = true          // opens the app

    @Parameter(title: "Prefilled text",
               inputConnectionBehavior: .connectToPreviousIntentResult)
    var text: String?

    func perform() async throws -> some IntentResult {
        await MainActor.run {
            AppIntentRouter.shared.handledIntent = .init(intent: self)
        }
        return .result()
    }
}

```

The `perform()` method sets a hand-off object on a shared router observable by your app's scene, then returns an empty `IntentResult` to signal completion.

## Routing Intents to Your UI

To handle the hand-off from the previous example, implement an `AppIntentRouter` that your scene delegate observes. This pattern separates intent handling from UI presentation logic.

```swift
import AppIntents
import Observation

@Observable
final class AppIntentRouter {
    struct HandledIntent: Equatable {
        let id = UUID()
        let intent: any AppIntent
        static func == (lhs: Self, rhs: Self) -> Bool { lhs.id == rhs.id }
    }
    static let shared = AppIntentRouter()
    var handledIntent: HandledIntent?
    private init() {}
}

```

In your scene delegate, monitor `AppIntentRouter.shared.handledIntent` and call `handleIntent()` to route to the appropriate view controller based on the intent type.

## Implementing Inline Action Intents

For actions that complete without UI—such as creating a database record or toggling a setting—set `openAppWhenRun = false`. The `perform()` method executes entirely in the background and returns a result with an optional dialog.

This example from [`code-templates.md`](https://github.com/openai/plugins/blob/main/code-templates.md) (lines 64-88) shows an inline creation intent:

```swift
import AppIntents

struct CreateItemIntent: AppIntent {
    static let title: LocalizedStringResource = "Create item"
    static let description = IntentDescription("Create a new item without opening the app")
    static let openAppWhenRun = false          // stays in the background

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

    @Parameter(title: "Workspace")
    var workspace: WorkspaceEntity

    func perform() async throws -> some IntentResult & ProvidesDialog {
        do {
            try await ItemService.shared.createItem(title: title,
                                                    workspaceID: workspace.id)
            return .result(dialog: "Created \(title).")
        } catch {
            return .result(dialog: "Could not create the item. Please try again.")
        }
    }
}

```

The `ProvidesDialog` protocol allows the intent to return spoken feedback to the user via Siri or displayed confirmation in Shortcuts.

## Defining AppEntity and EntityQuery for Domain Objects

When intents operate on specific domain objects, define `AppEntity` conforming types to represent them. These entities provide display representations and unique identifiers that the system uses in Shortcuts interfaces and Siri disambiguation.

The following pattern from [`code-templates.md`](https://github.com/openai/plugins/blob/main/code-templates.md) (lines 37-48) implements a workspace entity:

```swift
import AppIntents

struct WorkspaceEntity: AppEntity, Identifiable {
    let workspace: Workspace
    var id: String { workspace.id }

    static let typeDisplayRepresentation = TypeDisplayRepresentation("Workspace")
    static let defaultQuery = WorkspaceQuery()

    var displayRepresentation: DisplayRepresentation {
        DisplayRepresentation(title: "\(workspace.name)")
    }
}

```

Pair the entity with a query implementation that fetches specific identifiers and provides suggestions:

```swift
struct WorkspaceQuery: EntityQuery {
    func entities(for identifiers: [WorkspaceEntity.ID]) async throws -> [WorkspaceEntity] {
        let workspaces = try await WorkspaceStore.shared.workspaces(matching: identifiers)
        return workspaces.map(WorkspaceEntity.init)
    }
    // suggestedEntities & defaultResult implementations omitted for brevity
}

```

## Registering Discoverable Shortcuts

To make intents available in the Shortcuts app, Siri, and Spotlight, implement an `AppShortcutsProvider`. This static provider declares the phrases users can speak and the system images representing each action.

This registration pattern from [`code-templates.md`](https://github.com/openai/plugins/blob/main/code-templates.md) (lines 41-68) links intents to discoverable phrases:

```swift
import AppIntents

struct AppShortcuts: AppShortcutsProvider {
    static var appShortcuts: [AppShortcut] {
        [
            AppShortcut(
                intent: OpenComposerIntent(),
                phrases: [
                    "Open composer in \(.applicationName)",
                    "Draft with \(.applicationName)"
                ],
                shortTitle: "Open composer",
                systemImageName: "square.and.pencil"
            ),
            AppShortcut(
                intent: CreateItemIntent(),
                phrases: [
                    "Create item with \(.applicationName)",
                    "Add a task in \(.applicationName)"
                ],
                shortTitle: "Create item",
                systemImageName: "plus.circle"
            )
        ]
    }
}

```

Registering shortcuts does not require submitting to the App Store; the system indexes them locally based on this provider.

## Implementation Workflow Checklist

According to [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md) in the openai/plugins repository, follow this architectural workflow:

1.  **Identify high-value actions** (verbs) that users need outside the UI, starting with actions rather than screens (`SKILL.md#L20-L24`).
2.  **Define minimal `AppEntity` types** for objects the system must understand, keeping the entity surface small (`SKILL.md#L25-L29`).
3.  **Choose execution context** by setting `openAppWhenRun` to `true` for hand-off intents or `false` for inline execution (`SKILL.md#L30-L34`).
4.  **Register shortcuts via `AppShortcutsProvider`** to surface intents in system locations (`SKILL.md#L36-L40`).
5.  **Implement `perform()` validation** to handle runtime logic or prepare the hand-off object (`SKILL.md#L42-L45`).

For additional guidance on system surfaces and release checklists, consult [`plugins/build-ios-apps/skills/ios-app-intents/references/system-surfaces.md`](https://github.com/openai/plugins/blob/main/plugins/build-ios-apps/skills/ios-app-intents/references/system-surfaces.md) and [`first-pass-checklist.md`](https://github.com/openai/plugins/blob/main/first-pass-checklist.md).

## Summary

- **App Intents** are defined as Swift structs conforming to `AppIntent`, exposing specific actions to iOS system surfaces without full UI launches.
- **Open-app handoffs** use `openAppWhenRun = true` and an `AppIntentRouter` observable to transfer execution to your scene, while **inline actions** set `openAppWhenRun = false` and return `IntentResult` directly.
- **AppEntity** and **EntityQuery** model domain objects for parameterized intents, providing display representations and suggestion logic to the system.
- **AppShortcutsProvider** registers intents with user-facing phrases and system images, making them discoverable in Shortcuts, Siri, and Spotlight.
- Reference templates and architectural guidance are available in [`plugins/build-ios-apps/skills/ios-app-intents/references/code-templates.md`](https://github.com/openai/plugins/blob/main/plugins/build-ios-apps/skills/ios-app-intents/references/code-templates.md) and [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md).

## Frequently Asked Questions

### What is the difference between `openAppWhenRun` set to true versus false?

When `openAppWhenRun` is `true`, the intent prepares data (such as setting `AppIntentRouter.shared.handledIntent`) and the system launches your app's UI, allowing your scene delegate to handle navigation. When `false`, the intent executes the `perform()` method entirely in the background without launching the app, suitable for database writes or API calls that return immediate confirmation dialogs.

### Do I need to define `AppEntity` types for every intent?

No, `AppEntity` types are only required when your intent operates on specific domain objects that users must select from a list or reference by identifier. Simple intents that create new objects or perform global actions can use primitive parameters like `String` or `Int` without defining custom entities, as shown in the `CreateItemIntent` example.

### How does the system discover my App Intents?

The system discovers intents through a concrete implementation of `AppShortcutsProvider`, which you define with a static `appShortcuts` property containing `AppShortcut` instances. Each shortcut links an intent to trigger phrases and a system image, registering them with the Shortcuts app and Siri without requiring server-side configuration or App Store submission.

### Where can I find the reference templates for App Intents implementation?

Complete Swift templates for intents, entities, queries, and shortcuts are located in [`plugins/build-ios-apps/skills/ios-app-intents/references/code-templates.md`](https://github.com/openai/plugins/blob/main/plugins/build-ios-apps/skills/ios-app-intents/references/code-templates.md) within the openai/plugins repository. Architectural guidance and workflow checklists are available in [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md), [`system-surfaces.md`](https://github.com/openai/plugins/blob/main/system-surfaces.md), and [`first-pass-checklist.md`](https://github.com/openai/plugins/blob/main/first-pass-checklist.md) in the same directory.