Amazon Connect: Scaling Development and Testing — Part 2
By Cody Jenkins
In Part 1 of our blog, we set out to answer a number of questions around scaling up development of Amazon Connect. In short, we found two things. First, it is possible to write a fully automated test framework to validate Contact Flow logic. However, we also found that the Connect API is not expressive enough yet to run automated deployments to pre-prod and prod environments.
This post continues the journey as we try to answer these questions:
- Is there some way to “pass through” the conversation from Connect to another NLU solution like Rasa?
- Is there really no way to automate deployments of our flow logic?
Let’s get right back into it!
Integration with a different NLU solution
As of today, Connect’s “Get customer input” blocks only have native support for dial-tone input and Lex integration. There is no easy way to integrate with a different Natural Language Understanding (NLU) solution like Rasa. Despite these limitations, we wanted to see if we could find a way to “pass” through to Rasa anyway.
After a lot of digging with Connect, Lex and Lambda, we finally struck paydirt. Lex has a special built-in intent for handling “fallback” scenarios: AMAZON.FallbackIntent. This intent matches when nothing else does. Here’s what it looks like in Lex:
As with any Lex intent, you may invoke a Lambda function which receives the Lex event as an input. And, as with any Lex invocation, you get a transcription of the intent provided by the user. Since we’re integrating directly from Connect to Lex, we get voice-to-text transcription for free! We can take that transcript and pass it through to a Rasa webhook or anywhere else we like. That solves half of the equation.
But what about Rasa’s response? And what if we expect a few bits of back-and-forth between the user and Rasa? We need to close the loop.
Achieving this is actually quite straightforward. Once Lambda has processed the original user intent, it responds to Lex with a message for the user and an instruction to elicit a new intent. When the user responds, we hit the FallbackIntent again and the cycle repeats. Or If we want to exit the loop, Lambda responds to Lex with a concluding message and an instruction to close the dialogue.
Now we have a closed loop! In addition to this closed loop, Lex and Lambda can easily maintain any conversation state with the sessionAttributes field. Now we’re really cooking!
An unexpected surprise!
If you followed along closely, you might have realised that our “Fallback Loop” solution doesn’t only work well as a passthrough for other NLU solutions. In fact, this loop structure opens up a much wider range of possibilities.
Thinking back to our user authentication example with customer Jen, there is another way we can define the authentication logic and error handling.
The “Connect way” will require us to drag and drop 3 “Get customer input” blocks for each of the 3 identity check steps and, wire them up to each other, add in a validation block, add in a branching block, and then wire up the error paths to the appropriate error handling paths.
In the “Fallback loop” solution, though, we may use a single loop and handle all of the user input collection, validation, and error handling in the Lambda code! You’re even covered in the case where you want to use dial-tone keypad input: Connect and Lex support dial-tone parsing out of the box.
Now the possibilities really open up. If we can define most of our routing logic in one or more Fallback Loops, that means we may write unit and integration tests against the code, and we may use a CD approach to deploy, test, and promote changes.
Though Connect doesn’t come with native CD capabilities, it seems that we’ve finally got a way to reap the benefits of Amazon Connect without compromising on development scalability. This was our last and most exciting finding.
Bringing it all home
At the end of our two week investigation, we found a lot of useful and useless techniques for scaling the development of an Amazon Connect project. At the end, these were our takeaways:
Can we build a test automation framework for validating the Contact Flow logic?
Yes, we can use the Chat API to exercise the logic. But some Contact Flow blocks are problematic. By moving those blocks into separate Contact Flows, we may achieve some level of automated testing on the remaining flows, albeit with a long feedback loop. You still have to “Publish” a flow before you may test the logic.
Can we use the AWS API to automate creation and configuration of Connect and the Contact Flows?
No, but there is another way. If you use the “loop” solution we propose above, you can move the problem out of the Connect domain and into the Lambda domain. And if you pull enough of your routing logic into Lambda, you can reap the benefits of CI/CD there instead. Once you exit the “loop”, Connect can use the sessionAttributes to route the user to the correct Queue and/or Transfer. You can even set the Queue dynamically using the data returned by the Lambda.
Is there some way to “pass through” the conversation from Connect to another NLU system like Rasa?
Yes, but you will have to rely on the transcription powers of Connect and Lex and that is sometimes unreliable. To mitigate this, create custom Lex intents and slots within the loop to help improve the transcription.
Though Amazon Connect has been out for a little over 2 years, there are still a few rough edges to contend with when it comes to automated testing and continuous delivery strategies. We’ve found a couple of tricks to get around these limitations, but they’re not perfect. We will continue to experiment with different configurations to understand more about the limitations and possibilities.
There may come a time when Amazon Connect’s API is a bit more full-featured and we can drop the “Fallback Loop” entirely. But at least now we have a way to deliver an Amazon Connect solution in a testable, repeatable way.