AppFunctions の概要

AppFunctions を使用すると、Android アプリは、システムやさまざまな AI エージェントやアシスタントが検出して呼び出すことができる特定の機能を共有できます。これらの関数を定義することで、アプリは Android OS にサービス、データ、アクションを提供できるようになり、ユーザーは AI エージェントやシステムレベルのインタラクションを通じてタスクを完了できます。

AppFunctions は、Model Context Protocol(MCP)内のツールに相当するモバイル版として機能します。MCP は従来、エージェントがサーバーサイド ツールに接続する方法を標準化していましたが、AppFunctions は Android アプリに同じメカニズムを提供します。これにより、アプリの機能をオーケストレーション可能な「ツール」として公開し、承認されたアプリ(呼び出し元)が検出して実行し、ユーザーの意図を満たすことができます。呼び出し元は、AppFunction を検出して実行するための EXECUTE_APP_FUNCTIONS 権限を持っている必要があります。呼び出し元には、エージェント、アプリ、Gemini などの AI アシスタントを含めることができます。

AppFunctions は Android 16 以降を搭載したデバイスで動作します。

ユースケースの例

AppFunctions は、タスクを自動化し、ユーザー インタラクションを効率化するための強力なメカニズムを提供します。アプリの機能を公開することで、ユーザーは自然言語を使用して複雑な目標を達成できるようになります。多くの場合、UI を使用したステップバイステップの手動ナビゲーションは不要になります。

次のシナリオは、さまざまなアプリカテゴリで AppFunctions を使用してエクスペリエンスを向上させる方法を示しています。

  • タスク管理と生産性
    • ユーザーのリクエスト: 「今日の午後 5 時に仕事場で荷物を受け取るようリマインドして」。
    • AppFunction アクション: 発信者は関連するタスク管理アプリを特定し、関数を呼び出してタスクを作成します。ユーザーのプロンプトに基づいて、タイトル、時間、場所のフィールドが自動的に入力されます。
  • メディアとエンターテイメント
    • ユーザーのリクエスト: 「今年のジャズのトップ アルバムの新しいプレイリストを作成して」。
    • AppFunction アクション: 発信者が音楽アプリ内でプレイリスト作成関数を実行し、「2026 年のジャズのトップ アルバム」などのコンテキストをクエリとして渡して、コンテンツをすぐに生成して起動します。
  • クロスアプリ ワークフロー
    • ユーザーのリクエスト: 「Lisa のメールから麺のレシピを探して、ショッピング リストに材料を追加して」。
    • AppFunction アクション: このリクエストは複数のアプリの関数を使用します。まず、発信者はメールアプリの検索機能を使用してコンテンツを取得します。次に、関連する材料を抽出し、買い物リスト アプリの関数を呼び出してユーザーのリストに入力します。
  • カレンダーとスケジュール
    • ユーザーのリクエスト: 「来週の月曜日の午後 6 時に、母の誕生日パーティーをカレンダーに追加して」。
    • AppFunction アクション: 承認済みのエージェント アプリがカレンダー アプリの「イベントの作成」関数を呼び出し、「来週の月曜日」や「午後 6 時」などの関連するコンテキストを解析して、ユーザーが手動でカレンダーを開く必要なくエントリを作成します。

AppFunctions の仕組み

AppFunctions は、Android 16 プラットフォームの機能と、それに付随する Jetpack ライブラリです。これにより、アプリは、エージェント アプリなどの呼び出し元がデバイス上でアクセスして実行できる特定の関数を公開できます。

次の図は、アプリが AppFunctions をエージェントと共有し、その後実行される一般的なフローを示しています。エージェントは、ユーザー リクエストを処理する際に、サーバーサイドのリモート MCP ツールとローカルの AppFunctions の両方を一緒に検討する可能性があります。ローカル AppFunctions を使用する詳細なフローは次のとおりです。

  • AppFunction 宣言: Android アプリは、「メモを作成」や「メッセージを送信」などの AppFunction を公開するように構築されています。
  • スキーマの生成: AppFunctions Jetpack ライブラリは、アプリで宣言されたすべての AppFunctions をリストする XML スキーマ ファイルを生成します。このファイルは、利用可能な AppFunctions のインデックス登録に Android OS によって使用されます。
  • メタデータの取得: エージェントは、AppFunction メタデータをクエリして取得できます。
  • AppFunction の選択と実行: ユーザーのプロンプトに基づいて、エージェントは適切な AppFunction を適切なパラメータとともに選択して実行します。
アプリの公開からエージェントの実行までの AppFunction の一般的なフローを示す図。
図 1: AppFunction が公開され、エージェントによって実行される一般的なフロー。

AppFunctions Jetpack ライブラリを使用すると、アプリの機能を簡単に公開できます。アノテーション プロセッサを使用すると、公開する関数にアノテーションを付けることができます。呼び出し元は、AppFunctionManager を使用して、これらのインデックス付き関数を検出して呼び出すことができます。

アプリで AppFunction 機能がサポートされているかどうかを確認する必要はありません。これは Jetpack ライブラリ内で自動的に処理されます。たとえば、AppFunctionManager は、機能がサポートされているかどうかを確認できます。

以下に、メモの作成、編集、一覧表示の機能を備えたメモ作成アプリの AppFunctions の例を示します。

class NoteFunctions(
  private val noteRepository: NoteRepository
) {
    /**
     * A note.
     *
     * @param id The note's ID.
     * @param title The note's title.
     * @param content The note's content.
     */
    @AppFunctionSerializable(isDescribedByKDoc = true)
    data class Note(val id: Int, val title: String, val content: String)

    /**
     * Lists all available notes.
     *
     * @param appFunctionContext The context in which the AppFunction is executed.
     */
    @AppFunction(isDescribedByKDoc = true)
    suspend fun listNotes(appFunctionContext: AppFunctionContext): List<Note>? {
        return if (noteRepository.appNotes.isEmpty()) null else viewModel.appNotes
    }

    /**
     * Adds a new note to the app.
     *
     * @param appFunctionContext The context in which the AppFunction is executed.
     * @param title The title of the note.
     * @param content The note's content.
     */
    @AppFunction(isDescribedByKDoc = true)
    suspend fun createNote(
      appFunctionContext: AppFunctionContext,
      title: String,
      content: String
    ): Note {
        return noteRepository.createNote(title, content)
    }

    /**
     * Edits a single note.
     *
     * @param appFunctionContext The context in which the AppFunction is executed.
     * @param noteId The target note's ID.
     * @param title The new title if it should be updated.
     * @param content The new content if it should be updated.
     */
    @AppFunction(isDescribedByKDoc = true)
    suspend fun editNote(
      appFunctionContext: AppFunctionContext,
      noteId: String,
      title: String?,
      content: String,
    ): Note? {
        return noteRepository.updateNote(noteId, title, content)
    }
}