Create Actions.xml

Once you identify the in-app functionality and built-in intent (BII) to implement, you create an actions.xml resource in your Android app that maps the BII to your app functionality. App Actions defined in actions.xml describe how each BII resolves its fulfillment, as well as which parameters are extracted and provided to your app.

Overview

To integrate your Android app with App Actions, you must have an actions.xml file placed in your app project's res/xml directory.

Add a reference to the actions.xml file in the AndroidManifest.xml file using a <meta-data> tag as follows:

<application>
    <!-- ... -->
    <meta-data android:name="com.google.android.actions" android:resource="@xml/actions" />
</application>

This declares an XML resource for the xml/actions.xml file in the APK. To learn more about specifying resources in Android, see the App resources overview in the Android developer documentation.

Schema

The following table describes the schema for actions.xml. When including a tag, all of its attributes are required unless marked "optional".

Tag Contained in Attributes
<actions> top-level
<action> <actions> intentName
<parameter> <action> name
<entity-set-reference> <parameter>

entitySetId OR

urlFilter

<fulfillment> <action>

urlTemplate

fulfillmentMode (optional)

requiredForegroundActivity (optional)

<parameter-mapping> <fulfillment>

urlParameter

intentParameter

required (optional)

entityMatchRequired (optional)

<entity-set> <actions> entitySetId
<entity> <entity-set>

name (and optionally alternateName) OR

sameAs

identifier OR url

Description

<action>

An App Action that the app supports. For every <action> tag in your actions.xml file, you must provide at least one <fulfillment>.

Attributes:

  • intentName: Built-in intent for the App Action (for example, "actions.intent.CREATE_TAXI_RESERVATION"). For a list of supported built-in intents, see the built-in intent reference.

<parameter>

A parameter of an App Action having a name and list of associated entities.

Attributes:

  • name: Name to associate with this parameter (for example, "destination"). The name should be a leaf-level field of the parameter (for example, tradeOrder.assetOrdered.assetIssuedBy.name). If the parameter is a primitive type, such as a string, then the name is just the parameter name itself.

<entity-set-reference>

Reference to a schema.org feed that the developer supplies. Feeds must be provided directly in the actions.xml file using <entity-set> tags.

Attributes:

  • entitySetId: A reference to a specific collection of entities. This attribute must correspond to an entitySetId in an <entity-set> tag.
  • urlFilter: URL path used when providing web inventory for fulfillment. This attribute supports two wildcards:
    • *: An asterisk matches a sequence of zero to many occurrences of the immediately preceding character.
    • .*: A period followed by an asterisk matches any sequence of zero to many characters.
    • Escape characters are only needed for literal * and \, which you can escape as \\* and \\\\, respectively.

<fulfillment>

Information about how to fulfill the user intent using the Android app. Developers may provide multiple <fulfillment> tags in actions.xml, with different set of required parameters for each intent.

Google uses the first <fulfillment> for which all required parameters are available to fulfill the user's query. You must provide one <fulfillment> without any required parameters as a fallback fulfillment.

Attributes:

  • urlTemplate: Template for constructing either the deep link or a Slice URI to be opened on the device. The template may be expanded with the parameters of the user intent if all required parameters for the template are available. For examples of the HTTP URL template, see the Wikipedia article on URL templates. The template format follows the RFC6570 URI template specification.
  • fulfillmentMode: (optional) Fulfillment mode used for serving. The valid values are:
    • actions.fulfillment.DEEPLINK: Fulfill user action by opening the Android app using a deep link. This is the default.
    • actions.fulfillment.SLICE: Fulfill user action by embedding a Slice provided by Android app.
  • requiredForegroundActivity: (optional) Indicates the activity that must be in the foreground for the App Action to be triggered with foreground app invocation.
    • Specify the activity without any class abbreviations using your app package name, followed by a forward slash (/), followed by the activity name: APP_PACKAGE_NAME/ACTIVITY_NAME

The following are some examples of URL template values:

Template Values Expanded value
https://example.com/test{?foo,bar} "foo": "123"

"bar": "456"

https://example.com/test?foo=123&bar=456
https://example.com/test?utm_campaign=appactions{&foo,bar} "foo": "123"

"bar": "456"

https://example.com/test?utm_campaign=appactions&foo=123&bar=456
https://example.com/test?utm_campaign=appactions{#foo} "foo": "123" https://example.com/test?utm_campaign=appactions#foo=123
myapp://example/{foo} "foo": "123" myapp://example/123
intent://foo#Intent;scheme=my-scheme{;S.extra1,S.extra2};end "S.extra1": "123"

"S.extra2": "456"

intent://foo#Intent;scheme=my-scheme;S.extra1=123;S.extra2=456;end

For more about configuring URL templates, see URL templates in fulfillment.

<parameter-mapping>

Maps from variables in the URL template to intent parameters. Keys in this map represent URL template parameters, or "variables" as decribed in RFC 6570.

If a parameter is not included in the intent, the corresponding variable will be left undefined at the time of URL template expansion. See RFC 6570, Section 3.2.1 for a description of how undefined variables are treated.

Note that required="true" and entityMatchRequired="true" are distinct.

Attributes:

  • urlParameter: Every variable mentioned in the URL template must have a corresponding urlParameter in <parameter-mapping>. For example, if the uri_template is "http://spysatellite.com/show{?lat,long}", there must be a key in <parameter-mapping> for parameters "lat" and "long".
  • intentParameter: Values refer to intent parameters. If the intent parameter is of a structured type, use dot.notation to refer to a nested field. For example, if there is a parameter "taxiReservation" of type schema.org/TaxiReservation, you can use taxiReservation.pickupLocation.geo.latitude to refer to the latitude value.

    If providing an entity set for this parameter, the intentParameter must match exactly the name of the corresponding <parameter> tag (for example, taxiReservation.pickupLocation.geo.latitude). It should point to a leaf-level field of the parameter (if the intent parameter has a complex type) or the parameter name itself (if the intent parameter has a primitive type).

  • required: (optional) Indicates that a value for the given intentParameter is required to be present for this URL template to be valid. The URL template is dropped if the user query does not include a value for the given intentParameter.

  • entityMatchRequired: (optional) Indicates that an inventory match for the given intentParameter must be present. Defaults to false. When this attribute is set to true, either the identifier from an inventory match is passed to the URL template, or Assistant skips the fulfillment if there is no match. When this attribute is set to false, either the identifier from an inventory match is passed to the URL template, or Assistant provides the BII parameter value as extracted from the user query if there is no match.

<entity-set>

Set of inlined entities in actions.xml.

Attributes:

  • entitySetId: Required unique identifier for an <entity-set>in actions.xml (for example, "myInlineEntitySet1"). This value must also correspond to the <entitySetId> value in the <entity-set-reference> tag.

    Values for entitySetId must contain at most 30 characters, contain only alphanumeric characters (no special characters like - or _), and begin with a letter.

<entity>

One element among a set of entities inlined in actions.xml. Contains a subset of schema.org/Thing fields.

String values for the url, identifier, and sameAs fields can either be hard-coded or referenced via the APK's string resources. When providing synonyms, use string values for the alternateName field that reference the APK's string array resources.

Attributes:

  • name: Required name for the entity, unless you are specifying a sameAs field. Must be unique across entity name and alternateName fields for the given <entity-set> (for example, "toothpaste").
  • alternateName: (optional) Alternate names for the entity. You must specify a name field before specifying an alternateName field. Must be unique across entity name and alternateName fields for the given <entity-set>. The entity is selected if the user's query matches any of these strings.
  • sameAs: URL of a reference web page that unambiguously identifies the entity. Used to specify an enum value if and only if the intent parameter type is a subtype of schema.org/Enumeration.

    Required for parameter fields whose types are subtypes of schema.org/Enumeration (for example: MealTypeBreakfast).

  • identifier: Identifier for the entity. Must be unique across entities for the given <entity-set> (for example, "CAPPUCCINO_ID").

  • url: RFC 3986 URL to be opened on an Android device. The URL may or may not be resolvable by an HTTP client. For example, on Android, the URL may be an app-linked "http://" URL or a device-specific URL, like an "intent://" URL or a URL in a custom URL scheme.

    You can use the url field together with the urlTemplate attribute of <fulfillment> in the following ways:

    • Provide url values in inline inventory, and omit urlTemplate in <fulfillment>.
    • Provide url values in inline inventory, and use those values in the urlTemplate value (for example, "{@url}&extra_param=ExampleValue").

Either identifier or url must be provided. All entities within a given entity set must use the same attribute (identifier or url).

Inline inventory for App Actions

For some built-in intents, you can optionally guide entity extraction to a set of supported entities specified in actions.xml, known as inline inventory. When a user invokes your App Action, Assistant matches user query parameters with entities specified as inline inventory. Google Assistant can then use identifiers that correspond to inventory items when generating a deep link for fulfillment.

You define inline inventory primarily using the <entity-set> and <entity> elements. Inline inventory simplifies development by allowing your app to handle only identifiers or URLs from App Action invocations instead of needing to recognize strings or Google enumeration values.

For example, your app offers different beverages that users can order, and you expect users to make the following requests for the same type of beverage:

  • Hey Google, order a Blueberry Crisp Iced Signature Latte from ExampleApp.
  • Hey Google, order a Blueberry Iced Coffee from ExampleApp.

In your inline inventory, you specify "Blueberry Crisp Iced Signature Latte" as an entity that corresponds to the identifier "12345a". You also specify "Blueberry Iced Coffee" as an entity that corresponds to the same identifier. Now, when a user triggers your App Action with the above queries, Assistant can use the identifier "12345a" when generating a deep link for fulfillment.

You can specify up to 1,000 entities per app, across all entity sets.

Web inventory for App Actions

For some built-in intents, you can use web inventory as a method of generating URLs for fulfillment. Web inventory uses your website to discover URLs for App Action fulfillment. This feature is most useful when you have a strong web presence and your in-app deep links are organized around publicly available web content.

To use web inventory, update your actions.xml:

  1. In the <action> tag where you want to use web inventory, add a <fulfillment> tag and set its urlTemplate attribute to {@url}.
  2. In the same <action> tag, add a <parameter> tag and set its name attribute to the BII parameter you want to get from web inventory.
  3. In the new <parameter> tag, add a <entity-set-reference> tag and set its urlFilter attribute to the URL path you want to use for web inventory.

By performing the above steps, Assistant can perform a web search in the URL path you provide in the urlFilter attribute. Google Assistant then supplies a {@url} value to your fulfillment using the results. Your deep link handler can then route a user based on the deep link returned by Assistant for that fulfillment.

For example, your website contains product listings that use a path beginning with https://www.example.com/items/. You use the urlFilter value https://www.example.com/items/.*, and Assistant later returns a fulfillment URL like https://www.example.com/items/item123. See <entity-set-reference> above for information about the urlFilter attribute.

URL templates in fulfillment

In a <fulfillment> tag, you can declare a URL template with placeholders for dynamic parameters. This template maps to one of your Android activities, using an App Links URL, a custom scheme, or an Intent-based URL.

Configuring the URL template

Example of an App Links URL:

<action intentName="actions.intent.CREATE_TAXI_RESERVATION">
    <fulfillment urlTemplate="http://my-taxi.com/order{?dropoffLocation}">
        <parameter-mapping
                intentParameter="taxiReservation.dropoffLocation.name"
                urlParameter="dropoffLocation"/>
    </fulfillment>
</action>

Example of a custom scheme:

<action intentName="actions.intent.CREATE_TAXI_RESERVATION">
    <fulfillment urlTemplate="mytaxi://reserve{?dropoffLocation}">
        <parameter-mapping
                intentParameter="taxiReservation.dropoffLocation.name"
                urlParameter="dropoffLocation"/>
    </fulfillment>
</action>

Example of an intent-based URL:

<action intentName="actions.intent.CREATE_TAXI_RESERVATION">
    <fulfillment
            urlTemplate="intent:#Intent;package=com.example.myapp;action=com.example.myapp.MY_ACTION{;S.dropoff};end">
        <parameter-mapping
                intentParameter="taxiReservation.dropoffLocation.name"
                urlParameter="S.dropoff"/>
    </fulfillment>
</action>

When specifying a <parameter-mapping> tag for a fulfillment, the intentParameter attribute denotes the built-in intent parameter provided by the user. In the above examples, that parameter is the drop off location name ("taxiReservation.dropoffLocation.name"). You can find the available parameters for any given built-in intent in the built-in intent reference.

To map the built-in intent parameter to a position in your URL, you use the urlParameter attribute of the <parameter-mapping> tag. This attribute corresponds to the placeholder value in the URL template that you want to substitute with information from the user. The placeholder value must be present in your urlTemplate and enclosed by curly braces ({}).

If you specify entity sets, you can combine the URL from an entity set with other URL parameters. To add URL parameters, provide a urlTemplate value that begins with the {@url} placeholder, such as: "{@url}&autoplay=true&utm_source=assistant".

App Links URLs

If you're using an App Links URL, the urlTemplate points to a regular HTTP URL that can trigger your Activity. Parameters are passed as URL parameters to the App Links URL. The parameters in urlTemplate must be enclosed in curly braces ({}) and prefixed with a question mark (?). If a parameter is not set, the parameter (curly braces included) is omitted from the result.

For example, if a user triggered the App Action by asking to order a taxi to "San Francisco", the final URI that is triggered (after parameter substitution) would be the following:

https://mydomain.com/order?action=com.example.myapp.MY_ACTION&dropoff=San+Francisco

Intent-based URLs

If you're using an intent-based URL, the urlTemplate value includes the package name, the Intent action, and one extra Intent, called the "dropoff". The extra is prefixed by "S." to denote a String Intent extra (as defined by Intent.toUri()) and is surrounded by curly braces to denote a substitution by a parameter. The extra preceding semicolon is needed to separate the Intent action from the Intent extra (and is only included if the parameter is set).

In our example, the urlParameter value is set to "S.dropoff"; you can see where this appears in our URL by looking for this value in urlTemplate.

As an example, if a user triggered our Action by asking to order a ride to "San Francisco", the final Uri that is triggered (after parameter substitution) would be:

intent:#Intent;package=com.example.myapp;action=com.example.myapp.MY_ACTION;S.dropoff=San+Francisco;end

Using URL values from entities in URL templates

By default, if an <entity> is matched to the user's query, the value of the identifier attribute is passed to the URL template. To reference the url attribute of an <entity> instead, use {@url} in the URL template and do not use a <parameter-mapping> tag. Note that identifier values are URL-escaped, but url attribute values are left unchanged.

If a fulfillment uses {@url} in the URL template, the fulfillment attempts to derive {@url} from sources such as web and inline inventory. When both web and inline inventories are potential sources of deriving {@url}, web inventory takes preference.

For example:

<fulfillment urlTemplate="{@url}">
    <!-- No parameter-mapping is needed -->
</fulfillment>
<entity-set entitySetId="...">
    <entity name="..." url="https://my.url.fulfillment/1"/>
    <entity name="..." url="https://my.url.fulfillment/2"/>
</entity-set>

The {@url} parameters can be combined with other parameters. For example:

<fulfillment urlTemplate="{@url}?referrer=actions_on_google{&amp;other_param}">
    <parameter-mapping intentParameter="otherParam.name" urlParameter="other_param"/>
</fulfillment>
<entity-set entitySetId="...">
    <entity name="..." url="https://my.url.fulfillment/1"/>
    <entity name="..." url="https://my.url.fulfillment/2"/>
</entity-set>

Parameter matching

The way Google matches parameters from the user utterances to the entities you specified depends on the type of the parameter:

  • Enum: Google matches the user's query ("monday") to an associated enum URL ("http://schema.org/Monday"), then picks the entity whose sameAs value matches the enum URL.
  • String: Google picks the entity whose name or alternateName value matches the user's query.

Examples

Finance - accounts and payments

The following actions.xml example uses the actions.intent.CREATE_MONEY_TRANSFER built-in intent:

<?xml version="1.0" encoding="utf-8"?>
<actions>
    <action intentName="actions.intent.CREATE_MONEY_TRANSFER">
        <fulfillment urlTemplate="mybankapp://transfer{?amount,currency,recipientBankAccountType,senderBankAccountType,mode}">
            <parameter-mapping intentParameter="moneyTransfer.amount.value" urlParameter="amount" />
            <parameter-mapping intentParameter="moneyTransfer.amount.currency" urlParameter="currency" />
            <parameter-mapping intentParameter="moneyTransfer.moneyTransferDestination.name" urlParameter="recipientBankAccountType" />
            <parameter-mapping intentParameter="moneyTransfer.moneyTransferOrigin.name" urlParameter="senderBankAccountType" />
            <parameter-mapping intentParameter="moneyTransfer.transferMode" urlParameter="mode" />
        </fulfillment>
    </action>
</actions>

Fitness - nutrition

The following actions.xml example uses the actions.intent.RECORD_FOOD_OBSERVATION built-in intent:

<?xml version="1.0" encoding="utf-8"?>
<actions>
    <action intentName="actions.intent.RECORD_FOOD_OBSERVATION">
        <parameter name="foodObservation.forMeal">
            <entity-set-reference entitySetId="MealEntitySet"/>
        </parameter>
        <fulfillment urlTemplate="myfoodapp://record{?food,meal}">
            <parameter-mapping intentParameter="foodObservation.forMeal" urlParameter="meal" entityMatchRequired="true" />
            <parameter-mapping intentParameter="foodObservation.aboutFood.name" urlParameter="food" />
        </fulfillment>
    </action>
    <entity-set entitySetId="MealEntitySet">
        <entity sameAs="http://schema.googleapis.com/MealTypeBreakfast" identifier="1" />
        <entity sameAs="http://schema.googleapis.com/MealTypeLunch" identifier="2" />
        <entity sameAs="http://schema.googleapis.com/MealTypeDinner" identifier="3" />

    </entity-set>
</actions>

Food ordering

The following actions.xml example uses the actions.intent.ORDER_MENU_ITEM built-in intent:

<?xml version="1.0" encoding="utf-8"?>
<actions>
    <action intentName="actions.intent.ORDER_MENU_ITEM">
        <parameter name="menuItem.inMenuSection.inMenu.forRestaurant.servesCuisine">
            <entity-set-reference entitySetId="CuisineEntitySet"/>
        </parameter>
        <fulfillment urlTemplate="myfoodapp://order{?restaurant}">
            <parameter-mapping intentParameter="menuItem.inMenuSection.inMenu.forRestaurant.name" urlParameter="restaurant" required="true" />
        </fulfillment>
        <!-- URL values are derived from a matched entity from the CuisineEntity Set. This is not a fallback fulfillment because {@url} is a required parameter. -->
        <fulfillment urlTemplate="{@url}" />
        <!-- Fallback fulfillment with no required parameters -->
        <fulfillment urlTemplate="myfoodapp://browse{?food}">
            <parameter-mapping intentParameter="menuItem.name" urlParameter="food" />
        </fulfillment>
    </action>
    <entity-set entitySetId="CuisineEntitySet">
        <entity url="myfoodapp://browse/italian/pizza" name="@string/pizza" alternateName="@array/pizzaSynonyms" />
        <entity url="myfoodapp://browse/american/hamburger" name="@string/hamburger" alternateName="@array/hamburgerSynonyms" />
        <entity url="myfoodapp://browse/mediterranean" name="@string/mediterranean" alternateName="@array/mediterraneanSynonyms" />
    </entity-set>
</actions>

Transportation

The following actions.xml file uses the actions.intent.CREATE_TAXI_RESERVATION built-in intent:

<actions>
    <action intentName="actions.intent.CREATE_TAXI_RESERVATION">
        <fulfillment urlTemplate="https://taxi-actions.firebaseapp.com/order{?dropoffAddress}">
            <!-- Dropoff location as an address -->
            <parameter-mapping
                    intentParameter="taxiReservation.dropoffLocation.name"
                    urlParameter="dropoffAddress"/>
        </fulfillment>
    </action>
</actions>

Other

The following actions.xml example uses the actions.intent.OPEN_APP_FEATURE built-in intent.

<?xml version="1.0" encoding="utf-8"?>
<actions>
    <action intentName="actions.intent.OPEN_APP_FEATURE">
        <!-- Each parameter can reference an entity set using a custom ID. -->
        <parameter name="feature">
            <entity-set-reference entitySetId="FeatureEntitySet"/>
        </parameter>

        <fulfillment urlTemplate="myexampleapp://pathto{?appFeature}">
            <parameter-mapping intentParameter="feature" urlParameter="appFeature" />
        </fulfillment>
    </action>

    <entity-set entitySetId="FeatureEntitySet">
        <entity identifier="FEATUREONE" name="first feature" />
        <entity identifier="FEATURETWO" name="second feature" />
    </entity-set>
</actions>