The project you will build
Build Android Decision Lab, a native Kotlin and Jetpack Compose app that makes this sequence visible:
Android input → minimal context → Jev decision → application policy → Android action
The home screen has Voice Decision and Notification Triage cards, plus a recent-decision list. Selecting a result opens a Decision Inspector. Camera Context and AppFunctions are later milestones. This roadmap supplies design guidance and assignments; it does not bundle a finished Android repository or promise access to a provider account.
Jev is a hosted decision model from TypeSafe AI. It supports predefined questions and typed answers rather than serving as the application's prose generator. For a bounded task, define the alternatives before making the request. A generative model can separately produce a summary or extract information; Kotlin decides whether an action is permitted and performs it. See the TypeSafe introduction and official quickstart.
Decide what needs a model
Consider “Read this reminder when my headphones are connected.” Whether headphones are connected is observed state. Whether the app has permission to read aloud is a product rule. Neither needs a model. Classifying a varied natural-language request into one of several supported intents may benefit from Jev.
Start with a narrow vocabulary: SHOW_IN_APP, READ_ALOUD, ASK_USER and IGNORE. IGNORE means your lab takes no action; it does not mean deleting another app's notification. A typed response can still choose the wrong valid action. Never use confidence to bypass permission or confirmation requirements.
For “Remind me after the meeting,” routing to a reminder workflow is not sufficient: the meeting and due time remain unresolved. Ask for missing details rather than inventing them or claiming the reminder was scheduled.
A native architecture
Use feature packages for home, voice, notifications and inspector. Keep context capture, decision contracts and action execution separate:
feature/voice → ViewModel → DecisionRepository → your backend → Jev
↓
policy + executor
↓
DecisionRecord → inspector
A fixture implementation of DecisionRepository should let you build the UI without credentials. Label its output “Simulated”; fixtures prove UI and policy behavior, not model accuracy. Store request identifiers and lifecycle states so a response for an old input cannot execute after the user starts a new one.
We will build the companion Android Decision Lab project in the Android Engineers Android AI Cookbook. The Jev sample is planned and is not yet available. Its native Kotlin architecture will follow an observe → decide → validate → execute loop, with Android APIs handling the actions. Until the sample is published, use these assignments to build your own implementation.
Practice and checkpoint
Create a Compose project with a text input, the two home cards and a fixture repository. Submit two inputs in quick succession and deliberately delay the first response. Only the latest request may offer an action. Show the older record as superseded.
Write a table of five supported requests, their allowed actions, required context and missing arguments. Include one request that deterministic rules can handle and one unsupported request that must ask the user. Keep all fixture data fictional.
Pass when: you can trace one request across the architecture, distinguish routing from argument extraction, and explain why no model result is permission to execute. Continue to the secure integration module once fixture mode works without a network connection.