Google announced Gemini Spark at I/O this morning, and with it the formal opening of the agentic surface in Android 17. Spark is the user-facing product, but the developer story is the older, quieter one underneath it: App Actions, refreshed and re-prioritised so that any third-party app can be a tool an agent calls. If your app exposes the right capabilities, it becomes a reachable building block in a user's Gemini workflows. If it doesn't, it stays invisible — opened only by the few users who still tap the launcher icon.
This guide walks through what changed in App Actions for Android 17, how to declare a capability that Gemini Intelligence can call, how to test it end-to-end with the new emulator support, and the listing and discovery work you need to do alongside the manifest changes so Gemini's app discovery layer actually finds you. It assumes a working Kotlin codebase and a basic familiarity with Jetpack and the manifest. It is not exhaustive — Google's official docs are — but it is the practical version, ordered the way an indie shipping in the next six weeks actually needs to do the work.
What's actually new in Android 17#
App Actions has existed since 2018. The change in 2026 is that the agent layer is no longer an experiment. Gemini Spark is shipping into the Gemini app on Android 17 over the summer, and the agent's tool list — the actions it can call to get something done for the user — is built primarily from App Actions declared by installed apps.
Three things changed concretely:
The capability schema expanded. Google has published roughly 50 new built-in intents covering domains the original spec didn't reach — fitness tracking, recipe steps, financial summaries, calendar conflict resolution, document drafting, social posting. You declare capabilities by mapping your app's verbs to these built-in intents, which Gemini knows how to invoke.
Custom intents are now first-class. Previously, if Google didn't ship a built-in intent for your domain, you had to wait. Android 17 lets you declare a custom capability with your own schema, and Gemini's agent can call it as long as the description is well-formed. This is the part most coverage will miss. Custom intents are how vertical apps — niche tools, hobby trackers, internal apps — get into the agent surface without waiting for Google.
App Actions runs headlessly by default. Older intents always opened your app. Spark wants your action to return a result without taking over the screen, so the agent can chain calls together. You opt into headless mode in your capability declaration, and you return a structured result rather than navigating to a screen.
How to declare a capability Gemini can call#
The mechanical part is small. The judgement part — picking which verbs to expose first — is where most teams stall.
1. Pick the right built-in intent or define a custom one#
Open the App Actions built-in intent catalogue in the Android Developer docs and look for the closest match to a verb your app already supports. "Log a workout," "add to shopping list," "summarise today's emails," "create a calendar event," "send a message to a contact" all have built-in intents. If your verb matches, use the built-in — Gemini's agent already knows how to fill in the parameters from a user's request.
If nothing in the catalogue fits, define a custom capability. Custom capabilities are declared in your shortcuts.xml resource and include a name, a description (which the agent reads to decide whether to call you), and a parameter schema. The description is the only thing Gemini sees when deciding "should I call this app?" — write it like you're writing a tool description for an LLM, because that's exactly what it is.
2. Declare the capability in shortcuts.xml#
A minimal shortcuts.xml declaration for a built-in intent looks like this:
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<capability android:name="actions.intent.LOG_WORKOUT">
<intent
android:targetPackage="com.example.fitness"
android:targetClass="com.example.fitness.LogWorkoutHandler">
<parameter
android:name="exerciseObservation.name"
android:key="exerciseName" />
<parameter
android:name="exerciseObservation.exercise.name"
android:key="exerciseType" />
</intent>
</capability>
</shortcuts>A custom capability looks similar but with your own name and a <parameter> schema you control. Reference shortcuts.xml from your manifest via <meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts" /> inside your launcher activity.
3. Build the handler#
For headless execution, your handler isn't an activity — it's a class that implements CapabilityHandler (the new interface in Android 17's androidx.appactions library) and returns a structured CapabilityResult synchronously or via a coroutine. The result includes a status, a payload the agent can present to the user, and optionally a follow-up suggestion ("Want me to log another set?") that Gemini can offer as the next step in a chain.
Don't open an activity from inside a headless handler. If your action genuinely needs UI — a confirmation, a multi-step form — declare the capability with android:requireConfirmation="true" and let the agent decide whether to surface your UI or take a fast path.
4. Test with the Gemini agent simulator#
Google shipped a Gemini agent simulator as part of Android Studio's I/O 2026 update. It runs in the emulator, takes a natural-language prompt, and calls into your app's declared capabilities the same way Spark will in production. The simulator logs every parameter parse and every result, so you can see exactly what Gemini understood from a prompt and what your handler returned.
Run the simulator against five or six phrasings of the same intent before shipping. Users do not say "log a workout." They say "I just ran four miles," "add a 30-minute run to my activity log," "I went for a jog," "stick a run in." If your capability description and parameter names only handle the literal verb, the agent will route the request to a different app — or to an open-the-app fallback.
The discovery half nobody talks about#
A capability that ships in your APK but isn't discoverable from the Play Store doesn't get called. Gemini's app discovery layer — the part of Spark that decides "the user has no app installed that handles this, should I suggest one?" — indexes the Play Store listing alongside the manifest of installed apps. If your listing description, screenshots, and store metadata don't mention the verbs your app supports, Spark will suggest a competitor that does.
Three things matter for discovery:
The description on your Play Store page should list the verbs as verbs. Not "fitness tracker" — "log workouts, plan runs, sync to wear os." Spark indexes verbs, not nouns.
Your screenshots should show the action in flight. Spark's app suggestion UI pulls screenshot 1 and 2 from your listing. If those screenshots show a generic home screen, you're losing the suggestion fight to apps whose screenshot 1 is the verb in motion.
Your tags and category should match the built-in intent domain. Fitness apps that don't use the Fitness category get downranked in domain-scoped agent suggestions.
A practical six-step rollout plan#
For an indie shipping into Android 17's launch window, here's the order to do this work:
-
Audit your current intents. Open your existing manifest and count the intents and shortcuts you already declare. Most apps have one or two that were written years ago and forgotten.
-
Pick the three to five verbs that represent the most-used actions in your app — the things a user does in the first thirty seconds of opening it. Those are your candidates for App Actions capabilities.
-
Map each verb to a built-in intent if one exists; declare a custom capability if not.
-
Refactor each verb's logic so it can run headlessly. If a verb absolutely requires UI, mark the capability as requiring confirmation rather than dropping it.
-
Test each capability with five paraphrased prompts in the Gemini simulator. Fix the descriptions and parameter names until all five resolve to your handler.
-
Update your Play Store listing — title, short description, full description, screenshots 1 and 2 — to reflect the verbs you now expose.
Steps 1–5 are the manifest and code work, and they're well-bounded — a one-sprint job for a small team. Step 6 is the one that drifts, because it lives in App Store Connect's Play equivalent rather than in your codebase, and it doesn't have tests.
How Stora fits in#
The Play Store listing half of this work is exactly what Stora's store listing engine is built for. Stora reads your manifest, finds the capabilities you declare, generates Play Store listing copy that reflects the verbs your app actually supports, and regenerates screenshot captions to feature the actions Gemini will route to you. When you add a new capability in shortcuts.xml, Stora flags that your listing is now out of date and proposes the new copy alongside the diff.
The compliance engine catches the other side: a capability declared but unreachable (handler missing, manifest entry malformed) is a rejection risk in Play Console's automated checks, and Stora's pre-submission scan surfaces it before you push the build.
The agent surface is the new ASO. The apps that show up in Gemini Spark's suggestion sheet on launch day are the apps whose manifest, code, and listing all tell the same story — and keep telling the same story across every release.
Closing#
Spark is shipping in stages over the summer. The Android 17 stable build lands in June. The window to declare capabilities, test them in the simulator, and rewrite your listing to match is roughly six weeks. That's not a lot of time, but it's enough — App Actions isn't a new framework, just a newly-important one.
The work to do is small. The cost of skipping it is being invisible in a launcher-less future. Start with the manifest. End with the listing. The verbs in between are the part of your app that matters.