AppFunctions, revisited An Android developer updated the Be Nice app to use Jetpack AppFunctions alpha10, which removed the appfunctions-service artifact and requires hosting an @AppFunctionServiceEntryPoint AppFunctionService. The implementation now matches app display names instead of package names, and the developer corrected an earlier article's claim about package name usage. In Agentic interaction using AppFunctions https://dev.to/tkuenneth/agentic-interaction-using-appfunctions-m8k I showed how Be nice publishes createAppPair for agents, using Jetpack appfunctions 1.0.0-alpha08 . That setup leaned on a library-merged PlatformAppFunctionService , an AppFunctionContext parameter, and aggregate XML named app functions.xml / app functions v2.xml . When I bumped toward what Android Studio was suggesting as of mid July, Sync failed: Could not find androidx.appfunctions:appfunctions-service:1.0.0-alpha10. On 1 July 2026 https://developer.android.com/jetpack/androidx/releases/appfunctions , alpha10 stopped publishing appfunctions-service Maven still lists it through alpha09 . The Add the AppFunctions API https://developer.android.com/ai/appfunctions/add-appfunctions guide now expects you to host an @AppFunctionServiceEntryPoint AppFunctionService . Spoiler: that is the real change. The rest of this post is how that landed in Be nice , plus an important update to the earlier article that is easy to miss if you only chase compile errors. In the earlier post I wrote that agents would pass package names for app1 and app2 . That was wrong for Be nice . The implementation matches display names , case-insensitively, against installed apps. Package names are a convenient engineer habit; they are a poor agent habit when the user said “Clock” and “Contacts”. KDoc and app-level metadata have to say what the code accepts — agents lean on that text harder than on your mental model of the APK. Before alpha10 you annotated a helper class and let the service AAR merge a stock entry point into the manifest. Starting with alpha10: @AppFunction lives in androidx.appfunctions not androidx.appfunctions.service AppFunctionService marked @AppFunctionServiceEntryPoint serviceName and the XML named in appFunctionXmlFileName AppFunctionContext parameter; the service Context appfunctions:aggregateAppFunctions . Grepping for empty app functions.xml / app functions v2.xml is no longer the success signalAlpha09 still shipped the service artifact. Jumping from the first article to today skips that soft landing and hits alpha10. versions appfunctions = "1.0.0-alpha10" libraries androidx-appfunctions = { group = "androidx.appfunctions", name = "appfunctions", version.ref = "appfunctions" } androidx-appfunctions-compiler = { group = "androidx.appfunctions", name = "appfunctions-compiler", version.ref = "appfunctions" } dependencies { implementation libs.androidx.appfunctions ksp libs.androidx.appfunctions.compiler } compileSdk stays at 36 or higher Be nice is on 37 . I still keep each merge Assets task depending on the matching ksp Kotlin task. Alpha10 still emits XML under KSP-generated assets — benice app functions.xml for me — and on my AGP/KSP combo packaging was flaky without that edge. Same class of problem as in the first article; new file name. @RequiresApi Build.VERSION CODES.BAKLAVA @AppFunctionServiceEntryPoint serviceName = "BeNiceAppFunctionService", appFunctionXmlFileName = "benice app functions", abstract class BeNiceFunctions : AppFunctionService { / Launches two installed apps together in split screen an app pair . @param app1 Name of the first app in the pair. @param app2 Name of the second app in the pair. @return A localized message describing success or failure. / @AppFunction isDescribedByKDoc = true suspend fun createAppPair app1: String, app2: String : String = withContext Dispatchers.IO { val success = performPairing applicationContext, app1, app2 if success { getString R.string.pair created success, app1, app2 } else { getString R.string.pair created failure } } } AppFunctionService is API 36 Baklava , so the abstract host carries @RequiresApi . Where the old code used context.context , I use applicationContext / getString on the service. I still use suspend . The docs also say AppFunctions run on the UI thread unless you move work elsewhere. Resolving installed apps and publishing a dynamic shortcut is not UI-thread work; withContext Dispatchers.IO is not optional once the body does real I/O. isDescribedByKDoc = true still folds KDoc into agent metadata. Treat that block as public API surface for a model, not as a comment for the next human on your team. Official snippets often put @AndroidEntryPoint and @Inject on the abstract service. I did not. KSP already generates a subclass BeNiceAppFunctionService . Hilt would want to subclass the same type for injection. Stacking two code generators on one service is a fight I do not need for two collaborators. A small @EntryPoint plus EntryPointAccessors.fromApplication for InstalledAppsManager and ShortcutsRepository keeps the host boring. Point at the generated class and at the XML name you chose: