actions.xml を作成する(サポート終了)

実装するアプリ内機能と組み込みインテント(BII)を特定したら、その BII をアプリの機能にマッピングする actions.xml リソースを Android アプリに作成します。actions.xml で定義された App Actions は、各 BII がフルフィルメントを解決する方法と、抽出されてアプリに渡されるパラメータを記述します。

概要

Android アプリと App Actions を統合するには、アプリ プロジェクトの res/xml ディレクトリに actions.xml ファイルが存在している必要があります。

<meta-data> タグを使用して AndroidManifest.xml ファイルに actions.xml ファイルへの参照を追加します。次に例を示します。

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

これにより、APK で xml/actions.xml ファイルの XML リソースが宣言されます。Android でリソースを指定する方法の詳細については、Android デベロッパー向けドキュメントのアプリリソースの概要をご覧ください。

スキーマ

次の表に、actions.xml のスキーマを示します。タグを含める場合は、任意と記載されていない限りすべての属性が必須です。

タグ 親要素 属性
<actions> 最上位
<action> <actions>

intentName

queryPatternsカスタム インテントの場合にのみ適用)

<parameter> <action> name
<entity-set-reference> <parameter>

entitySetId または

urlFilter

<fulfillment> <action>

urlTemplate

fulfillmentMode(任意)

requiredForegroundActivity(任意)

<parameter-mapping> <fulfillment>

urlParameter

intentParameter

required(任意)

entityMatchRequired(任意)

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

name(および任意で alternateName)または

sameAs

identifier または url

タグの説明

このセクションでは、actions.xml の各スキーマタグについて説明します。

<action>

アプリがサポートする App Action。actions.xml ファイル内のすべての <action> タグに、少なくとも 1 つの <fulfillment> を指定する必要があります。

属性:

  • intentName: App Actions の組み込みインテント(actions.intent.CREATE_TAXI_RESERVATION など)。サポートされている組み込みインテントの一覧については、組み込みインテントのリファレンスをご覧ください。

  • queryPatterns: このインテントに関して想定されるユーザーからのクエリのセット。この属性はカスタム インテントにのみ適用されます。これは、すでに BII にはユーザーが行おうとしているタスクやユーザーが求める情報を表現する一般的なモデルが含まれているためです。

<parameter>

名前と関連エンティティのリストを指定するアプリ アクションのパラメータ。

属性:

  • name: このパラメータに関連付ける名前(「destination」など)。名前はこのパラメータのリーフレベルのフィールド(tradeOrder.assetOrdered.assetIssuedBy.name など)です。パラメータが文字列などのプリミティブ タイプの場合、パラメータ名自体がこの名前になります。

<entity-set-reference>

デベロッパーが提供する schema.org フィードへの参照。 フィードは、<entity-set> タグを使用して actions.xml ファイルに直接指定する必要があります。

属性:

  • entitySetId: 特定のエンティティ コレクションへの参照。この属性は、<entity-set> タグの entitySetId に対応している必要があります。

  • urlFilter: フルフィルメントにウェブ インベントリを提供するときに使用する URL パス。この属性では、次の 2 つのワイルドカードを使用できます。

    • *: アスタリスクは、直前の文字が 0 個以上出現するシーケンスと一致します。

    • .*: アスタリスクの前のピリオドは、0 個以上の文字のシーケンスに一致します。

    • エスケープ文字が必要なのは、リテラルの *\ のみであり、それぞれ \\*\\\\ でエスケープできます。

<fulfillment>

Android アプリを使用してユーザーのインテントを処理する方法に関する情報。デベロッパーは actions.xml に複数の <fulfillment> タグを指定し、インテントごとに異なる必須パラメータのセットを設定できます。

Google は、最初の <fulfillment> を使用します。この最初のタグでは、ユーザーのクエリを処理するために必要なすべてのパラメータが使用可能です。フォールバック フルフィルメントとして、1 つの <fulfillment> を必須パラメータなしで指定する必要があります。

属性:

  • urlTemplate: デバイスで開くディープリンクまたはスライス URI を作成するためのテンプレート。テンプレートのすべての必須パラメータが使用可能な場合、ユーザー インテントのパラメータを使用してテンプレートを展開できます。HTTP URL テンプレートの例については、URL テンプレートについての Wikipedia 記事をご覧ください。テンプレートの形式は、RFC 6570 URI テンプレートの仕様に準拠しています。

  • fulfillmentMode:(任意)処理に使用されるフルフィルメント モード。有効な値は次のとおりです。

    • actions.fulfillment.DEEPLINK: ディープリンクを使用して Android アプリを開き、ユーザー アクションを実行します。これがデフォルトです。

    • actions.fulfillment.SLICE: Android アプリから提供される Slice を埋め込むことで、ユーザー アクションを実行します。

  • requiredForegroundActivity: (任意)フォアグラウンド アプリ呼び出しで App Action をトリガーするときに、フォアグラウンドでなければならないアクティビティを示します。

    • APP_PACKAGE_NAME/ACTIVITY_NAME のように、アプリのパッケージ名の後ろに、スラッシュ(/)、アクティビティ名と続けて、アクティビティを指定します(クラスの省略形は使用しません)。

URL テンプレートの値の例を次に示します。

テンプレート 展開された値
https://example.com/test{?someValue,anotherValue} "someValue": "123"

"anotherValue": "456"

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

"anotherValue": "456"

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

"S.extra2": "456"

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

URL テンプレートの構成の詳細については、フルフィルメントの URL テンプレートをご覧ください。

<parameter-mapping>

インテント パラメータから URL テンプレートの変数にマッピングします。このマップのキーは、URL テンプレートのパラメータ、または RFC 6570 で説明する「変数」を表します。

インテントにパラメータが含まれていない場合、URL テンプレートの展開時に対応する変数は未定義のままになります。未定義の変数の処理方法については、RFC 6570、セクション 3.2.1 をご覧ください。

required="true"entityMatchRequired="true" は異なる点に注意してください。

属性:

  • urlParameter: URL テンプレートに記載されているすべての変数に対し、対応する urlParameter<parameter-mapping> に含まれている必要があります。たとえば、uri_template が http://spysatellite.com/show{?lat,long} の場合、パラメータ latlong に対応するキーが <parameter-mapping> に必要です。

  • intentParameter: 値はインテント パラメータを参照します。インテント パラメータが構造化タイプの場合、ネストしたフィールドを参照するにはドット表記を使用します。たとえば、タイプ schema.org/TaxiReservation のパラメータ taxiReservation の場合、taxiReservation.pickupLocation.geo.latitude を使用して緯度の値を参照できます。

    このパラメータにエンティティ セットを指定する場合、intentParameter は対応する <parameter> タグの名前と正確に一致している必要があります(taxiReservation.pickupLocation.geo.latitude など)。

    インテント パラメータに複合タイプがある場合、値はパラメータのオブジェクト参照に対応します(taxiReservation など)。インテント パラメータにプリミティブ タイプがある場合、値はパラメータ名自体になります。

  • required: (任意)この URL テンプレートが有効であるためには、指定の intentParameter の値が存在している必要があることを示します。ユーザークエリに指定の intentParameter の値が含まれていない場合、URL テンプレートは削除されます。

  • entityMatchRequired: (任意)指定された intentParameter のインベントリ一致の存在が必須であることを示します。デフォルトは false です。

    この属性を true に設定すると、インベントリ一致がある場合、その一致の ID が URL テンプレートに渡されます。一致がない場合、アシスタントはフルフィルメントをスキップします。

    この属性を false に設定すると、インベントリ一致がある場合、その一致の ID が URL テンプレートに渡されます。一致がない場合、アシスタントはユーザークエリから抽出された BII パラメータ値を渡します。

<entity-set>

actions.xml 内のインライン エンティティのセット。

属性:

  • entitySetId: actions.xml<entity-set> の一意の必須 ID("myInlineEntitySet1" など)。この値は <entity-set-reference> タグの <entitySetId> 値に対応している必要もあります。

    entitySetId の値は、30 文字以下の英数字(-_ などの特殊文字を除く)を含んでいて、先頭が英字である必要があります。

<entity>

actions.xml でインライン化された一連のエンティティのうちの 1 つの要素。schema.org/Thing フィールドのサブセットが含まれています。

urlidentifiersameAs の各フィールドの文字列値は、ハードコーディングするか、または APK の文字列リソースを使用して参照できます。類義語を提供する場合は、APK の文字列配列リソースを参照する alternateName フィールドに文字列値を使用します。

属性:

  • name: エンティティの必須名(sameAs フィールドを指定する場合を除く)。指定の <entity-set> のエンティティ name フィールドと alternateName フィールドにおいて固有でなければなりません(「toothpaste」など)。

  • alternateName:(任意)エンティティの代替名。alternateName フィールドを指定する前に、name フィールドを指定する必要があります。指定の <entity-set> のエンティティ name フィールドと alternateName フィールドで固有である必要があります。ユーザーのクエリが以下のいずれかの文字列と一致すると、このエンティティが選択されます。

  • sameAs: エンティティを明確に識別する参照ウェブページの URL。インテント パラメータ タイプが schema.org/Enumeration のサブタイプである場合に限り、列挙値を指定するために使用されます。

    タイプが schema.org/Enumeration のサブタイプ(MealTypeBreakfast など)であるパラメータ フィールドの場合は必須です。

  • identifier: エンティティの ID。指定の <entity-set> のエンティティで固有でなければなりません(CAPPUCCINO_ID など)。

  • url: Android デバイスで開く RFC 3986 URL。この URL は、HTTP クライアントでは解決できない場合があります。たとえば Android では、URL はアプリからリンクされている「http://」URL、またはデバイス固有の URL(「intent://」URL や、カスタム URL スキームの URL)になることがあります。

    url フィールドは、次のようにして <fulfillment>urlTemplate 属性と組み合わせて使用できます。

    • インライン インベントリで url 値を指定し、<fulfillment>urlTemplate を省略する。

    • インライン インベントリで url 値を指定し、その値を urlTemplate 値の中で使用する({@url}?extra_param=ExampleValue など)。

identifierurl のいずれかを指定する必要があります。指定したエンティティ セット内のすべてのエンティティは同じ属性(identifier または url)を使用する必要があります。

App Actions のインライン インベントリ

一部の組み込みインテントでは、インライン インベントリと呼ばれる、actions.xml で指定したサポートされているエンティティのセットへエンティティ抽出をガイドできます(任意)。ユーザーが App Action を呼び出すと、アシスタントはユーザークエリのパラメータをインライン インベントリとして指定されたエンティティと照合します。すると、Google アシスタントがフルフィルメント用のディープリンクを生成する際に、インベントリ アイテムに対応する ID を使用できます。

インライン インベントリの定義には、主に <entity-set> 要素と <entity> 要素を使用します。インライン インベントリを使用することで、アプリで文字列や Google 列挙値を認識する必要がなくなり、App Action 呼び出しの ID や URL のみを処理すればよくなるため、開発が簡単になります。

たとえば、アプリでユーザーがさまざまな飲料を注文できる場合、ユーザーが同じ種類の飲料について、次のようなリクエストを行うことを想定します。

  • OK Google, Example App でブルーベリー クリスプ オリジナル アイスラテを注文して。

  • OK Google, Example App でブルーベリー アイスコーヒーを注文して。

インライン インベントリで、ID 12345a に対応するエンティティとして「ブルーベリー クリスプ オリジナル アイスラテ」を指定します。さらに、同じ ID に対応するエンティティとして「ブルーベリー アイスコーヒー」を指定します。これで、ユーザーが上記のクエリを使用して App Action をトリガーすると、フルフィルメントのディープリンクを生成するときにアシスタントが ID 12345a を使用できるようになります。

すべてのエンティティ セットで、アプリあたり最大 1,000 個のエンティティを指定できます。<entity> ごとに最大 20 個の alternateName 類義語値を定義できます。

App Actions のウェブ インベントリ

一部の組み込みインテントでは、フルフィルメントの URL を生成する方法としてウェブ インベントリを使用できます。ウェブ インベントリは、ウェブサイトを使用して App Action フルフィルメントの URL を検出します。この機能は、ウェブでのプレゼンスが高く、アプリ内ディープリンクが一般公開されているウェブ コンテンツを中心に編成されている場合に特に役立ちます。

ウェブ インベントリを使用するには、actions.xml を更新します。

  1. ウェブ インベントリを使用する <action> タグで、<fulfillment> タグを追加し、その urlTemplate 属性を {@url} に設定します。

  2. 同じ <action> タグ内で、<parameter> タグを追加し、その name 属性をウェブページに記述したエンティティに最も対応する組み込みインテント パラメータに設定します。 たとえば、ORDER_MENU_ITEM のウェブ インベントリを指定する場合、メニューページを menuItem.name にリンクし、レストランの場所のページを menuItem.inMenuSection.inMenu.forRestaurant.name にリンクします。

  3. 新しい <parameter> タグで、<entity-set-reference> タグを追加して、その urlFilter 属性を、ウェブ インベントリに使用する URL パスに設定します。

上記の手順により、アシスタントは、urlFilter 属性で指定した URL パスでウェブ検索を行うことができます。Google アシスタントは、その結果を使用して {@url} 値をフルフィルメントに渡します。すると、ディープリンク ハンドラが、そのフルフィルメントにアシスタントが返したディープリンクに基づいてユーザーを転送できるようになります。

たとえば、ウェブサイトに https://www.example.com/items/ で始まるパスを使用した商品リスティングが含まれているとします。urlFilterhttps://www.example.com/items/.* を使用すると、アシスタントは後で https://www.example.com/items/item123 のようなフルフィルメント URL を返します。urlFilter 属性の詳細については、<entity-set-reference> をご覧ください。

フルフィルメントの URL テンプレート

<fulfillment> タグでは、動的パラメータのプレースホルダを使用して URL テンプレートを宣言できます。このテンプレートは、App Links URL、カスタム スキーム、インテント ベースの URL のいずれかを使用して Android アクティビティの 1 つにマッピングされます。

URL テンプレートを設定する

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>

カスタム スキームの例:

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

インテント ベースの 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>

フルフィルメントに <parameter-mapping> タグを指定するとき、intentParameter 属性は、ユーザーが指定する組み込みインテント パラメータを示します。上記の例では、このパラメータは降車場所の名前(taxiReservation.dropoffLocation.name)です。特定の組み込みインテントで使用可能なパラメータは、組み込みインテントのリファレンスで確認できます。

組み込みインテント パラメータを URL 内の位置にマッピングするには、<parameter-mapping> タグの urlParameter 属性を使用します。この属性は、ユーザーからの情報に置き換える URL テンプレートのプレースホルダ値に対応します。プレースホルダ値は、urlTemplate 内に記述し、中かっこ({})で囲む必要があります。

App Links URL を使用している場合、urlTemplateActivity をトリガーできる通常の HTTP URL を指します。パラメータは URL パラメータとして App Links URL に渡されます。urlTemplate 内のパラメータは中かっこ({})で囲み、疑問符(?)をプレフィックスとして付ける必要があります。パラメータが設定されていない場合、パラメータ(中かっこを含む)は結果から除外されます。

たとえば、降車場所を「San Francisco」としてタクシーを依頼して App Action をトリガーすると、(パラメータの置換後に)トリガーされる最終 URI は次のようになります。

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

インテント ベースの URL

インテント ベースの URL を使用している場合、urlTemplate の値にはパッケージ名、インテントのアクション、および dropoff という 1 つのインテント エクストラが含まれます。エクストラには、(Intent.toUri() で定義されている)String インテント エクストラであることを示す「S」がプレフィックスとして付加され、またパラメータにより置き換えることを示す中かっこで囲まれています。

エクストラの前にあるセミコロンは、インテント アクションとインテント エクストラを区切るために必要です(このパラメータが設定されている場合にのみ追加されます)。

次の例では、urlParameter 値は S.dropoff に設定されています。URL でこの値がどこに位置するかを確認するには、urlTemplate でこの値を探します。

たとえば、ユーザーが「San Francisco」までの配車を依頼することで App Actions をトリガーすると、(パラメータの置換後に)トリガーされる最終 URI は次のようになります。

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

インテントの詳細については、Android のインテントに関するドキュメントをご覧ください。

URL テンプレートのエンティティの URL 値を使用する

デフォルトでは、<entity> がユーザークエリに一致すると、identifier 属性の値が URL テンプレートに渡されます。代わりに <entity>url 属性を参照するには、URL テンプレートで {@url} を使用し、<parameter-mapping> タグを使用しないでください。ID 値は URL エスケープされますが、url 属性値は変更されません。

フルフィルメントが URL テンプレートで {@url} を使用している場合、フルフィルメントはウェブ インベントリやインライン インベントリなどのソースから {@url} を導き出します。ウェブ インベントリとインライン インベントリの両方から {@url} を導き出すことができる場合、ウェブ インベントリが優先されます。

これを次の例に示します。

<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>

{@url} パラメータは他のパラメータと組み合わせることができます。

<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>

パラメータの一致

Google がユーザーの発話のパラメータと、指定したエンティティを一致させる方法は、パラメータのタイプに応じて異なります。

  • Enum: Google はユーザーのクエリ(「Monday」)を、関連付けられている列挙型 URL(「http://schema.org/Monday」)に一致させ、sameAs 値が列挙型 URL と一致するエンティティを選択します。
  • String: Google は、ユーザーのクエリに一致する name 値または alternateName 値を持つエンティティを選択します。

このセクションでは、actions.xml で組み込みインテントを利用する方法の例を示します。

財務 - アカウントと支払い

次の actions.xml の例では、actions.intent.CREATE_MONEY_TRANSFER 組み込みインテントを使用しています。

<?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>

フィットネス - 栄養補助

次の actions.xml の例では、actions.intent.RECORD_FOOD_OBSERVATION 組み込みインテントを使用しています。

<?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>

料理の注文

次の actions.xml の例では、actions.intent.ORDER_MENU_ITEM 組み込みインテントを使用しています。

<?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>

交通情報

次の actions.xml ファイルでは、actions.intent.CREATE_TAXI_RESERVATION 組み込みインテントを使用しています。

<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>

その他

次の actions.xml の例では、actions.intent.OPEN_APP_FEATURE 組み込みインテントを使用しています。

<?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>