AWS Messaging & Targeting Blog
Visually build telephony applications with AWS Step Functions
Developers face numerous challenges when building telephony applications: managing unpredictable user responses, handling disconnections, processing incorrect inputs, and addressing errors. These challenges extend development cycles and create unstable applications that fail to meet user expectations.
This blog demonstrates how Amazon Web Services (AWS) Step Functions, combined with Amazon Chime SDK Public Switched Telephone Network (PSTN) audio service, offers a solution to overcome these challenges.
Overview of the solution
To demonstrate our solution, we built a sample telephony application that lets business owners manage customer calls through a dedicated business phone number. This solution helps small business owners separate personal and business communications, while managing all calls from their existing phone.
The beta version of this sample application delivers these six core call flows:
- During business hours: Routes incoming customer calls to the business owner
- After hours: Enables customers to leave voice messages
- Message retrieval: Allows owner to access customer voice messages
- Business caller ID: Enables owner to call customers using the business number
- Call scheduling: Permits owner to schedule customer calls for later in the day
- Automated calling: Initiates scheduled calls between owner and customer automatically
Using Workflow Studio, we built a Step Functions workflow (Figure 1) that processes all six call flows and handles unexpected scenarios.

Figure 1 – Step Functions telephony workflow designed in Workflow Studio
How it works
AWS Step Functions enable agile visual workflow design, through pre-built components and error handling rules. This creates workflows composed of event-driven states that input, process, and output JavaScript Object Notation (JSON)-formatted messages. The PSTN audio service streamlines telephony applications through its serverless approach using a request/response programming model. It invokes AWS Lambda functions with Events and waits for Actions responses, both in predefined JSON formats. This shared JSON format enables seamless integration between the PSTN audio service and Step Functions, leading us to design a serverless architecture (Figure 2) that allows for bidirectional JSON message exchange between the two services.

Figure 2 – Serverless architecture for Step Functions and PSTN audio service integration
Main components:
- eventRouter: Lambda function managing JSON message exchange
- appWorkflow: Step Functions implementing call flow logic
- actionsQueue: Amazon Simple Queue Service (Amazon SQS) queue storing response actions
Architecture flow:
- PSTN audio service receives inbound call
- Service sends NEW_INBOUND_CALL event to eventRouter
- eventRouter creates the actionsQueue
- eventRouter asynchronously executes appWorkflow with event data
- eventRouter begins long-polling from actionsQueue, waiting for next action(s) message
- appWorkflow processes JSON-formatted event data, computing next action(s)
- appWorkflow queues next action(s) using Amazon SQS SendMessage API with Wait for Callback with Task Token integration pattern to stop the workflow until the next event call is received
- eventRouter retrieves and removes action(s) from actionsQueue
- eventRouter returns action(s) to PSTN audio service
Observations:
- eventRouter code logic is generic and agnostic from the calls and different Step Function workflows
- eventRouter queries an environment variable to determine the workflow to call
- Pairs of actionsQueue and appWorkflow instances lives for the duration of each call
- eventRouter is responsible for the creation and deletion of each actionsQueue
- appWorkflow instances are created by the eventRouter at the start of each call
- appWorkflow instances complete its execution when all parties involved on the call hang up
Building your telephony application
Prerequisites:
- Familiarity with developing workflows in Step Functions Workflow Studio
- Access to AWS Management Console
Implementation Guidelines:
- Create dedicated Step Functions workflows for each telephony application
- Design and implement workflows using Workflow Studio
- Use a Standard workflow type to accommodate extended call durations
- Update the eventRouter Lambda function’s “CallFlowsDIDMap” environment variable to map phone numbers to their workflow Amazon Resource Name (ARN)
- Set workflow variables in the “Init” state Variables tab (Figure 3). The eventRouter function automatically sets “QueueUrl”, and adding other variables here removes the need for external storage

Figure 3 – Step Functions “Init” state Variables tab showing workflow data configuration
- Configure Choice state rules to route calls based on conditions. Rules one through three (Figure 4) handle call routing based on inbound/outbound direction, owner/customer identification, while the default rule manages unexpected scenarios.

Figure 4 – Step Functions Choice state defines rules for call routing decisions
- Configure the SQS: SendMessage state (Figure 5) to instruct the next action to the PSTN audio service by:
- Formatting the message content to match supported actions for the PSTN audio service
- Setting TransactionAttributes to pass back and forth the values of the “WaitToken” and “QueueUrl” throughout the call duration
- Enabling the Wait for Callback with a Task Token integration pattern

Figure 5 – SQS: SendMessage state configuration for PSTN audio service callback integration
- Leverage AWS service integration states to interact with other AWS services directly from the workflow.
- Example: Use a DynamoDB PutItem state (Figure 6) to store Amazon Simple Storage Service (Amazon S3) recording files, including bucket name and key, in Amazon DynamoDB.

Figure 6 – AWS service integration states enable direct service connections without custom code
- Utilize JSONata expressions (Figure 7) to minimize the number of Lambda functions.
- Example: For Amazon EventBridge scheduling, compute time expressions using JSONata functions [$fromMillis(), $millis(), number()] and string concatenation to handle customer call scheduling.

Figure 7 – JSONata expressions for direct data transformation without Lambda functions
- Use Step Functions error handling with success and fail states (Figure 8) to manage error paths and call termination results.

Figure 8 – Call error handling and termination setup
Key benefits
This approach for building telephony applications offers multiple advantages:
- Visual workflow-based designer
- Self-document call flow logic
- Managed versioning and publishing
- Native integration with AWS Services
- Visual log and inspection for each call
- Auto-scalable
- Pay-per-use pricing
Deploying the solution
The following steps allows you to deploy the sample telephony application together with the serverless architecture (Figure 2).
Prerequisites:
- AWS Management Console access
- Node.js and npm installed
- AWS Command Line Interface (AWS CLI) installed and configured
Walkthrough:
The Cloud Development Kit (CDK) project on the AWS GitHub repository will deploy the following resources:
- phoneNumberBusiness – Provisioned phone number for the sample application
- sipMediaApp – SIP media application that routes calls to lambdaProcessPSTNAudioServiceCalls
- sipRule – SIP rule that directs calls from phoneNumberBusiness to sipMediaApp.
- stepfunctionBusinessProxyWorkflow – Step Functions workflow for the sample application
- roleStepfuntionBusinessProxyWorkflow – IAM Role for stepfunctionBusinessProxyWorkflow
- lambdaProcessPSTNAudioServiceCalls – Lambda function for call processing
- roleLambdaProcessPSTNAudioServiceCalls – IAM Role for lambdaProcessPSTNAudioServiceCalls
- dynamoDBTableBusinessVoicemails – DynamoDB table to store customer voicemails
- s3BucketApp –S3 bucket for storing system recordings and customer voicemails
- s3BucketPolicy – IAM Policy granting PSTN audio service access to s3BucketApp
- lambdaOutboundCall – Lambda function for placing scheduled customer calls
- roleLambdaOutboundCall – IAM Role for lambdaOutboundCall
- roleEventBridgeLambdaCall – IAM Role to allow the EventBridge service to execute lambdaOutboundCall
Follow these steps to deploy the CDK stack:
- Clone the repository
- Bootstrap the stack
- Deploy the stack
Call the provisioned phone number to test the sample application. Optionally, edit the workflow to update the business name and working hours on the “Init” Task state, in the Variables tab.
Cleaning up:
To clean up this demo, execute:
Conclusion
This blog demonstrates how combining AWS Step Functions and Amazon Chime SDK PSTN audio service streamlines the development of reliable telephony applications through visual workflow design and managed error handling. We provided a sample application, implementing six core business phone features, showcasing how the solution effectively manages multiple conditional paths and edge cases like disconnections and invalid inputs.
The serverless architecture created enables seamless integration between the two services through JSON-based communication, while providing automatic scaling and pay-per-use pricing. Together, these components create a robust foundation for building sophisticated telephony applications that reduce maintenance costs and enhance reliability.
Contact an AWS Representative to know how we can help accelerate your business.