Architecture • 21 July 2026 • Written by Lochan Chugh

SiriKit to App Intents Migration: The Complete Playbook for iOS 27

SiriKit to App Intents Migration: The Complete Playbook for iOS 27

⚠️ Speculative Architecture & Preview: This article discusses future system iterations (e.g., iOS 27, Xcode 27) as conceptual planning and architectural design patterns. Technical details represent previews and proposals rather than finalized APIs.

SiriKit to App Intents Migration: The Complete Playbook for iOS 27

The formal deprecation of SiriKit marks a significant shift in how applications integrate with Apple’s assistant ecosystem. With iOS 27, apps that do not complete the SiriKit deprecation migration path will lose integration with Siri, Spotlight, and Apple Intelligence. This transition requires developers to rebuild integration models around the App Intents framework. This App Intents migration playbook details the technical steps needed to replace legacy handlers, map custom vocabularies to entity schemas, and register app states with the system’s semantic index using ValueRepresentation and RelevantEntities.

Key Takeaways

  • Architecture Modernization: Shifts from out-of-process SiriKit Extensions (INIntent) to target-embedded App Intents (AppIntent) executed in-process.
  • Semantic Index Registration: Exposes local databases and entities directly to Siri’s parser using RelevantEntities declarations.
  • Value Serialization: Employs ValueRepresentation protocols to define how custom structures are rendered and serialized across system interfaces.
  • State Synchronization: Eliminates intent handler class instances, replacing them with declarative structs conforming to modern Swift Concurrency.
  • Migration Overhead: Requires mapping legacy plist-based vocabulary catalogs to native Swift code, which must be updated manually.

The “Why”: In-Process Execution and Apple Intelligence

Under the legacy SiriKit framework, integrating with Siri required adding an Intent App Extension to your project bundle. When a user invoked a Siri command, the system launched this extension in a separate background process, passed it an INIntent object, and waited for an INIntentResponse. While this isolated extension execution from the main application, it introduced significant IPC overhead, forced developers to duplicate database access logic across targets, and made it difficult to share UI components.

+-------------------------------------------------------------+
|                      Apple Intelligence                     |
+-------------------------------------------------------------+
                               |
                               v (App Intents Engine / Semantic Index)
+-------------------------------------------------------------+
|                   Unified App Intents Runtime               |
|   - In-Process Execution (Zero IPC Copy Overhead)           |
|   - Entity Resolution via AppEntity & AppEntityQuery        |
|   - ValueRepresentation Formatting                          |
+-------------------------------------------------------------+
                               |
                               v (Main Application Process)
+-------------------------------------------------------------+
|                    Application Sandbox                      |
|   - Native Swift 6 AppIntent Structs                        |
|   - Local Database (Shared Memory Namespace)                |
+-------------------------------------------------------------+

With App Intents, the architecture is simplified. The system runs intents in-process within your main application or via targeted frameworks. This change removes IPC data copying, allowing intents to access the application’s memory space and shared database connections directly.

Additionally, App Intents is built to support Apple Intelligence. Rather than relying on rigid, pre-defined intent categories (like sending messages or booking rides), Apple Intelligence parses user requests using a local semantic index. To make your app’s data visible to this index, you must expose your data models using the AppEntity protocol. By registering these entities with the system, Apple Intelligence can understand user context and resolve intents dynamically, even if the user uses conversational phrasing instead of precise commands.


The Migration Playbook: Step-by-Step Transition

Migrating a legacy SiriKit codebase to the modern App Intents framework requires structured steps:

1. Mapping Vocabularies to Entity Schemas

If your app utilizes custom SiriKit vocabulary files (AppIntentVocabulary.plist), you must translate these strings into native Swift schemas. Create an AppEntity struct for each data model, using @Property wrappers to expose properties to the system parser.

2. Replacing Intent Handlers with AppIntent Structs

Convert your legacy INIntentHandler classes into declarative AppIntent structs. Instead of implementing delegate methods like confirm(intent:completion:) and handle(intent:completion:), implement the perform() method to execute your logic and return a result.

3. Exposing Entities via Queries

For each AppEntity, implement an AppEntityQuery to resolve inputs. The query is responsible for returning matching entity instances when a user references them in a command (e.g., resolving the name “Steve” to a specific contact ID).


Implementing App Intents, Queries, and Representations

The following Swift 6 implementation shows how to migrate a legacy task-tracking intent to the App Intents framework. This code defines a custom TaskEntity, registers a query resolver, configures ValueRepresentation and RelevantEntities schemas, and implements the execution logic.

import Foundation
import AppIntents

// Unique identifier for the database schema
public struct TaskIdentifier: Codable, Sendable, Hashable {
    public let rawValue: UUID
}

// Custom model representing an App Entity exposed to Apple Intelligence
public struct TaskEntity: AppEntity {
    public static var defaultQuery = TaskEntityQuery()
    public static var typeDisplayRepresentation: TypeDisplayRepresentation = "Project Task"
    
    public let id: TaskIdentifier
    
    @Property(title: "Task Title")
    public var title: String
    
    @Property(title: "Is Completed")
    public var isCompleted: Bool
    
    public init(id: TaskIdentifier, title: String, isCompleted: Bool) {
        self.id = id
        self.title = title
        self.isCompleted = isCompleted
    }
    
    // Defines how the entity is presented across system UIs (ValueRepresentation)
    public var displayRepresentation: DisplayRepresentation {
        DisplayRepresentation(
            title: "\(title)",
            subtitle: isCompleted ? "Completed" : "Active"
        )
    }
}

// Query resolver used by Apple Intelligence to find matching tasks
public struct TaskEntityQuery: EntityQuery {
    public typealias Entity = TaskEntity
    
    public init() {}
    
    /// Finds a specific task by its unique ID
    public func entities(for ids: [TaskIdentifier]) async throws -> [TaskEntity] {
        // In a real application, fetch records from your local database
        return ids.map { TaskEntity(id: $0, title: "Fetched Task \($0.rawValue)", isCompleted: false) }
    }
    
    /// Resolves string-based search inputs from conversational queries
    public func suggestedEntities() async throws -> [TaskEntity] {
        return [
            TaskEntity(id: TaskIdentifier(rawValue: UUID()), title: "Review Pull Request", isCompleted: false),
            TaskEntity(id: TaskIdentifier(rawValue: UUID()), title: "Update Documentation", isCompleted: true)
        ]
    }
}

// App Intent replacing the legacy INCreateNoteIntent or INAddTaskIntent
public struct CreateTaskIntent: AppIntent {
    public static var title: LocalizedStringResource = "Create Project Task"
    public static var description = IntentDescription("Creates a new task in the local project board.")
    
    @Parameter(title: "Task Title")
    public var title: String
    
    @Parameter(title: "Target Project ID", default: nil)
    public var projectID: String?
    
    public init() {}
    
    public init(title: String, projectID: String? = nil) {
        self.title = title
        self.projectID = projectID
    }
    
    /// Executes the intent logic in the application's process space
    public func perform() async throws -> some IntentResult & ReturnsValue<TaskEntity> {
        let taskID = TaskIdentifier(rawValue: UUID())
        let createdTask = TaskEntity(id: taskID, title: title, isCompleted: false)
        
        // Save the entity to the application's database
        // DatabaseManager.shared.save(createdTask)
        
        // Notify the system about the new entity to update the semantic index
        try await updateRelevantEntities()
        
        return .result(value: createdTask)
    }
    
    /// Registers the updated task state with the system semantic index
    private func updateRelevantEntities() async throws {
        let taskID = TaskIdentifier(rawValue: UUID())
        let activeTask = TaskEntity(id: taskID, title: title, isCompleted: false)
        
        // Configure relevant entity properties for Apple Intelligence
        let relevantTask = RelevantEntity(
            activeTask,
            situation: .activeScenario,
            relevanceScore: 0.95
        )
        
        // Publish the entity state to the system
        try await RelevantEntities.update([relevantTask])
    }
}

// Extension to map custom scenarios to system situations
extension RelevantEntitySituation {
    public static var activeScenario: RelevantEntitySituation {
        RelevantEntitySituation(rawValue: "com.iosdev.task.active")
    }
}

Syncing with the Semantic Index

The system’s semantic index acts as a local database where Apple Intelligence stores information about your application’s data. When you call RelevantEntities.update(), you write entity metadata directly to this index.

This synchronization is critical for:

  1. Conversational Relevance: If a user asks Siri, “What is next on my checklist?”, Apple Intelligence scans the semantic index for high-relevance entities from task-management apps.
  2. Context-Aware Suggestions: Spotlight uses relevant entity states to suggest quick actions on the home screen based on the user’s current situation (e.g., location, time of day).
  3. Cross-App Workflows: Exposing your data via entities allows other applications to reference your app’s content in multi-step automation scripts and shortcuts.

Ensure that you remove completed or deleted entities from the index. Stale metadata will confuse the LLM, leading to validation errors and incorrect tool execution paths.


The Verdict: Evaluating On-Device AI Trade-offs

  • When to Use:

    • Modernizing applications for iOS 27 to maintain compatibility with Siri and Spotlight search.
    • Applications managing user-generated content that would benefit from voice-driven workflows.
    • System utility apps that integrate with the Shortcuts app to enable multi-step automation.
  • When NOT to Use:

    • Legacy enterprise applications deployed on managed devices running older iOS versions.
    • Games or graphic-heavy applications that do not expose structured data models to the user.
    • Simple utility apps where the voice interaction surface is too narrow to justify the development effort.
  • The Hidden Cost:

    • Debugging Tooling Overhead: In-process intent execution is faster, but debugging conflicts between the application UI thread and system intent threads requires careful design to prevent thread blocks and race conditions.
    • Database Synchronization Lag: Updating the semantic index via RelevantEntities is asynchronous. If the user triggers an intent immediately after modifying data in the app UI, the local index may return outdated state.

Ready for more depth?

Master these concepts with our structured technical roadmap.

View Roadmap