iOS 27 extends App Intents with advanced features including custom Siri dialog responses, interaction donations for learning user preferences, OwnershipProvidingEntity for smarter confirmations, IndexedEntityQuery for Spotlight reindexing, and structured/in-app search integration.
โข New IntentDonationManager API allows donating schema-conforming intents from app UI interactions so Apple Intelligence can learn user preferences
โข New OwnershipProvidingEntity protocol lets entities declare public/shared ownership state, enabling Siri to decide when confirmation dialogs are necessary
โข Custom snippet views (ShowsSnippetView) can now be returned directly from intent perform methods as SwiftUI views
โข New IndexedEntityQuery protocol supports Spotlight-triggered reindexing of app entities separately from Core Spotlight APIs
โข Interaction donations let Apple Intelligence learn from in-app UI actions โ not just Siri calls โ so it can predict the right app and contact for voice requests
โข OwnershipProvidingEntity tells Siri whether shared/public content needs explicit user confirmation before modification, reducing unintended side effects from LLM-driven actions
โข Custom dialog responses, snippet views, and entity DisplayRepresentation let your app's personality and branding shine inside Siri rather than using generic system UI
Demonstrates donating a SendMessageIntent from the app's UI so Apple Intelligence learns which contacts a user prefers to message through the app, using IntentDonationManager.
import AppIntents+import CoreSpotlightโ// Pre-iOS 27: No interaction donation API existed.โ// Developers could only expose actions via Siri/Shortcuts directly;โ// Apple Intelligence had no way to learn from in-app UI behavior.โ// The only option was to conform to AppIntent and let users invoke via Siri:+// MARK: - Entity with Ownership+struct MessageRecipient: AppEntity, OwnershipProvidingEntity {+ static var typeDisplayRepresentation = TypeDisplayRepresentation(name: "Recipient")+ static var defaultQuery = MessageRecipientQuery()++ var id: String+ var name: String+ var isSharedContact: Bool++ var displayRepresentation: DisplayRepresentation {+ DisplayRepresentation(+ title: "\(name)",+ subtitle: isSharedContact ? "Shared contact" : "Private contact",+ image: .init(systemName: isSharedContact ? "person.2.fill" : "person.fill")+ )+ }++ // OwnershipProvidingEntity: tell Siri if this entity is shared/public+ var ownershipState: EntityOwnershipState {+ isSharedContact ? .owned : .notOwned+ }+}++struct MessageRecipientQuery: EntityQuery {+ func entities(for identifiers: [String]) async throws -> [MessageRecipient] {+ identifiers.map { MessageRecipient(id: $0, name: "Contact \($0)", isSharedContact: false) }+ }+}++// MARK: - Intent+struct SendMessageIntent: AppIntent {static var title: LocalizedStringResource = "Send Message"+ static var description = IntentDescription("Send a message to a contact.")@Parameter(title: "Recipient")โ var recipientName: String+ var recipient: MessageRecipient@Parameter(title: "Message")var messageBody: Stringโ func perform() async throws -> some IntentResult {โ // Send the messageโ // Return empty result โ Siri wrote its own generic responseโ return .result()+ func perform() async throws -> some ProvidesDialog {+ // Actually send the message here+ return .result(dialog: IntentDialog(+ full: "Sent '\(messageBody)' to \(recipient.name).",+ supporting: "Message sent!"+ ))}}โ// No IntentDonationManager existed โ Apple Intelligence could notโ// learn from actions taken inside the app's own UI.โ// No OwnershipProvidingEntity protocol โ Siri could not distinguishโ// shared vs private entities for confirmation decisions.โ// No IndexedEntityQuery โ reindexing required Core Spotlight APIs directly.+// MARK: - Donation from UI++final class ConversationViewModel: ObservableObject {+ /// Called from the app's compose UI โ NOT from an intent+ func sendMessage(to recipient: MessageRecipient, body: String) async {+ // 1. Perform the actual send+ await performActualSend(recipient: recipient, body: body)++ // 2. Donate to Apple Intelligence so it learns this preference+ var intent = SendMessageIntent()+ intent.recipient = recipient+ intent.messageBody = body++ // IntentDonationManager is new in iOS 27+ try? await IntentDonationManager.shared.donate(intent: intent)+ }++ private func performActualSend(recipient: MessageRecipient, body: String) async {+ // Real send logic here+ }+}++// MARK: - IndexedEntityQuery for Spotlight reindexing (new in iOS 27)++struct IndexedMessageRecipientQuery: IndexedEntityQuery {+ typealias Entity = MessageRecipient++ func entities(for identifiers: [String]) async throws -> [MessageRecipient] {+ identifiers.map { MessageRecipient(id: $0, name: "Contact \($0)", isSharedContact: false) }+ }++ // Called by Spotlight when it needs a full reindex+ func suggestedEntities() async throws -> [MessageRecipient] {+ // Return all entities to index+ return [+ MessageRecipient(id: "1", name: "Alice", isSharedContact: false),+ MessageRecipient(id: "2", name: "Bob", isSharedContact: true)+ ]+ }+}
Interaction donations should only be made for genuine UI-initiated user actions โ excessive donations will be ignored by the system. OwnershipProvidingEntity should only be applied to entities users can actually share or make public. Custom snippet views must be SwiftUI views and scale appropriately for voice-only devices like AirPods where visuals are not shown.
Apple Intelligence features (interaction donation learning, semantic search) require Apple Intelligence-compatible devices; custom views and dialog responses work on all iOS 27 devices
More iOS 27 APIs land every week.
Get notified when new capabilities are published โ no noise, just signal.