Use Skill Connections to Request Tasks
An Alexa skill can use a skill connection to request a task from Amazon or from a provider skill. For example, a recipe skill can request that a printer skill print a recipe. Before you make your skill a requester skill, determine what task you want a provider skill to fulfill, and whether you want to use an Amazon-predefined task, or a custom task that's offered by a provider skill. For an overview of skill connections, see Understand Skill Connections.
Request a task from a provider skill
A requester skill requests a task from a provider skill. If possible, the provider skill fulfills the request of the requester skill.
To pass control to the provider, the skill sends a Connections.StartConnection
directive. To pass control back to the skill after verifying the user, Alexa sends a SessionResumedRequest
to the skill. If you have an existing skill, you can modify this skill so that it becomes a requester, which means that it can request a task from skills that are providers.
When requesting a task from a provider skill, the requester skill can specify whether it should receive control back after the task is completed, by setting one of the following values in the onCompletion
field:
- Specify
RESUME_SESSION
to receive control back and return the user to the same place in the original requester skill session. - Specify
SEND_ERRORS_ONLY
to be notified of errors, without getting control back. - The default setting is
RESUME_SESSION
.
To make your skill a requester for a skill connections task
- Implement a handler to return a
Connections.StartConnection
directive.Important: When responding to a request with aTasks.CompleteTask
orConnections.StartConnection
directive, your response cannot include audio or video player directives. - Depending on the
onCompletion
value you specified in your requester skill'sConnections.StartConnection
directive, implement one of the following.- If your requester skill specifies
RESUME_SESSION
, implement a handler to receive the response from aSessionResumedRequest
request. When the provider skill completes its task, this handler enables the provider skill to return control to your requester skill. - If your requester skill specifies
SEND_ERRORS_ONLY
, implement a handler to receive the response from aSystem.ExceptionEncountered
request. If the provider skill fails to complete its task, this handler enables Alexa to return error notification to your requester skill.
- If your requester skill specifies
Transition prompt
During the transition from the requester skill to the provider skill, Alexa always renders a forwarding prompt. This happens whether the requester skill specifies RESUME_SESSION
or SEND_ERRORS_ONLY
in the Connections.StartConnection
directive. This prompt cannot be customized.
- Got it. {requester_skill_name} would like to use the skill {provider_skill_name} to do that. May I send the request to {provider_skill_name}?
If the requester skill specifies SEND_ERRORS_ONLY
, Alexa doesn't render a returning prompt. If the requester skill specifies RESUME_SESSION
, Alexa always renders a returning prompt during the transition from the provider skill back to the requester skill. This prompt cannot be customized.
- Returning you to {requester_skill_name}.
Implement a handler to return a Connections.StartConnection
directive to use skill connection
Your requester skill sends a skill connections request by setting the Connections.StartConnection
directive in the response object, as shown in the following examples.
Tasks.CompleteTask
or Connections.StartConnection
directive, your response cannot include audio or video player directives.Return Connections.StartConnection
directive with RESUME_SESSION
set explicitly or by default
When setting the onCompletion
field to RESUME_SESSION
, your service code must leave the shouldEndSession
flag undefined when it returns a Connections.StartConnection
directive.
shouldEndSession
flag undefined if you don't set a value for the onCompletion
field. For managed skill connection
Only Amazon predefined tasks are supported in managed skill connection. In the following example, the format for task_name
should always be AMAZON.{name}
, for example, AMAZON.PrintPDF
.
return handlerInput.responseBuilder
.addDirective({
'type': 'Connections.StartConnection',
'uri': 'connection://{task_name}/{version_number}',
'input': {
...
},
'onCompletion': 'RESUME_SESSION',
'token': '...'
})
.getResponse();
Note that the onCompletion
field is not required, and RESUME_SESSION
is the default value, so the following example has the same effect as the preceding one:
return handlerInput.responseBuilder
.addDirective({
'type': 'Connections.StartConnection',
'uri': 'connection://{task_name}/{version_number}',
'input': {
...
},
'token': '...'
})
.getResponse();
For direct skill connection
Both Amazon predefined tasks and custom tasks are supported in direct skill connection.
In the following example, there are two different formats for task_name
:
- For Amazon predefined tasks, the format is
AMAZON.{name}
, for example,AMAZON.PrintPDF
- For custom tasks, the format is
{provider_skill_id}.{name}
, for example,amzn1.ask.skill.12345678-90ab-cdef-1234-567890abcdef.CountDown
return handlerInput.responseBuilder
.addDirective({
'type': 'Connections.StartConnection',
'uri': 'connection://{task_name}/{version_number}?provider={provider_skill_id}',
'input': {
...
},
'onCompletion': 'RESUME_SESSION',
'token': '...'
})
.getResponse();
Return Connections.StartConnection
directive with SEND_ERRORS_ONLY
When setting the onCompletion
field to SEND_ERRORS_ONLY
, your service code must set the shouldEndSession
flag to true
.
For managed skill connection
Only Amazon predefined tasks are supported in managed skill connection. In the following example, the format for task_name
should always be AMAZON.{name}
, for example, AMAZON.PrintPDF
.
return handlerInput.responseBuilder
.addDirective({
'type': 'Connections.StartConnection',
'uri': 'connection://{task_name}/{version_number}',
'input': {
...
},
'onCompletion': 'SEND_ERRORS_ONLY'
})
.withShouldEndSession(true)
.getResponse();
For direct skill connection
Both Amazon predefined tasks and custom tasks are supported in direct skill connection.
In the following example, there are two different formats for task_name
:
- For Amazon predefined tasks, the format is
AMAZON.{name}
, for example,AMAZON.PrintPDF
- For custom tasks, the format is
{provider_skill_id}.{name}
, for example,amzn1.ask.skill.12345678-90ab-cdef-1234-567890abcdef.CountDown
return handlerInput.responseBuilder
.addDirective({
'type': 'Connections.StartConnection',
'uri': 'connection://{task_name}/{version_number}?provider={provider_skill_id}',
'input': {
...
},
'onCompletion': 'SEND_ERRORS_ONLY'
})
.withShouldEndSession(true)
.getResponse();
Response attributes
Attribute | Description |
---|---|
type | Required. Type of the directive, which is Connections.StartConnection in this case.
|
uri | Required. Resource that defines the task and the task version. |
input | Optional. Contains the request object for the task request being sent. |
token | Optional. Token comes back to the skill as-is in the SessionResumedRequest . It can be used to resume the requester skill after the task request is complete.
|
onCompletion | Optional. Enum field that defines whether your requester skill is resumed after the task is completed. It can be either RESUME_SESSION or SEND_ERRORS_ONLY . If it is RESUME_SESSION , the requester skill receives SessionResumedRequest when the task is completed. If it is SEND_ERRORS_ONLY , the requester skill receives System.ExceptionEncountered only when an error happens.The default value is RESUME_SESSION .
|
Implement a handler to receive a response from a skill connections request
If it does not set the onCompletion
attribute to SEND_ERRORS_ONLY
, your requester skill must also implement a handler to receive a skill connection response for the original task request. If you don't implement a response handler, your skill will have an unhandled exception, which means that your requester skill cannot take back control from the provider skill.
To implement a handler to receive a skill connection response for a task request
- Add a
SessionResumedRequest
handler to the skill, as shown in the following example. When the requester skill receives aSessionResumedRequest
, it restores the previous session of the skill from when the originalConnections.StartConnection directive
was returned.
Example: implement a response handler
The following example shows how to implement a handler to receive a response from a skill connections request.
const SessionResumedRequestHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'SessionResumedRequest';
},
handle(handlerInput) {
const status = handlerInput.requestEnvelope.request.cause.status;
const code = status.code;
const message = status.message;
console.log(`SessionResumedRequest received status code : ${code} and message : ${message}`);
// The current sessionId is same as the one in previous IntentRequest when the original Connections.StartConnection directive was returned.
const currentSessionId = handlerInput.requestEnvelope.session.sessionId;
// Continue requester skill experience. In this example, it renders a speech.
return handlerInput.responseBuilder
.speak("Requester skill received SessionResumedRequest")
.getResponse();
}
};
Example: JSON schema for the SessionResumedRequest
request
When onCompletion
is set to RESUME_SESSION
, the requester receives a SessionResumedRequest
object. The result
of the request is defined in the task definition.
result
object, but the exact contents of this object will vary depending on the skill that handled the request. The result
is expected to be a JSON object containing the key-value pairs that the provider skill chose to return.{
"type": "SessionResumedRequest",
"requestId": "string",
"timestamp": "string",
"locale": "string",
"cause": {
"type": "ConnectionCompleted",
"token": "...",
"status": {
"code": "200",
"message": "OK"
},
"result": {
"key1": "value1",
"key2": "value2"
}
}
}
Status code attributes in SessionResumedRequest
For managed skill connection
Alexa can return any of the following status codes on a task request call.
The provider skill that is fulfilling the task request can return any valid HTTP code.
status
: Status of the requestcode
: status code200
: Request was successfully fulfilled204
: User denied to use the Connection227
: Provider was not account linked400
: Bad request - request was invalid403
: Requester was not allowed to invoke provider404
: No providers available at this time500
: Server error
message
: Plain string message that describes the outcome of the request. For example, this message might be "Ride has been booked successfully."
For direct skill connection
The requester skill will only receive the following status codes. The provider skill that is fulfilling the task request can only return one of the following status code.
status
: Status of the requestcode
: status code200
: Request was successfully fulfilled400
: Bad request - request was invalid403
: Requester was not allowed to invoke provider404
: No providers available at this time500
: Server error
message
: Plain string message that describes the outcome of the request. For example, this message might be "Ride has been booked successfully."
For more information, see Handle Requests Sent by Alexa.
Implement a handler to handle System.ExceptionEncountered
If your requester skill sets onCompletion
to SEND_ERRORS_ONLY
and you want to know if the requested task is not completed, you must implement a handler in the requester skill to handle the System.ExceptionEncountered
request. The System.ExceptionEncountered
request looks like the following example.
{
"type": "System.ExceptionEncountered",
"requestId": "unique.id.for.the.request",
"timestamp": "timestamp of request in format: 2018-04-11T15:15:25Z",
"locale": "a locale code such as en-US",
"error": {
"type": "error code such as INVALID_RESPONSE",
"message": "description of the error that occurred"
},
"cause": {
"requestId": "unique identifier for the request that caused the error"
}
}
Following is example code for handling System.ExceptionEncountered
. Note: This request is for notification only, and any response is ignored.
const SystemExceptionEncounteredHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'System.ExceptionEncountered';
},
handle(handlerInput) {
console.dir(handlerInput.requestEnvelope.request);
return handlerInput.responseBuilder
.getResponse();
},
};
Error types in System.ExceptionEncountered
request
For both managed skill connections and direct skill connections, requester skills receive only the following error types in the System.ExceptionEncountered
request.
error
: Contains an object with error informationtype
: Identifies the specific type of error:INVALID_RESPONSE
: The response from the requester skill to start a connection was invalid.INTERNAL_ERROR
: An internal service error occurred.
message
: A description of the error the device has encountered, for example, "The ride booking request failed."
Task request examples
The following examples show how a skill might request the fulfillment of an Amazon predefined task AMAZON.PrintPDF
and custom task amzn1.ask.skill.12345678-90ab-cdef-1234-567890abcdef.CountDown
when handling an IntentRequest
.
For managed skill connection with RESUME_SESSION
const TestIntentRequestHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest'
&& request.intent.name === 'TestIntent';
},
handle(handlerInput) {
return handlerInput.responseBuilder
.addDirective({
'type': 'Connections.StartConnection',
'uri': 'connection://AMAZON.PrintPDF/1',
'onCompletion': 'RESUME_SESSION',
'input': {
'@type': 'PrintPDFRequest',
'@version': '1',
'title': 'title',
'description': 'description',
'url': 'http://www.example.com/flywheel.pdf'
},
'token': '...'
})
.getResponse();
}
};
For managed skill connection with SEND_ERRORS_ONLY
const TestIntentRequestHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest'
&& request.intent.name === 'TestIntent';
},
handle(handlerInput) {
return handlerInput.responseBuilder
.addDirective({
'type': 'Connections.StartConnection',
'uri': 'connection://AMAZON.PrintPDF/1',
'onCompletion': 'SEND_ERRORS_ONLY',
'input': {
'@type': 'PrintPDFRequest',
'@version': '1',
'title': 'title',
'description': 'description',
'url': 'http://www.example.com/flywheel.pdf'
}
})
.withShouldEndSession(true)
.getResponse();
}
};
For Amazon predefined task direct skill connection with RESUME_SESSION
const TestIntentRequestHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest'
&& request.intent.name === 'TestIntent';
},
handle(handlerInput) {
return handlerInput.responseBuilder
.addDirective({
'type': 'Connections.StartConnection',
'uri': 'connection://AMAZON.PrintPDF/1?provider=amzn1.ask.skill.12345678-90ab-cdef-1234-567890abcdef',
'onCompletion': 'RESUME_SESSION',
'input': {
'@type': 'PrintPDFRequest',
'@version': '1',
'title': 'title',
'description': 'description',
'url': 'http://www.example.com/flywheel.pdf'
},
'token': '...'
})
.getResponse();
}
};
For Amazon predefined task direct skill connection with SEND_ERRORS_ONLY
const TestIntentRequestHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest'
&& request.intent.name === 'TestIntent';
},
handle(handlerInput) {
return handlerInput.responseBuilder
.addDirective({
'type': 'Connections.StartConnection',
'uri': 'connection://AMAZON.PrintPDF/1?provider=amzn1.ask.skill.12345678-90ab-cdef-1234-567890abcdef',
'onCompletion': 'SEND_ERRORS_ONLY',
'input': {
'@type': 'PrintPDFRequest',
'@version': '1',
'title': 'title',
'description': 'description',
'url': 'http://www.example.com/flywheel.pdf'
}
})
.withShouldEndSession(true)
.getResponse();
}
};
For custom task direct skill connection with RESUME_SESSION
const TestIntentRequestHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest'
&& request.intent.name === 'TestIntent';
},
handle(handlerInput) {
return handlerInput.responseBuilder
.addDirective({
'type': 'Connections.StartConnection',
'uri': 'connection://amzn1.ask.skill.12345678-90ab-cdef-1234-567890abcdef.CountDown/1?provider=amzn1.ask.skill.12345678-90ab-cdef-1234-567890abcdef',
'onCompletion': 'RESUME_SESSION',
'input': {
'upperLimit': 10,
'lowerLimit': 1
},
'token': '...'
})
.getResponse();
}
};
For custom task direct skill connection with SEND_ERRORS_ONLY
const TestIntentRequestHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest'
&& request.intent.name === 'TestIntent';
},
handle(handlerInput) {
return handlerInput.responseBuilder
.addDirective({
'type': 'Connections.StartConnection',
'uri': 'connection://amzn1.ask.skill.12345678-90ab-cdef-1234-567890abcdef.CountDown/1?provider=amzn1.ask.skill.12345678-90ab-cdef-1234-567890abcdef',
'input': {
'upperLimit': 10,
'lowerLimit': 1
},
'onCompletion': 'SEND_ERRORS_ONLY'
})
.withShouldEndSession(true)
.getResponse();
}
};
Test your requester skill
After you make your skill a requester skill, you can test it as you would normally test for other invocations. After your requester skill initiates the task request, Alexa selects a suitable provider for the task request from the list of possible providers, and the Alexa service routes the request to the selected live provider skill.
Additionally, if your requester skill specifies RESUME_SESSION
, you should test how it handles various status codes that it might receive. To test how your skill responds when it receives SessionResumedRequest
with a specific status code, alter your requester skill to return a Connections.StartConnection
directive with the AMAZON.TestStatusCode
task defined. In the return body of this directive, the input includes the status code you want to test.
live
stage. Failure to do so will result in a 404
status code.Example: test how your SessionResumedRequest
handler deals with a 404
status code
To test how your SessionResumedRequest
handler deals with receiving a 404
status code, your skill should return the following directive:
return handlerInput.responseBuilder
.addDirective({
'type': 'Connections.StartConnection',
'uri': 'connection://AMAZON.TestStatusCode/1',
'input': {
'code': '404'
}
})
.getResponse();
The requester skill then receives a SessionResumedRequest
object that contains the status code defined in the input.
{
"type": "SessionResumedRequest",
"requestId": "string",
"timestamp": "string",
"locale": "string",
"cause": {
"type": "ConnectionCompleted",
"status": {
"code": "404",
"message": "Status code testing succeeded"
}
}
}
Publish your requester skill
The certification requirements for a requester skill are no different from the requirements for a skill that is not a requester.
If you have not already published your requester skill, complete the testing and skill submission requirements as usual, and submit your skill for certification. When Amazon certifies your skill, they make it publicly available, and your skill can then function as a requester skill. If Amazon has already certified your skill, and you later make changes to make your skill a requester skill, you make those changes publicly available when you publish them.
For more information about publishing Alexa skills, see Skill Certification and Publication.
Developer support
For inquiries and support, please reach out to the Skill Connections team at skill-connections-v2-beta@amazon.com
Related topics
Last updated: Apr 30, 2024