← すべての記事

iOS 26のApp Intents 2.0:Visual Intelligence、インタラクティブスニペット、Deferred Property

App Intentsは、Shortcuts、Siri、Spotlight向けのAppleの構造化アクションAPIとしてiOS 16で登場し、iOS 17でApp Intents駆動のウィジェットへと拡張され、iOS 18ではApple Intelligenceのアクションサーフェスのコントラクトとなりました。iOS 26では、App IntentsをVisual Intelligence(サードパーティアプリからの画像検索結果)、インタラクティブスニペット(システムコンテキストに組み込まれる小さなポップアップUIウィンドウ)、エンティティビューアノテーション(エンティティをインラインで描画する方法)、@DeferredProperty(非同期で計算されるエンティティプロパティ)へと拡張しています1。これらの拡張はApp Intentsのコアモデルを変更するものではなく、アプリが採用できる新しい参加サーフェスを追加するものです。

本記事では、iOS 26の追加機能をAppleのドキュメントに沿って解説します。「既存のApp Intents採用が、iOS 26の準拠を追加することで得られる新しいサーフェスは何か」という観点で構成しています。なぜなら、App Intentsを採用しているほとんどのアプリでは基礎となる型がすでに整っており、iOS 26での作業はそれらの型を新しいコンテキストに拡張することが中心となるからです。

TL;DR

  • IntentValueQueryはVisual Intelligence統合のための新しいプロトコルです。クエリはSemanticContentDescriptor(ユーザーの視覚的コンテキスト)を受け取り、アプリが関連すると判断したAppEntityインスタンスの配列を返します2
  • @DeferredPropertyは値が非同期に計算されるエンティティプロパティを宣言します。プロパティはシステムが実際に必要とするときに読み込まれるため、表示用の軽量なフィールドが多数あり、計算コストの高いフィールドが数個あるエンティティで前払いコストを回避できます。
  • インタラクティブApp Intentsスニペットを使用すると、Spotlight、Visual Intelligence、Siri応答サーフェスといったシステムコンテキスト内で、ボタン、テキスト、コントロールを含む小さなポップアップウィンドウをアプリが提示できます。スニペットはApp Intentの結果にバインドされたSwiftUIビューです。
  • エンティティビューアノテーションを使うと、AppEntityが異なるシステムコンテキストでどのように描画されるか(Spotlightでのコンパクトな行、Visual Intelligenceでのヒーローカード、Live Activityスタイルのウィジェットなど)をアプリが宣言できます。
  • 本クラスタのApp Intents記事では基礎モデルを取り上げました。本記事ではそれをiOS 26の新しい参加サーフェスへと拡張します。本クラスタのApp Intents vs MCP Tools記事では、Apple Intelligenceのインテントサーフェスと汎用エージェントMCPツールとの間のルーティングの問題を扱っています。

Visual Intelligence:IntentValueQuerySemanticContentDescriptor

iOS 26におけるApp Intentsの目玉となる追加機能はVisual Intelligence統合です2。フローは次のとおりです。

  1. ユーザーが写真を撮影、スクリーンショットを取得、またはオブジェクトにカメラを向けます。
  2. システムのVisual Intelligenceレイヤーが視覚的および意味的コンテキスト(画像内に何があるか、ユーザーがそれについて何を求めているか)を抽出します。
  3. システムは、その意味的コンテキストでIntentValueQueryを登録したすべてのアプリにクエリを発行します。
  4. 各アプリは関連するAppEntityインスタンスを返します。システムはそれらを集約してVisual Intelligence UIに提示します。
  5. ユーザーがエンティティをタップすると、適切なコンテキストで起点となるアプリに入ります。

開発者向けのサーフェスは、SemanticContentDescriptorを受け取るvalues(for:)メソッドを持つIntentValueQueryに準拠した構造体です。

import AppIntents

struct ProductLookupQuery: IntentValueQuery {
    func values(for descriptor: SemanticContentDescriptor) async throws -> [Product] {
        // descriptor.labels: detected category and content labels
        // descriptor.pixelBuffer: the visual content as a CVReadOnlyPixelBuffer
        //                        (use VideoToolbox/CoreImage to convert if needed)
        let candidates = try await catalog.search(labels: descriptor.labels)
        return candidates.map(Product.init)
    }
}

SemanticContentDescriptorは、システムが値を設定する2つのフィールドを保持します。labels(「ワインボトル」「ピノ・ノワール」「ラベルテキスト」など、検出されたカテゴリおよびコンテンツタグの配列)と、pixelBuffer(コンテンツに対して独自のビジョンモデルを実行したいアプリのために、CVReadOnlyPixelBufferとして基礎となる画像データ)です。アプリの仕事は、これらのシグナルを自身のデータにマッピングし、一致するエンティティを返すことです。

正しい採用パターンは次のとおりです。ショッピングアプリは商品カタログに対してクエリを実装(視覚的コンテキスト → 一致する商品)、ワインアプリはボトルデータベースに対して(ラベル画像 → ワインエントリ)、レシピアプリはレシピライブラリに対して(食材の写真 → 一致するレシピ)。

@DeferredProperty:非同期エンティティ値

既存のAppEntity型はプロパティを静的に宣言します。エンティティが返される前に、すべてのプロパティを計算する必要があります。コストの異なるプロパティが混在するエンティティ(高速なtitle/subtitle/image、サーバーから取得する遅いdetailed-description)の場合、すべてを計算するか何もしないかという方式は無駄が生じます。

@DeferredProperty(iOS 26以降)は、プロパティを非同期に計算されるものとして宣言します3

import AppIntents

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

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

    @Property(title: "Cuisine")
    var cuisine: String

    @DeferredProperty(title: "Detailed Instructions")
    var instructions: String {
        get async throws {
            try await loadInstructionsFromBackend(id: id)
        }
    }
}

deferred propertyのゲッターは非同期です。システムが実際にその値を必要とするとき(例えば、エンティティが詳細表示のために選択されたとき)にのみ実行されます。クエリから返されたエンティティが選択UIにのみ使われる場合、deferred propertyは決して計算されません。

このパターンが適切なのは、構築の速いフィールド(id、title、summary)と構築コストの高いフィールド(本文全体、計算済みメトリクス、サーバーから取得するデータ)を併せ持つエンティティです。@DeferredPropertyがない場合、開発者はすべてを計算するか(無駄)、軽量なフィールドのみを計算して別途「詳細を読み込む」インテントを追加する(より複雑)かを選ぶことになります。

インタラクティブスニペットとSnippetIntent

iOS 26では、これまでのリリースから存在するShowsSnippetView準拠のAppIntentパターンに加えて、スニペット形式のインタラクション専用のSnippetIntentプロトコルが導入されました4SnippetIntentには静的なreload()メソッドが追加されており、システムはインテントを再呼び出しすることなくスニペットの内容を更新できます。

struct WeatherSnippet: SnippetIntent {
    static var title: LocalizedStringResource = "Weather Snippet"

    @Parameter(title: "City")
    var city: City

    func perform() async throws -> some IntentResult & ShowsSnippetView {
        let forecast = try await weatherService.forecast(for: city)
        return .result(view: ForecastSnippet(forecast: forecast))
    }

    static func reload() async throws {
        // Triggered by the system when it wants fresh snippet data
        // (e.g., after the data source signals an update)
    }
}

スニペット専用ではないインテントが応答にスニペットビューをアタッチしたい場合は、既存のAppIntent + ShowsSnippetViewパターンが引き続き使えます。

struct WeatherForecastIntent: AppIntent {
    static var title: LocalizedStringResource = "Weather Forecast"

    @Parameter(title: "City")
    var city: City

    func perform() async throws -> some IntentResult & ProvidesDialog & ShowsSnippetView {
        let forecast = try await weatherService.forecast(for: city)

        return .result(
            dialog: "Here's the forecast for \(city.name).",
            view: ForecastSnippet(forecast: forecast)
        )
    }
}

struct ForecastSnippet: View {
    let forecast: Forecast
    var body: some View {
        VStack(alignment: .leading) {
            Text(forecast.headline).font(.headline)
            HStack {
                ForEach(forecast.days) { day in
                    DayCell(day: day)
                }
            }
            Button("Open in App") {
                // App-launching action wired via App Intents
            }
        }
        .padding()
    }
}

結果型のShowsSnippetView準拠は、ダイアログと並べてSwiftUIビューを描画するようシステムに指示します。スニペットはインタラクティブです。内部のボタンは他のApp Intentsをトリガーでき、ユーザーはスクロールでき、ビューはシステムのインタラクションレイヤーに参加します。

インタラクティブスニペットがふさわしいケースは、天気予報、カレンダーイベント、交通機関の時刻、スポーツのスコア、荷物の追跡などです。システムサーフェスから1行のダイアログ応答以上のものをユーザーが求める場面ならどこでも有効です。

エンティティビューアノテーション

エンティティビューアノテーションを使うと、AppEntityが異なるシステムコンテキストでどのように描画されるかをアプリが宣言できます5。このメカニズムはDisplayRepresentationを複数のバリアントで拡張します。

struct Recipe: AppEntity {
    var displayRepresentation: DisplayRepresentation {
        DisplayRepresentation(
            title: "\(title)",
            subtitle: "\(cuisine) - \(time) min",
            image: .init(named: imageName)
        )
    }
}

従来のモデルは単一のDisplayRepresentationを返します。iOS 26では、エンティティが描画される場所(コンパクトリスト、ヒーローカード、Spotlight結果、Visual Intelligenceパネル)に基づいてシステムが選択できるよう、コンテキスト固有のバリアントを提供できます。フレームワークがコンテキストごとに正しいバリアントを選び、アプリは各バリアントを宣言します。

このパターンは、例えば密に並ぶSpotlightリストと単一カードのVisual Intelligence応答とでエンティティ描画を変える必要があるアプリをサポートします。アプリ側でコンテキストを検出する必要なく、バリアントを組み合わせられます。

既存のApp Intentsとの組み合わせ

iOS 26の追加機能は既存のApp Intentsプリミティブと組み合わさります。

  • アプリのAppShortcutsProviderAccessibility as platformで取り上げ)は、音声、アクションボタン、Spotlight向けのショートカットを登録します。
  • AppShortcutAppIntentを参照し、それはユーザーのリクエストから解決される@Parameterプロパティを持ちます。
  • AppIntent.perform()メソッドは、スニペットビュー(ShowsSnippetView)またはダイアログ(ProvidesDialog)を含められる結果型を返します。
  • インテントのパラメータが参照するAppEntity型は、@DeferredPropertyおよびエンティティビューアノテーションをサポートするようになりました。
  • 新しいIntentValueQuery型により、同じエンティティをVisual Intelligenceに登場させられます。

形としては、既存のモデルは保たれたまま、iOS 26の作業は同じエンティティサーフェスに新しい型(クエリ)と新しいアノテーション(deferred、ビューバリアント)を追加することです。

よくある失敗

App Intents 2.0の採用失敗から3つのパターンを挙げます。

スコープを絞らない結果を返すIntentValueQuery。記述子の検索語に一致するすべての商品を関連性に関係なく返すクエリは、Visual Intelligence体験を希薄化させます。修正:返される各エンティティがシステムUIで居場所を得られるよう、クエリのスコープを絞ります(上位N件の関連度、新しさで重み付け、ユーザーのパーソナライズ)。

軽量な値に対する@DeferredProperty。Deferredメカニズムは本当にコストの高い計算のためのものです。高速なインメモリのプロパティをdeferredとしてマークすると、メリットなしに非同期のオーバーヘッドが加わります。修正:@DeferredPropertyは、deferredにすることで実際に効果が出るプロパティ(サーバー取得、大きな計算、MLモデル呼び出し)に限定します。

フルアプリのようなインタラクティブスニペット。スニペットはコンパクトなUIサーフェスです。ミニアプリとして扱うと、窮屈に感じられたり描画が遅かったりするスニペットになります。修正:スニペットは即時の応答と1つか2つの関連アクションに絞り、複雑なフローはフルアプリに引き渡すために「Open in App」ボタンを使います。

このパターンがiOS 26+アプリにとって意味すること

3つのテイクアウェイ。

  1. ビジュアルコンテンツを持つアプリにはIntentValueQueryを追加する。ショッピング、レシピ、商品、場所、識別可能なオブジェクト。Visual Intelligence統合は新たな発見サーフェスです。参加しないアプリはそこでは見えません。

  2. コストの高いエンティティフィールドには@DeferredPropertyを使う。詳細な説明、計算済みメトリクス、サーバーから取得するデータ。デフォルト非同期のパターンはモダンなSwiftコードと整合し、軽量なエンティティ返却を高速に保ちます。

  3. 価値の高いクエリ型にはインタラクティブスニペットを採用する。天気、カレンダー、交通、スポーツ、荷物追跡。1行のダイアログでは足りないがフルアプリ起動はやり過ぎ、というケースで、スニペットUIはユーザーをシステム応答サーフェスに留めます。

Apple Ecosystemクラスタの全体:型付きのApp IntentsMCPサーバールーティングの問題Foundation Modelsランタイム vs ツーリングのLLM区別3つのサーフェス単一の信頼できる情報源パターン2つのMCPサーバーApple開発のためのフックLive ActivitieswatchOSランタイムSwiftUIの内部RealityKitの空間メンタルモデルSwiftDataスキーマ規律Liquid Glassパターンマルチプラットフォーム展開プラットフォームマトリックスVisionフレームワークSymbol EffectsCore MLによる推論Writing Tools APISwift TestingPrivacy ManifestAccessibility as platformSF ProタイポグラフィvisionOSの空間パターンSpeechフレームワークSwiftDataマイグレーションtvOSフォーカスエンジン@Observableの内部SwiftUI LayoutプロトコルカスタムSF SymbolsAVFoundation HDRwatchOSワークアウトライフサイクル書かないと決めていること。ハブはApple Ecosystem Seriesにあります。AIエージェントとiOSの広い文脈については、iOS Agent Developmentガイドを参照してください。

FAQ

IntentValueQueryをテストするためにApple Intelligenceを有効化する必要はありますか?

完全なVisual Intelligenceテストには必要です。Visual Intelligenceには、Apple Intelligence対応ハードウェア(iPhone 15 Pro以降、M1 Mac以降)、iOS 26以降、Apple Intelligenceの有効化が必要です。開発時には、SemanticContentDescriptorを直接構築してクエリのvalues(for:)メソッドを呼び出すことで、システムスタック全体なしにユニットテストでクエリを検証できます。

@DeferredPropertyはthrowできますか?

はい。非同期ゲッターのシグネチャはget async throwsで、例外はシステムに伝播します。システムは、deferred propertyの値なしでエンティティを表示する(または一部のコンテキストではエラー状態を表示する)ことで失敗を扱います。アプリはクラッシュではなく、適切に失敗して意味のあるエラー状態を返すようにすべきです。

インタラクティブスニペットのコンテンツはアニメーションをサポートしますか?

はい、標準のSwiftUIアニメーションプリミティブで対応できます。スニペットのビューはシステムの応答サーフェスで実行され、アプリ内SwiftUIと同じアニメーション基盤をサポートします。プラットフォーム規約に合うアニメーション語彙については、本クラスタのSymbol Effects記事を参照してください。

エンティティビューアノテーションはウィジェットとどのように関係しますか?

ウィジェットは別個のWidgetKitサーフェスです。エンティティビューアノテーションはApp Intentsのコンテキスト内(Spotlight、Visual Intelligence、Siri応答)で適用されます。同じデータをAppEntityとウィジェットの両方で公開するアプリでは、2つのサーフェスは別々のUI宣言を必要とします。通常は基礎となるデータモデルを共有し、サーフェスごとに薄いプレゼンテーションビューを書きます。

これとMCPツールの関係は?

App IntentsはApple Intelligenceのインテントサーフェスであり、MCPツールは汎用LLM向けのエージェント・サーバープロトコルです。iOS 26はApp IntentsにVisual Intelligenceを追加します(Appleのサーフェス)。Apple以外のエージェント(Claude、GPTクラス)には、ローカルまたはリモートで実行されるMCPツールが同じ概念領域をカバーします。本クラスタのApp Intents vs MCP Tools記事でルーティングの問題を扱っています。

IntentValueQueryEntityQueryと組み合わせられますか?

はい。両者は異なるサーフェスを担います。EntityQueryはユーザーがエンティティ名を入力または発話する場合(Spotlight、Siri)向け、IntentValueQueryはユーザーが画像コンテキストを伴うVisual Intelligenceにいる場合向けです。アプリのAppEntityは両方のクエリを登録でき、システムはコンテキストに合わせて正しい方を選びます。

References


  1. Apple Developer Documentation: App Intents. The framework reference covering AppIntent, AppEntity, queries, parameters, and the iOS 26 additions. 

  2. Apple Developer: Explore new advances in App Intents (WWDC 2025 session 275). The introduction of IntentValueQuery, SemanticContentDescriptor, and Visual Intelligence integration. 

  3. Apple Developer Documentation: @DeferredProperty(). The async-computed entity property macro introduced for App Entities in iOS 26. Coverage in WWDC 2025 session 275 (Explore new advances in App Intents). 

  4. Apple Developer Documentation: Interactive App Intents Snippets via the ShowsSnippetView result type combined with SwiftUI views that render in system contexts (Spotlight, Visual Intelligence, Siri response area). 

  5. Apple Developer Documentation: DisplayRepresentation and entity view annotations. The mechanism for declaring how an AppEntity renders in different system contexts. 

関連記事

App Intents vs MCP: The Routing Question

Two protocols, one app. App Intents expose your app to Apple Intelligence. MCP exposes the same domain to Claude, ChatGP…

16 分で読める

Three Surfaces: Human, Apple Intelligence, Agent

Every iOS app capability faces three surfaces: human, Apple Intelligence, agent. Each has different obligations, renderi…

17 分で読める

The Cleanup Layer Is the Real AI Agent Market

Charlie Labs pivoted from building agents to cleaning up after them. The AI agent market is moving from generation to pr…

15 分で読める