Alexaサービスクライアント



Alexaサービスクライアント

Alexa Skills Kitには、スキルエクスペリエンスをパーソナライズできる複数のサービスAPIが用意されています。SDKには、スキルのロジックからAlexa APIを呼び出すのに使用するサービスクライアントが含まれます。

ServiceClientFactory

ハンドラー入力に含まれるservice_client_factoryにより、サポートされているすべてのAlexaサービスのクライアントインスタンスを取得することができます。個別のサービスクライアントの作成や、api_access_tokenおよびapi_endpointなどのメタデータの設定を行います。

service_client_factoryアトリビュートからhandler_inputで利用できるため、サービスクライアントは、任意のリクエストハンドラー、例外ハンドラー、リクエスト、応答インターセプターで使用できます。

利用可能なサービスクライアント

def get_device_address_service(self):
    # type: () -> ask_sdk_model.services.device_address.DeviceAddressServiceClient

def get_directive_service(self):
    # type: () -> ask_sdk_model.services.directive.DirectiveServiceClient

def get_list_management_service(self):
    # type: () -> ask_sdk_model.services.list_management.ListManagementServiceClient

def get_monetization_service(self):
    # type: () -> ask_sdk_model.services.monetization.MonetizationServiceClient

def get_ups_service(self):
    # type: () -> ask_sdk_model.services.ups.UpsServiceClient

def get_reminder_management_service(self):
    # type: () -> ask_sdk_model.services.reminder_management.ReminderManagementServiceClient

ApiClient

ask_sdk_model.services.api_client.ApiClientは、AlexaサービスへのAPI呼び出しを行うときにservice_client_factoryによって使用されます。SDKを使用して、次のインターフェースに準拠する任意のカスタマイズ済みApiClientを登録できます。

インターフェース

class ask_sdk_model.services.api_client.ApiClient:
    def invoke(self, request):
        # type: (ApiClientRequest) -> ApiClientResponse

class ask_sdk_model.services.api_client_request.ApiClientRequest(ApiClientMessage):
    def __init__(self, headers=None, body=None, url=None, method=None):
        # type: (List[Tuple[str, str]], str, str, str) -> None

class ask_sdk_model.services.api_client_request.ApiClientResponse(ApiClientMessage):
    def __init__(self, headers=None, body=None, status_code=None):
        # type: (List[Tuple[str, str]], str, int) -> None

class ask_sdk_model.services.api_client_message.ApiClientMessage(object):
    def __init__(self, headers=None, body=None):
        # type: (List[Tuple[str, str]], str) -> None

CustomSkillBuilderコンストラクターは、ApiClientの登録に使用できます。

from ask_sdk_core.skill_builder import CustomSkillBuilder

sb = CustomSkillBuilder(api_client=<YourClassInstance>)

DefaultApiClient

スキル開発者はrequestsライブラリに基づくDefaultApiClientを、ask_sdk_core.api_clientモジュールで利用できます。

このクライアントは、デフォルトでStandardSkillBuilderに登録されています。またはスキル開発者は、このクライアントをCustomSkillBuilderに登録できます。

from ask_sdk_core.skill_builder import CustomSkillBuilder
from ask_sdk_core.api_client import DefaultApiClient

sb = CustomSkillBuilder(api_client=DefaultApiClient())

DeviceAddressServiceClient

DeviceAddressServiceClientは、デバイスアドレスAPIに対してユーザーのAlexaデバイスに関連付けられた所在地データを照会するために使用できます。この所在地データを使用して、スキルの主要機能を提供したり、ユーザーエクスペリエンスを向上させることができます。たとえば、スキルはこの所在地情報を使って、近くの店舗の所在地一覧を提供したり、おすすめのレストランを紹介したりすることができます。

インターフェース

class ask_sdk_model.services.device_address.DeviceAddressServiceClient:
    def get_country_and_postal_code(device_id):
        # type: (str) -> Union[ShortAddress, Error]

    def get_full_address(self, device_id):
        # type: (str) -> Union[Address, Error]

class ask_sdk_model.services.device_address.ShortAddress:
    def __init__(self, country_code=None, postal_code=None):
        # type: (Optional[str], Optional[str]) -> None

class ask_sdk_model.services.device_address.Address:
    def __init__(
        self, address_line1=None, address_line2=None, address_line3=None,
        country_code=None, state_or_region=None, city=None,
        district_or_county=None, postal_code=None):
        # type: (Optional[str], Optional[str], Optional[str], Optional[str], Optional[str], Optional[str], Optional[str], Optional[str]) -> None

モデルの詳細については、こちら(英語)を参照してください。

サンプルコード

次の例は、リクエストハンドラーがユーザーの住所を取得する方法を示しています。

from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_core.utils import is_intent_name
from ask_sdk_model.response import Response
from ask_sdk_model.ui import AskForPermissionsConsentCard
from ask_sdk_model.services import ServiceException

NOTIFY_MISSING_PERMISSIONS = ("アマゾンアレクサアプリで"
                              "位置情報の権限を有効にしてください。")
NO_ADDRESS = ("住所が設定されていないようです。 "
              "コンパニオンアプリで住所を設定できます。")
ADDRESS_AVAILABLE = "住所は次のとおりです。{}, {}, {}"
ERROR = "申し訳ありません。エラーが発生しました。"
LOCATION_FAILURE = ("デバイスアドレスAPIでエラーが発生しました。"
                    "もう一度試してみてください。")

permissions = ["read::alexa:device:all:address"]

class GetAddressIntentHandler(AbstractRequestHandler):
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool
        return is_intent_name("GetAddressIntent")(handler_input)

    def handle(self, handler_input):
        # type: (HandlerInput) -> Response
        req_envelope = handler_input.request_envelope
        service_client_fact = handler_input.service_client_factory
        response_builder = handler_input.response_builder

        if not (req_envelope.context.system.user.permissions and
                req_envelope.context.system.user.permissions.consent_token):
            response_builder.speak(NOTIFY_MISSING_PERMISSIONS)
            response_builder.set_card(
                AskForPermissionsConsentCard(permissions=permissions))
            return response_builder.response

        try:
            device_id = req_envelope.context.system.device.device_id
            device_addr_client = service_client_fact.get_device_address_service()
            addr = device_addr_client.get_full_address(device_id)

            if addr.address_line1 is None and addr.state_or_region is None:
                response_builder.speak(NO_ADDRESS)
            else:
                response_builder.speak(ADDRESS_AVAILABLE.format(
                    addr.address_line1, addr.state_or_region, addr.postal_code))
            return response_builder.response
        except ServiceException:
            response_builder.speak(ERROR)
            return response_builder.response
        except Exception as e:
            raise e

DirectiveServiceClient

DirectiveServiceClientは、プログレッシブ応答APIにディレクティブを送信するために使用できます。プログレッシブ応答を使用すると、スキルがユーザーのリクエストへの完全な応答を準備している間もユーザーの関心を引き続けることができます。

インターフェース

class ask_sdk_model.services.directive.DirectiveServiceClient:
    def enqueue(self, send_directive_request):
        # type: (SendDirectiveRequest) -> Union[Error]

class ask_sdk_model.services.directive.SendDirectiveRequest:
    def __init__(self, header=None, directive=None):
        # type: (Optional[Header], Optional[SpeakDirective]) -> None

class ask_sdk_model.services.directive.SpeakDirective:
    def __init__(self, speech=None):
        # type: (Optional[str]) -> None

モデルの詳細については、こちら(英語)を参照してください。

サンプルコード

次の例は、プログレッシブ応答を送信するためのhandleメソッドで使用できる関数を示しています。

from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_model.services.directive import (
    SendDirectiveRequest, Header, SpeakDirective)
import time

def get_progressive_response(handler_input):
    # type: (HandlerInput) -> None
    request_id_holder = handler_input.request_envelope.request.request_id
    directive_header = Header(request_id=request_id_holder)
    speech = SpeakDirective(speech="わかりました。少々お待ちください")
    directive_request = SendDirectiveRequest(
        header=directive_header, directive=speech)

    directive_service_client = handler_input.service_client_factory.get_directive_service()
    directive_service_client.enqueue(directive_request)
    time.sleep(5)
    return

ListManagementServiceClient

ListManagementServiceClientを使用して、Alexaのデフォルトリストやユーザーが保持しているカスタムリストの読み取りや変更を行うためにリスト管理APIにアクセスできます。

インターフェース

class ask_sdk_model.services.list_management.ListManagementServiceClient:
    def get_lists_metadata(self):
        # type: () -> Union[ForbiddenError, Error, AlexaListsMetadata]

    def get_list(self, list_id, status):
        # type: (str, str) -> Union[AlexaList, Error]

    def get_list_item(self, list_id, item_id):
        # type: (str, str) -> Union[AlexaListItem, Error]

    def create_list(self, create_list_request):
        # type: (CreateListRequest) -> Union[Error, AlexaListMetadata]

    def create_list_item(self, list_id, create_list_item_request):
        # type: (str, CreateListItemRequest) -> Union[AlexaListItem, Error]

    def update_list(self, list_id, update_list_request):
        # type: (str, UpdateListRequest) -> Union[Error, AlexaListMetadata]

    def update_list_item(self, list_id, item_id, update_list_item_request):
        # type: (str, str, UpdateListItemRequest) -> Union[AlexaListItem, Error]

    def delete_list(self, list_id):
        # type: (str) -> Union[Error]

    def delete_list_item(self, list_id, item_id):
        # type: (str, str) -> Union[Error]

モデルの詳細については、こちら(英語)を参照してください。

MonetizationServiceClient

スキル内課金サービス

SDKには、inSkillPurchase APIを呼び出すMonetizationServiceClientが用意されています。このAPIでは、現在のスキルに関連付けられているすべてのスキル内商品を取得し、各商品が課金可能かまたは現在のユーザーが既に課金済みかを確認できます。

インターフェース

class ask_sdk_model.services.monetization.MonetizationServiceClient:
    def get_in_skill_products(
        self, accept_language, purchasable=None, entitled=None,
        product_type=None, next_token=None, max_results=None):
        # type: (str, Optional[PurchasableState], Optional[EntitledState], Optional[ProductType], Optional[str], Optional[float]) -> Union[Error, InSkillProductsResponse]

    def get_in_skill_product(self, accept_language, product_id):
        # type: (str, str) -> Union[Error, InSkillProduct]

class ask_sdk_model.services.monetization.InSkillProductsResponse:
    def __init__(self, in_skill_products=None, is_truncated=None, next_token=None):
        # type: (Optional[List[InSkillProduct]], Optional[bool], Optional[str]) -> None

class ask_sdk_model.services.monetization.InSkillProduct:
self, product_id=None, reference_name=None, name=None, object_type=None, summary=None, purchasable=None, entitled=None, active_entitlement_count=None, purchase_mode=None
    def __init__(
        self, product_id=None, reference_name=None, name=None,
        object_type=None, summary=None, purchasable=None, entitled=None,
        active_entitlement_count=None, purchase_mode=None):
        # type: (Optional[str], Optional[str], Optional[str], Optional[ProductType], Optional[str], Optional[PurchasableState], Optional[EntitledState], Optional[int], Optional[PurchaseMode]) -> None

class ask_sdk_model.services.monetization.ProductType(Enum):
    SUBSCRIPTION = "SUBSCRIPTION"
    ENTITLEMENT = "ENTITLEMENT"
    CONSUMABLE = "CONSUMABLE"

class ask_sdk_model.services.monetization.PurchasableState(Enum):
    PURCHASABLE = "PURCHASABLE"
    NOT_PURCHASABLE = "NOT_PURCHASABLE"

class ask_sdk_model.services.monetization.EntitledState(Enum):
    ENTITLED = "ENTITLED"
    NOT_ENTITLED = "NOT_ENTITLED"

class ask_sdk_model.services.monetization.PurchaseMode(Enum):
    TEST = "TEST"
    LIVE = "LIVE"

モデルの詳細については、こちら(英語)を参照してください。

サンプルコード

get_in_skill_products

get_in_skill_productsメソッドは、現在のスキルに関連付けられているすべてのスキル内商品を取得し、現在のスキルとユーザーについて各スキル内商品の課金可能性と買い切り型商品のステータスを示します。

from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_core.utils import is_request_type
from ask_sdk_model.response import Response
from ask_sdk_model.services.monetization import (
    EntitledState, PurchasableState, InSkillProductsResponse)

class LaunchRequestHandler(AbstractRequestHandler):
    def can_handle(self, handler_input):
        return is_request_type("LaunchRequest")(handler_input)

    def handle(self, handler_input):
        locale = handler_input.request_envelope.request.locale
        ms = handler_input.service_client_factory.get_monetization_service()
        product_response = ms.get_in_skill_products(locale)

        if isinstance(product_response, InSkillProductsResponse):
            total_products = len(product_response.in_skill_products)
            entitled_products = len([l for l in product_response.in_skill_products
                                 if l.entitled == EntitledState.ENTITLED])
            purchasable_products = len([l for l in product_response.in_skill_products
                                    if l.purchasable == PurchasableState.PURCHASABLE])

            speech = (
                "合計{}個の商品が見つかりました。そのうち{}個が課金可能で、{}個が"
                "購入済みです".format(
                    total_products, purchasable_products, entitled_products))
        else:
            speech = "購入履歴のロード中に問題が発生しました。"

        return handler_input.response_builder.speak(speech).response

API応答にはスキル内商品レコードの配列が含まれます。

get_in_skill_product

get_in_skill_product APIは指定されたproductIdで識別される単一のスキル内商品の商品レコードを取得します。

from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_core.utils import is_request_type
from ask_sdk_model.response import Response
from ask_sdk_model.services.monetization import InSkillProduct

class LaunchRequestHandler(AbstractRequestHandler):
    def can_handle(self, handler_input):
        return is_request_type("LaunchRequest")(handler_input)

    def handle(self, handler_input):
        locale = handler_input.request_envelope.request.locale
        ms = handler_input.service_client_factory.get_monetization_service()
        product_id = "amzn1.adg.product.<GUID>"
        product_response = ms.get_in_skill_product(locale)

        if isinstance(product_response, InSkillProduct):
            # InSkillProductを処理するコードがここに入ります
            speech = ""
            pass
        else:
            speech = "商品のロード中に問題が発生しました。"

        return handler_input.response_builder.speak(speech).response

API応答には単一のスキル内商品レコードが含まれます。

これらのAPIとスキル実装での使い方の詳細については、こちらを参照してください。 カスタムスキルへのスキル内課金の追加

スキル内課金のインターフェース

SDKには、スキルでAlexaからスキル内課金とキャンセルのリクエストを開始するためのadd_directive()メソッドが用意されています。Amazonシステムはユーザーとの音声による対話を管理し、課金取引を処理して、ステータス応答をリクエスト元のスキルに返します。このインターフェースを使用して、以下の3つのアクションがサポートされます。

  • Upsell
  • Buy
  • Cancel

これらのアクションと推奨されるユースケースの詳細については、こちらを参照してください。 カスタムスキルへのスキル内課金の追加

サンプルコード

Upsell

スキルは、ユーザーが明示的にコンテキストをリクエストしなかった場合にスキルのコンテキストを提供するためにUpsellアクションを開始する必要があります。たとえば、無料のコンテンツが提供されている間または後です。Upsellアクションを開始するには、製品IDとアップセルメッセージが必要です。アップセルメッセージを使って、開発者はAlexaで価格を提示する前にユーザーにスキル内商品を提示する方法を指定できます。

from ask_sdk_model.interfaces.connections import SendRequestDirective

# スキルフローでは、ユーザーから明示的な依頼なしで
# スキル内商品を提供するために意思決定がなされた場合


return handler_input.response_builder.add_directive(
        SendRequestDirective(
            name="Upsell",
            payload={
                "InSkillProduct": {
                    "productId": "<product_id>",
                },
                "upsellMessage": "<スキル内商品のアップセル用紹介説明>",
            },
            token="correlationToken")
    ).response
Buy

スキルは、ユーザーが特定のスキル内商品の課金をリクエストしたときにBuyアクションを開始します。Buyアクションを開始するには、product_idが必要です。

from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_core.utils import is_intent_name
from ask_sdk_model.response import Response
from ask_sdk_model.interfaces.connections import SendRequestDirective

# スキル内商品を購入するためにユーザーのインテントをキャプチャするカスタムインテント
# (下のBuyProductIntent)を実装し、次にこれに対してBuyリクエストをトリガーします。
# 例:'アレクサ、<商品名>を買って'

class BuyProductIntentHandler(AbstractRequestHandler):
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool
        return is_intent_name("BuyProductIntent")(handler_input)

    def handle(self, handler_input):
        # type: (HandlerInput) -> Response

        # InSkillProducts APIを呼び出してリクエストしたスキル内商品の
        # product_idを取得します。
        # 以下で使われているスロット数product_nameはデモ用です。

        locale = handler_input.request_envelope.request.locale
        ms = handler_input.service_client_factory.get_monetization_service()

        product_response = ms.get_in_skill_products(locale)
        slots = handler_input.request_envelope.request.intent.slots
        product_ref_name = slots.get("product_name").value
        product_record = [l for l in product_response.in_skill_products
                          if l.reference_name == product_ref_name]

        if product_record:
            return handler_input.response_builder.add_directive(
                SendRequestDirective(
                    name="Buy",
                    payload={
                        "InSkillProduct": {
                            "productId": product_record[0].product_id
                        }
                    },
                    token="correlationToken")
            ).response
        else:
            return handler_input.response_builder.speak(
                "すみません。その商品は課金できません"
                ).response
Cancel

スキルは、ユーザーがサポートされているスキル内商品の既存の買い切り型アイテムまたはサブスクリプションのキャンセルをリクエストしたときにCancelアクションを開始します。Cancelアクションを開始するには、product_idが必要です。

from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_core.utils import is_intent_name
from ask_sdk_model.response import Response
from ask_sdk_model.interfaces.connections import SendRequestDirective

# スキル内商品をキャンセルするためにユーザーのインテントをキャプチャするカスタムインテント
# (下のCancelProductIntent)を実装し、次にこれに対してCancelリクエストをトリガーします。
# 例:'アレクサ、<商品名>をキャンセルして'

class CancelProductIntentHandler(AbstractRequestHandler):
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool
        return is_intent_name("CancelProductIntent")(handler_input)

    def handle(self, handler_input):
        # type: (HandlerInput) -> Response

        # InSkillProducts APIを呼び出してリクエストしたスキル内商品の
        # product_idを取得します。
        # 以下で使われているスロット数product_nameはデモ用です。

        locale = handler_input.request_envelope.request.locale
        ms = handler_input.service_client_factory.get_monetization_service()

        product_response = ms.get_in_skill_products(locale)
        slots = handler_input.request_envelope.request.intent.slots
        product_ref_name = slots.get("product_name").value
        product_record = [l for l in product_response.in_skill_products
                          if l.reference_name == product_ref_name]

        if product_record:
            return handler_input.response_builder.add_directive(
                SendRequestDirective(
                    name="Cancel",
                    payload={
                        "InSkillProduct": {
                            "productId": product_record[0].product_id
                        }
                    },
                    token="correlationToken")
            ).response
        else:
            return handler_input.response_builder.speak(
                "すみません。わかりません").response

UpsServiceClient

UpsServiceClientを使用して、AlexaユーザープロフィールAPIに対してユーザーの連絡先情報を照会したり、Alexaユーザー設定APIに対してユーザーのタイムゾーン設定、長さの単位、および温度の単位を取得できます。

インターフェース

class ask_sdk_model.services.ups.UpsServiceClient:
    def get_profile_email(self):
        # type: () -> Union[str, Error]

    def get_profile_given_name(self):
        # type: () -> Union[str, Error]

    def get_profile_mobile_number(self):
        # type: () -> Union[PhoneNumber, Error]

    def get_profile_name(self):
        # type: () -> Union[str, Error]

    def get_system_distance_units(self, device_id):
        # type: (str) -> Union[Error, DistanceUnits]

    def get_system_temperature_unit(self, device_id):
        # type: (str) -> Union[TemperatureUnit, Error]

    def get_system_time_zone(self, device_id):
        # type: (str) -> Union[str, Error]

class ask_sdk_model.services.ups.PhoneNumber:
    def __init__(self, country_code=None, phone_number=None):
        # type: (Optional[str], Optional[str]) -> None

class ask_sdk_model.services.DistanceUnits(Enum):
    METRIC = "METRIC"
    IMPERIAL = "IMPERIAL"

class ask_sdk_model.services.TemparatureUnit(Enum):
    CELSIUS = "CELSIUS"
    FAHRENHEIT = "FAHRENHEIT"

サンプルコード

Alexaユーザー設定API

Alexaユーザー設定APIは、設定されている長さの単位、温度の単位、デバイスで現在設定されているタイムゾーンという3つの情報へのアクセスを提供します。UpsServiceClientを使用する場合、get_system_distance_unitsおよびget_system_temperature_unitは列挙オブジェクトを返します。この値は.valueアトリビュートを使ってアクセスする必要があります。一方、get_system_time_zoneは単に文字列を返します。

device_id = req_envelope.context.system.device.device_id
user_preferences_client = handler_input.service_client_factory.get_ups_service()

# Alexa設定APIから設定されている長さの単位を取得します
preferred_distance_units = user_preferences_client.get_system_distance_units(device_id).value
print (preferred_distance_units) # 「IMPERIAL」または「METRIC」の文字列

# Alexa設定APIから設定されている温度の単位を取得します
preferred_temperature_units = user_preferences_client.get_system_temperature_unit(device_id).value
print (preferred_temperature_units) # 「FAHRENHEIT」または「CELSIUS」の文字列

# Alexa設定APIからデバイスで現在設定されているタイムゾーンを取得します
time_zone = user_preferences_client.get_system_time_zone(device_id)
print (time_zone) # タイムゾーンを表す文字列(「America/Los_Angeles」など)

モデルの詳細については、こちら(英語)を参照してください。

ReminderManagementServiceClient

ReminderManagementServiceClientを使用して、ユーザーのリマインダーを作成、管理することができます。

インターフェース

class ask_sdk_model.services.reminder_management.ReminderManagementServiceClient:
    def create_reminder(self, reminder_request):
        # type: (ReminderRequest) -> Union[ReminderResponse, Error]

    def update_reminder(self, alert_token, reminder_request):
        # type: (str, ReminderRequest) -> Union[ReminderResponse, Error]

    def delete_reminder(self, alert_token):
        # type: (str) -> Union[Error]

    def get_reminder(self, alert_token):
        # type: (str) -> Union[GetReminderResponse, Error]

    def get_reminders(self):
        # type: () -> Union[GetRemindersResponse, Error]

サンプルコード

以下は、ReminderManagementServiceClientのインスタンスを作成し、新しいリマインダーを作成するリクエストハンドラーの例です。

import logging
import typing

from datetime import datetime
from ask_sdk_core.skill_builder import CustomSkillBuilder
from ask_sdk_model.ui import SimpleCard
from ask_sdk_core.utils import is_intent_name
from ask_sdk_core.api_client import DefaultApiClient
from ask_sdk_model.services.reminder_management import (
    ReminderRequest, Trigger, TriggerType, AlertInfo, PushNotification,
    PushNotificationStatus, ReminderResponse, SpokenInfo, SpokenText)
from ask_sdk_model.services import ServiceException
from ask_sdk_model.ui import AskForPermissionsConsentCard

if typing.TYPE_CHECKING:
    from ask_sdk_core.handler_input import HandlerInput
    from ask_sdk_model import Response

permissions = ["alexa::alerts:reminders:skill:readwrite"]
NOTIFY_MISSING_PERMISSIONS = ("アマゾンアレクサアプリでリマインダーの権限を"
                              "有効にしてください。")


sb = CustomSkillBuilder(api_client=DefaultApiClient())
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)


@sb.request_handler(can_handle_func=is_intent_name("CreateReminder"))
def create_reminder_intent_handler(handler_input):
    # type: (HandlerInput) -> Response
    req_envelope = handler_input.request_envelope
    response_builder = handler_input.response_builder

    # ユーザーがリマインダーを作成する権限を与えたかどうかを確認します。
    # 権限が与えられていない場合、スキルに権限を与えるようにリクエストします。
    if not (req_envelope.context.system.user.permissions and
            req_envelope.context.system.user.permissions.consent_token):
        response_builder.speak(NOTIFY_MISSING_PERMISSIONS)
        response_builder.set_card(
            AskForPermissionsConsentCard(permissions=permissions))
        return response_builder.response

    reminder_client = handler_input.service_client_factory.get_reminder_management_service()

    try:
        reminder_response = reminder_client.create_reminder(
            reminder_request=ReminderRequest(
                request_time=datetime.utcnow(),
                trigger=Trigger(
                    object_type=TriggerType.SCHEDULED_RELATIVE,
                    offset_in_seconds=60),
                alert_info=AlertInfo(
                    spoken_info=SpokenInfo(
                        content=[SpokenText(locale="en-US", text="Test reminder")])),
                push_notification=PushNotification(
                    status=PushNotificationStatus.ENABLED))) # type: ReminderResponse
        speech_text = "はい、 リマインダーを設定しました。"

        logger.info("Created reminder : {}".format(reminder_response))
        return handler_input.response_builder.speak(speech_text).set_card(
            SimpleCard(
                "Reminder created with id", reminder_response.alert_token)).response

    except ServiceException as e:
        logger.info("Exception encountered : {}".format(e.body))
        speech_text = "申し訳ありません。エラーが発生しました。"
        return handler_input.response_builder.speak(speech_text).set_card(
            SimpleCard(
                "Reminder not created",str(e.body))).response

モデルの詳細については、こちら(英語)を参照してください。