Entity Providers
Entity providers serve dynamic data to the assistant at runtime. Playlists, alarms, bookmarks, contacts, saved views. Anything where the set of valid values changes based on user data.
Without entity providers, the assistant can only match against static strings in oacp.json. That works for a language picker with 20 entries. It does not work for a music library with 500 playlists.
When to use them
Use an entity provider when:
- The valid values change at runtime (playlists, alarms, bookmarks)
- The list is too large to inline in
oacp.json(contacts, files) - The data is user-specific (custom tags, saved searches)
Use an entity snapshot instead when:
- The list is small and static (languages, categories, difficulty levels)
- The values never change between app updates
Declaring entity types
Define custom entity types at the top level of oacp.json.
Declaring entity providers
Entity providers tell the assistant where to query for entities of a given type.
The uri points to a ContentProvider in your app. The assistant queries it when it needs to resolve a parameter of this entity type.
Referencing in parameters
Link a parameter to an entity type with entityRef.
When resolution is "required", the assistant must resolve the user's input to a known entity before invoking the capability. If the input is ambiguous, the assistant shows the entityDisambiguationPrompt.
When resolution is "optional", the assistant tries to resolve but accepts free-form input as a fallback.
Implementing OacpEntitySource
Your app needs a Kotlin class that implements OacpEntitySource. This is the code that runs when the assistant queries your provider.
Register it in your Application.onCreate():
The query parameter is a prefix string. When the user says "play my rock playlist", the assistant queries with query = "rock". Return all matches. The assistant handles ranking and disambiguation.
Entity snapshots
For small, static sets of values, skip the provider and inline them directly in the parameter definition.
Each snapshot entry has:
Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | Stable identifier passed as the parameter value. |
| string | Yes | Human-readable name shown to the user. |
| string[] | No | Alternate names that resolve to this entity. |
The assistant matches the user's utterance against displayName and aliases. The resolved id is sent as the parameter value.
Testing with adb
Query your entity provider directly from the command line.
List all entities:
Search with a prefix:
You should see rows with id, displayName, aliases, and description columns. If you get no results, check that your Application.onCreate() calls OacpProvider.setEntitySource() and that the uri in oacp.json matches your provider's authority.
Example: Wikipedia language selection
A Wikipedia reader app lets users switch languages by voice. The app has ~300 supported languages, but only ~30 are commonly requested. An entity snapshot works here because the list is bounded and changes only with app updates.
The capability in oacp.json:
User says "Spanish Wikipedia". The assistant matches "Spanish" to the snapshot entry with displayName: "Spanish". It resolves language_code to "es" and invokes the capability.
User says "show me the espanol version". The assistant matches "espanol" to the aliases of the Spanish entry. Same result: language_code = "es".