モバイルアプリを使用する際、必ずしも人間が操作するとは限らない時代になってきました。人間の指示を受けたAIがアプリの機能を呼び出し、使用するケースが今後もっと増えていくことでしょう。
9月14日に配信されたiOS 27では「Siri AI」が登場、これまでのSiriよりも一層賢くアプリの機能を呼び出せるようになりました(配信時点では英語のみで、beta という位置づけです)。Androidにも AppFunctions があり、こちらはライブラリがまだ alpha で対象アプリも限られていますが、一部の端末・アプリでは実際に呼び出せます。
このようにAIがアプリを操作するようになったときに、モバイルアプリのインターフェースと設計はどう変わるのでしょうか。
結論からいうと、アプリの入口が画面だけではなくなるので、ロジックを画面から切り離しておくことが必須になるのではないか、と思っています。
※この記事でいう「インターフェース」は画面(GUI)に限らず、人間やAIがアプリの機能と相互にやり取りする接点全般を指します。
アプリを操作するのは「人間」から「人間 or AI」に
これからは、アプリを操作する主体として以下の2つを想定する必要があります。
- 人間が操作する。これまでどおり、人間が画面から操作する
- AIが操作する。人間がAIに目的を伝え、AIがアプリの機能を呼ぶ
※この記事内で「AIが操作する」と表現する際は、アプリが宣言した機能をAIが直接呼び出す場合に限定します。(ブラウザを自動で動かすエージェントのように、AIが人間用の画面をクリックしていくケースは含めません)
この変化は、UIの歴史の中で大きな区切りにあたります。ウェブユーザビリティ研究の第一人者であるヤコブ・ニールセン(Jakob Nielsen)は、コマンドライン、テキスト端末、GUI を、どれも「人間がコマンドでひとつずつ操作する方式」と分類しています(AI: First New UI Paradigm in 60 Years)。見た目は変わっても、人間がひとつずつ指示する点は60年変わっていない、ということです。
ところが、AIの登場により、人間が最終目的だけを指示する方式が登場しました。人が直接一つ一つの操作を行うことはなく、一連の機能の呼び出しはAIに任せられます。
このような操作の流れを「経路」と呼びましょう。人間が操作する経路と、AIが操作する経路を図にまとめるとこのようになります。

人間が操作する経路では、人間は画面を通じてアプリの機能を呼び出します。AIが操作する経路では、人間の指示をもとにAIが画面を通さずにアプリの機能を呼び、その結果も画面を通さずにAIが受け取ります。
AI・アプリ間のインターフェースの変遷
このときAIが使用できる機能は、アプリ側があらかじめ宣言した機能に限られます。AIにとっては、この「機能の宣言」が、アプリの入口となるわけです。
このAI側から見たアプリの入口について、もう少し詳しく見ていきましょう。
AIはどうやってアプリの機能を呼ぶのか
iOSを例に説明します。あなたがSiriに指示を出したとき、Siriはこんなふうに機能を探します。
- iOS 16(2022年): Siriは、アプリ開発者があらかじめ準備した想定フレーズに照らし合わせて機能を呼び出します。Apple のドキュメントでも "preconfigured"(あらかじめ設定された)shortcut と書かれています
- iOS 18(2024年): アプリの宣言に書かれた機能名や説明をApple Intelligence が読むため、Siriはユーザーの自由な言葉遣いの指示をもとに、呼び出す機能を選べるようになりました。
iOS 27 の新しいSiriも、iOS 18と同じような仕組みの上で動いています。また、AndroidのAppFunctionsも考え方は近いものです。
つまり、「決められた呼び出し方に一致させる」方式から、「アプリ側の機能の宣言を読み、ユーザーの自然な指示にあわせて適切な機能を選ぶ」方式へ移ってきた、と考えることができます。
このように、AI側の機能の呼び出し方法は大きく変わりました。一方で、アプリ側はどうでしょうか。アプリ側の「機能の宣言」についても見ていきましょう。
アプリはどう機能を宣言してきたか
アプリ側が書く宣言の形は、実は2022年から変わっていません。iOSでは App Intents と呼ばれ、名前、説明、型付きの引数、という形です。iOS 18 以降、Siriから呼ばせるにはAppleが定義したスキーマに準拠させる記述を足す必要がありますが、基本的な中身は同じです。iOS27でもそれは同じで、WWDC26 のセッション「Build intelligent Siri experiences with App Schemas」でも「それを可能にしている土台が App Intents です」と説明されています。
ところで、この「名前・説明・型付きの引数」という形は、MCP(Model Context Protocol)のtool定義とほぼ同じです。並べてみます。
//Swift struct RecordTemperatureIntent: AppIntent { static let title: LocalizedStringResource = "体温を記録" static let description = IntentDescription("体温を記録します") @Parameter(title: "体温") var temperature: Double func perform() async throws -> some IntentResult & ProvidesDialog { // アプリの機能を呼ぶ return .result(dialog: "\(temperature)度を記録しました") } }
// MCP { "name": "record_temperature", "title": "体温を記録", "description": "体温を記録します", "inputSchema": { "type": "object", "properties": { "temperature": { "type": "number", "description": "体温(℃)" } }, "required": ["temperature"] } }
どちらも、名前・説明・型付きの引数が書かれています。呼び出す側がここに書かれた説明をヒントに実行する機能を選択し、引数に何を入れるかを決める点も同じです。もちろんMCPサーバとApp Intents/AppFunctions は別物ですが、宣言の形は非常に似ていると言えます。
宣言の中身はそれだけではない~結果の返し方、認証
ここまでだと、AI用のインターフェースは「呼べる関数の一覧」に見えます。ただ、App Intents の宣言に書くのは、呼べる機能だけではありません。次の2つも宣言の一部です。
- 結果をどう返すか
- 認証をかけるか
1つ目は、結果の返し方です。さきほどのSwiftのコードにある ProvidesDialog は、実行後に返す文言の宣言で、それを受け取ったシステムが表示または読み上げる想定です。文言ではなく画面で返す ShowsSnippetView もあり、どちらもiOS 16からあります。iOS 26 で追加された SnippetIntent を使うと、返した画面の中でユーザーが選択肢を選んだり情報を確認したりできます。
AI時代のUIとして GenUI や A2UI という言葉を見かけますが、これは返す画面をAIがその場で組み立てるものです。一方でSnippetIntent で返す画面は、AIが作ったものではなく、アプリの開発者が書いたSwiftUIのビューです。出てくる場所は SnippetIntent と同じですが、画面を用意するのがアプリか、AIかという違いがありますね。
ちなみに、この画面はここまで分けて考えてきた、人間が操作する経路とAIが操作する経路、そのどちらかに属するものではありません。どちらの経路にも、AIが人間に応答するタイミングで登場します。たとえ経路が分かれていても、人間に見せる画面は結局どちらからも必要になる、ということです。
そして2つ目は、認証です。画面からの操作手順の中でかけていた認証は、画面を通らない経路には自動ではかからないことに注意すべきです。AIからは、ログイン画面の先にあるはずの機能でも、intentごとに設定しない限り認証なしで呼べてしまいます。モバイルアプリのセキュリティ診断を手がける NowSecure も、認証のポリシーはintentに自動適用はされないと指摘しています(原文: "Authentication policies are not automatically applied to every intent."、2026年8月)。
このことはまたあとで出てきます。
呼び出し元の数に応じてロジック層を切り出す
冒頭に「アプリの入口が画面だけではなくなるので、ロジックを画面から切り離しておくことが必須になるのではないか」と書きました。
今後は、AIが使う経路と人間が使う経路の両方から、同じ機能を呼び出すことになります。ということは、ロジックは両方から呼べる共通の場所に置かなければいけません。
先ほどの2つの経路の図を、アプリの内部まで広げて描くとこうなります。

ロジックの呼び出し元が2つになり、片方は画面を通らない、という点に注目してください。
では具体的にどのような設計にしたらいいのか。弊社ではモバイルアプリを Flutter で作っているので、Flutter に当てはめて考えてみます。Flutter の公式ドキュメント(App architecture guide)では、ドメイン層(use-case)は "Optional" として扱われていて、入れる条件が3つ挙げられています。
複数のリポジトリのデータを合わせる必要がある(Requires merging data from multiple repositories)
非常に複雑である(Is exceedingly complex)
そのロジックを別の ViewModel から使い回す(The logic will be reused by different view models)
推奨のページでは推奨度が "Conditional" で、"ほとんどのアプリでは、不要なオーバーヘッドを増やしてしまう(in most apps they add unnecessary overhead)" とまで書かれています。
これは一見「小さいアプリなら、UI層とdata層の2層で十分」だと読めるのですが、そういうことではありません。
注目したいのは3つ目の項目です。「別の ViewModel から使う」と書かれているのは、ロジックを呼ぶのが ViewModel だけだという前提があるからです。App Intents や AppFunctions は、ViewModel ではない呼び出し元です。条件を文字どおりに読むと、「呼び出し元は1つの ViewModel だけなので、use-case は要らない」と判断してしまいますが、これからは画面がない場所からロジックを呼ぶことも想定しなければいけないのです。
といっても、公式ガイドが間違っていると指摘したいわけではなく、呼び出し元が増えた前提で、同じ条件を読み直す必要がある、という話です。
つまり、やるべきことは3つあり、
- UI層とdata層の間に use-case を置く
- 画面からは ViewModel を通して呼び、機能の宣言からは use-case を直接呼び出す
- ViewModel は、読み込み中やエラー表示など、画面の状態だけを持つ
Flutter の層に当てはめると、こうなります。

RecordTemperatureUseCase のようなクラスを domain層に置き、ViewModel からも App Intent からも同じ execute() を呼びます。ViewModel に残すのは isSaving のような画面の状態だけです。
画面と intent が増えるほど、この形が効果的になります。記録画面と履歴画面、体温を記録する intent と今日の記録を見る intent が、同じ2つの use-case を呼び分けるだけで実装可能だからです。もしロジックを ViewModel の中に置いてしまうと、同じロジックを intent 側にもう一度書くことになります。
App Intent から Dart の関数を呼ぶ仕組みはパッケージによって違うので、ここでは触れません。設計として言いたいのは、AIからの呼び出しを受ける場所が、画面の状態を持つクラスの中にあると成立しないということです。
結果の返し方と一緒に触れた認証も、同じ理由で書くところが決まります。画面側に書いてあると、画面を通らない呼び出しでは実行されません。use-case か、機能の宣言の側に書く必要があります。
まとめ
- アプリのインターフェースは、人間が操作する画面、AIが呼ぶ機能の宣言、AIの応答を見せる画面の3つになります
- 宣言には、呼び出せる機能だけでなく、その結果の返し方と認証の情報までが含まれます
- アプリの機能としてのロジックは、どの経路から呼ばれても同じように動作する場所に置く必要があります
AIからアプリを呼び出す手段はまだ限られていますが、これから広がっていくことは間違いありません。その時のために、今からロジックを画面から切り離す設計を始めていきましょう。

書いた人:川喜田



















