AppFunctions는 Android MCP 통합을 간소화하는 Jetpack 라이브러리가 포함된 Android 플랫폼 API입니다. 이 API를 사용하면 앱이 기기 내 MCP 서버처럼 동작하여 Google Gemini와 같은 에이전트 및 어시스턴트와 함께 사전 예방적 기능에서 사용할 도구 역할을 하는 기능을 제공할 수 있습니다. 2026년 5월 현재 Gemini와의 AppFunctions 통합은 신뢰할 수 있는 테스터를 대상으로 비공개 미리보기로 제공됩니다. 지금부터 AppFunctions 및 개발 도구를 사용할 수 있도록 앱을 준비할 수 있습니다.
이러한 AppFunctions를 정의하면 앱에서 Android OS에 내장된 레지스트리에 서비스, 데이터, 작업을 제공할 수 있으므로 사용자가 에이전트 및 시스템 수준 상호작용을 통해 작업을 완료할 수 있습니다.
AppFunctions는 모델 컨텍스트
프로토콜 (MCP) 내 도구의 모바일 버전 역할을 합니다. MCP는 기존에 에이전트가 서버 측 도구에 연결하는 방법을 표준화했지만 AppFunctions는 Android 앱에 동일한 메커니즘을 제공합니다. 이를 통해 승인된 앱 (호출자)이 사용자 인텐트를 충족하기 위해 검색하고 실행할 수 있는 오케스트레이션 가능한 '도구'로 앱의 기능을 노출할 수 있습니다. 호출자는 AppFunctions를 검색하고 실행하려면 EXECUTE_APP_FUNCTIONS 권한이 있어야 하며 에이전트, 앱, Gemini와 같은 AI
어시스턴트를 포함할 수 있습니다.
AppFunctions는 Android 16 이상을 실행하는 기기에서 사용할 수 있습니다.
사용 사례
AppFunctions는 작업을 자동화하고 사용자 상호작용을 간소화하는 강력한 메커니즘을 제공합니다. 앱의 기능을 공개하면 사용자가 자연어를 사용하여 복잡한 목표를 달성할 수 있으며, UI를 사용하여 단계별 수동 탐색을 할 필요가 없는 경우가 많습니다.
다음 시나리오에서는 AppFunctions를 사용하여 다양한 앱 카테고리 내에서 환경을 개선하는 방법을 보여줍니다.
작업 관리 및 생산성
- 사용자 요청: "오늘 오후 5 시에 직장에서 택배를 찾아오라고 알려 줘".
- AppFunction 작업: 호출자가 관련 작업 관리 앱을 식별하고 함수를 호출하여 작업을 만듭니다. 이때 사용자 프롬프트에 따라 제목, 시간, 위치 필드가 자동으로 채워집니다.
/** * Create a new task or reminder with a title, due time, and location. * * @param title The descriptive title of the task (e.g., "Pick up my package"). * @param dueDateTime The specific date and time when the task should be completed. * @param location The physical location associated with the task (e.g., "Work"). * @return The created Task */ @AppFunction(isDescribedByKDoc = true) suspend fun createTask( title: String, dueDateTime: LocalDateTime? = null, location: String? = null, ): Task = TODO()
미디어 및 엔터테인먼트
- 사용자 요청: "올해 최고의 재즈 앨범으로 새 재생목록을 만들어 줘".
- AppFunction 작업: 호출자가 음악 앱 내에서 재생목록 생성 함수를 실행하고 '2026년 최고의 재즈 앨범'과 같은 컨텍스트를 쿼리로 전달하여 재생목록을 즉시 생성합니다.
/** * Create a new music playlist based on a natural language query. * * @param query The description used to generate the playlist (e.g., "top jazz albums from 2026"). * @return The final created playlist based on songs. */ @AppFunction(isDescribedByKDoc = true) suspend fun createPlaylistFromQuery( query: String, ): Playlist = TODO()
교차 앱 워크플로
- 사용자 요청: "Lisa의 이메일에서 국수 레시피를 찾아 쇼핑 목록에 재료를 추가해 줘".
- AppFunction 작업: 이 요청은 여러 앱의 함수를 사용합니다. 먼저 호출자가 이메일 앱의 검색 함수를 사용하여 콘텐츠를 가져옵니다. 그런 다음 관련 재료를 추출하고 쇼핑 목록 앱의 함수를 호출하여 사용자 목록을 채웁니다.
/** * Search for emails matching a query or sender name to retrieve content like recipes. * * @param query The search term or contact name (e.g., "Lisa noodle recipe"). * @return A list of matching email summaries containing the requested information. */ @AppFunction(isDescribedByKDoc = true) suspend fun searchEmails( query: String, ): List<EmailSummary> = TODO() /** * Add a list of items or ingredients to the user's active shopping list. * * @param items The names of the ingredients or products to add to the list. * @return The final shopping list with new items added */ @AppFunction(isDescribedByKDoc = true) suspend fun addItemsToShoppingList( items: List<String>, ): ShoppingList = TODO()
일정 관리 및 예약
- 사용자 요청: "다음 주 월요일 오후 6시에 엄마의 생일 파티를 내 캘린더에 추가해 줘".
- AppFunction 작업: 승인된 에이전트형 앱이 캘린더 앱의 '일정 만들기' 함수를 호출하고 '다음 주 월요일' 및 '오후 6시'와 같은 관련 컨텍스트를 파싱하여 사용자가 캘린더를 수동으로 열지 않고도 항목을 만들 수 있습니다.
/** * Schedule a new event on the user's primary calendar. * * @param title The name of the calendar event (e.g., "Mom's birthday party"). * @param startDateTime The specific date and time the event is scheduled to begin. * @return The created Event object. */ @AppFunction(isDescribedByKDoc = true) suspend fun createCalendarEvent( title: String, startDateTime: LocalDateTime, ): Event = TODO()
AppFunctions의 작동 방식
다음 다이어그램은 앱에서 에이전트로 AppFunctions를 공유하고 이후에 실행하는 일반적인 흐름을 보여줍니다. 에이전트는 사용자 요청을 처리할 때 서버 측 원격 MCP 도구와 로컬 AppFunctions를 모두 고려할 가능성이 높습니다. 로컬 AppFunctions를 사용하는 자세한 흐름은 다음과 같습니다.
- AppFunction 선언: Android 앱은 AppFunctions를 사용하여 '메모 만들기' 또는 '메시지 보내기'와 같은 기능을 사용할 수 있도록 빌드됩니다.
- 스키마 생성: AppFunctions Jetpack 라이브러리는 앱에 선언된 모든 AppFunctions를 나열하는 XML 스키마 파일을 생성합니다. Android OS는 이 파일을 사용하여 사용 가능한 AppFunctions의 색인을 생성합니다.
- 메타데이터 검색: 에이전트는 AppFunction 메타데이터를 쿼리하여 검색할 수 있습니다. 개발자는 함수별 KDocs 외에도 앱 메타데이터에서 앱 수준 운영 패턴과 제약 조건을 정의하여 여러 도구에서 에이전트 오케스트레이션을 안내할 수 있습니다.
- AppFunction 선택 및 실행: 사용자 프롬프트에 따라 에이전트는 적절한 매개변수로 적절한 AppFunction을 선택하고 실행합니다.
AppFunctions Jetpack 라이브러리를 사용하면 앱의 기능을 쉽게 노출할 수 있습니다.
주석 프로세서를 사용하면 에이전트에서 사용할 수 있도록 하려는 함수에 주석을 추가할 수 있습니다. 그러면 호출자가 AppFunctionManager를 사용하여 이러한 색인된
함수를 검색하고 호출할 수 있습니다.
함수를 호출하기 전에 호출자는 AppFunctionManager의 인스턴스를 검색하여 기기가 AppFunctions 기능을 지원하는지 확인해야 합니다. 지원되면 호출자는 타겟 앱 내에서 특정
함수가 사용 설정되어 있는지
isAppFunctionEnabled(packageName,functionId)를 사용하여 확인할 수 있습니다. 다른 패키지의 함수 상태를 쿼리하려면
android.permission.EXECUTE_APP_FUNCTIONS 권한이 필요합니다.
앱에서 AppFunction 기능이 지원되는지 확인할 필요는 없습니다. 이는 Jetpack 라이브러리 내에서 자동으로 처리됩니다. 예를 들어
AppFunctionManager는 기능이 지원되는지 확인할 수 있습니다.
다음은 메모를 만들고, 수정하고, 나열하는 기능이 있는 메모 작성 앱의 AppFunctions 예입니다.
@RequiresApi(36) @AndroidEntryPoint @AppFunctionServiceEntryPoint( serviceName = "TaskAppFunctionService", appFunctionXmlFileName = "task_app_function_service", ) abstract class BaseTaskAppFunctionService : AppFunctionService() { @Inject internal lateinit var taskRepository: TaskRepository /** * Creates a task based on [createTaskParams]. * * @param createTaskParams The parameter to describe how to create the task. */ @AppFunction(isDescribedByKDoc = true) suspend fun createTask( createTaskParams: CreateTaskParams, ): Task = withContext(Dispatchers.IO) { // Developers can use predefined exceptions to let the agent know // why it failed. if (createTaskParams.title == null && createTaskParams.content == null) { throw AppFunctionInvalidArgumentException("Title or content should be non-null") } val id = taskRepository.createTask( createTaskParams.title, createTaskParams.content ) return@withContext taskRepository .getTask(id) ?.toTask() ?: throw AppFunctionElementNotFoundException("Task not found for ID = $id") } // Maps internal TaskEntity private fun TaskEntity.toTask() = Task(id = id, title = title, content = description) }
/** The parameter to create the task. */ @AppFunctionSerializable(isDescribedByKDoc