Skip to contentSkip to navigationSkip to topbar
Page toolsOn this page
Looking for more inspiration?Visit the

AWS connectors


This guide shows how to connect AWS agents to Twilio communication channels using the twilio-agent-connect-aws(link takes you to an external page) package. The package provides connectors that handle channel routing and memory context. This guide covers three connectors: Strands (recommended), Bedrock Agent, and Bedrock AgentCore.

When you're ready to deploy to production, see Deploy to AWS Fargate.


Prerequisites

prerequisites page anchor

Before you begin, make sure you have:

  • TAC SDK installed and configured with your Twilio credentials and a Conversation Configuration (see Add TAC to your agent prerequisites)
  • An AWS account with access to Amazon Bedrock(link takes you to an external page)
  • A Bedrock foundation model activated in your AWS region (for example, Amazon Nova, Anthropic Claude, or Meta Llama)
  • AWS credentials configured locally (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION)
  • Python 3.10+

The twilio-agent-connect-aws package provides connectors for different AWS agent runtimes.

ConnectorUse caseInstall extra
StrandsConnectorBuild agents with the AWS Strands Agents SDK(link takes you to an external page). Recommended for most use cases.strands
BedrockConnectorUse a managed Bedrock Agent(link takes you to an external page) with an agent ID and alias.bedrock
BedrockAgentCoreConnectorUse Bedrock AgentCore(link takes you to an external page) with HTTP and WebSocket runtimes.agentcore

The Strands connector is the simplest way to connect a Bedrock-powered agent to Twilio channels.

Install dependencies

install-dependencies page anchor
pip install twilio-agent-connect-aws[strands,server]

The Strands SDK manages Bedrock calls internally, so no additional AWS environment variables are needed beyond your existing TAC credentials. Make sure your AWS credentials are configured through the standard AWS credential chain(link takes you to an external page) (environment variables, ~/.aws/credentials, or IAM role).

The StrandsConnector takes an agent factory function that creates a new Strands Agent for each conversation. The connector handles memory context, channel routing, and conversation cleanup.

1
from dotenv import load_dotenv
2
from strands import Agent
3
from tac import TAC
4
from tac.core.config import TACConfig
5
from tac.channels.voice import VoiceChannelConfig
6
from tac.channels.sms import SMSChannelConfig
7
from tac.models.session import ConversationSession
8
from tac.server import TACFastAPIServer
9
10
from tac_aws.connectors import StrandsConnector
11
12
load_dotenv()
13
14
tac = TAC(config=TACConfig.from_env())
15
16
17
def create_agent(context: ConversationSession) -> Agent:
18
return Agent(
19
model="amazon.nova-pro-v1:0",
20
system_prompt="You are a helpful customer service agent. Be concise and friendly.",
21
)
22
23
24
connector = StrandsConnector(
25
tac=tac,
26
agent_factory=create_agent,
27
voice_config=VoiceChannelConfig(memory_mode="always"),
28
sms_config=SMSChannelConfig(memory_mode="always"),
29
)
30
31
server = TACFastAPIServer(
32
tac=tac,
33
voice_channel=connector.voice,
34
messaging_channels=[connector.sms],
35
)
36
37
if __name__ == "__main__":
38
server.start()

The connector creates one agent per conversation and automatically:

  • Retrieves memory context from Conversation Memory and includes it in the first message (when memory_mode is set to "always" or "once")
  • Routes responses to the correct channel (Voice or SMS)
  • Cleans up agent resources when the conversation ends

To disable memory retrieval, omit voice_config and sms_config or set memory_mode to "never".


If you have a managed Bedrock Agent, use the BedrockConnector to connect it to Twilio channels.

pip install twilio-agent-connect-aws[bedrock,server]

Configure environment variables

configure-environment-variables page anchor

Add the following to your .env file alongside your existing TAC credentials.

1
BEDROCK_AGENT_ID=your_agent_id
2
BEDROCK_AGENT_ALIAS_ID=your_agent_alias_id
3
AWS_REGION=us-east-1
1
import boto3
2
from dotenv import load_dotenv
3
from tac import TAC
4
from tac.core.config import TACConfig
5
from tac.server import TACFastAPIServer
6
7
from tac_aws.connectors import BedrockConnector
8
9
load_dotenv()
10
11
tac = TAC(config=TACConfig.from_env())
12
client = boto3.client("bedrock-agent-runtime", region_name="us-east-1")
13
14
connector = BedrockConnector(
15
tac=tac,
16
bedrock_client=client,
17
config={
18
"agentId": "YOUR_AGENT_ID",
19
"agentAliasId": "YOUR_AGENT_ALIAS_ID",
20
},
21
)
22
23
server = TACFastAPIServer(
24
tac=tac,
25
voice_channel=connector.voice,
26
messaging_channels=[connector.sms],
27
)
28
29
if __name__ == "__main__":
30
server.start()

The connector automatically passes sessionId and inputText to each invoke_agent call. If Conversation Memory is configured, memory context is prepended to the user's message.

For advanced use cases like dynamic agent selection based on channel, you can provide a custom invoke function instead of a static config.

1
from tac.models.session import ConversationSession
2
3
def invoke_agent(
4
context: ConversationSession,
5
user_message: str,
6
memory_context: str | None,
7
):
8
agent_id = "VOICE_AGENT" if context.channel == "voice" else "SMS_AGENT"
9
10
full_message = user_message
11
if memory_context:
12
full_message = f"{memory_context}\n\nUser: {user_message}"
13
14
return client.invoke_agent(
15
agentId=agent_id,
16
agentAliasId="YOUR_AGENT_ALIAS_ID",
17
sessionId=context.conversation_id,
18
inputText=full_message,
19
)
20
21
connector = BedrockConnector(tac=tac, invoke_fn=invoke_agent)

Bedrock AgentCore connector

bedrock-agentcore-connector page anchor

Bedrock AgentCore(link takes you to an external page) supports a dual-runtime pattern: HTTP for SMS and a WebSocket option for low-latency voice streaming.

pip install twilio-agent-connect-aws[agentcore,server]

Configure environment variables

configure-environment-variables-1 page anchor

Add the following to your .env file alongside your existing TAC credentials.

1
BEDROCK_AGENTCORE_AGENT_ARN=arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/agent-xxx
2
AWS_REGION=us-east-1

The BedrockAgentCoreConnector requires an HTTP invoke function. You can optionally add a WebSocket configuration for voice optimization.

1
import json
2
import boto3
3
from dotenv import load_dotenv
4
from tac import TAC
5
from tac.core.config import TACConfig
6
from tac.channels.voice import VoiceChannelConfig
7
from tac.models.session import ConversationSession
8
from tac.server import TACFastAPIServer
9
from tac.session import ThreadSafeSessionManager
10
11
from tac_aws.connectors import BedrockAgentCoreConnector
12
from tac_aws.connectors.bedrock_agentcore.config import RuntimeConfig, WebSocketConfig
13
14
load_dotenv()
15
16
tac = TAC(config=TACConfig.from_env())
17
AGENT_ARN = "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/agent-xxx"
18
19
# HTTP invoke function (required for both Voice and SMS)
20
agentcore_http_client = boto3.client("bedrock-agentcore", region_name="us-east-1")
21
22
23
def invoke_agent_http(
24
context: ConversationSession,
25
user_message: str,
26
memory_context: str | None,
27
):
28
payload_data = {"prompt": user_message}
29
if memory_context:
30
payload_data["memory_context"] = memory_context
31
32
return agentcore_http_client.invoke_agent_runtime(
33
agentRuntimeArn=AGENT_ARN,
34
runtimeSessionId=context.conversation_id,
35
payload=json.dumps(payload_data).encode("utf-8"),
36
)
37
38
39
connector = BedrockAgentCoreConnector(
40
tac=tac,
41
runtime=RuntimeConfig(http=invoke_agent_http),
42
voice_config=VoiceChannelConfig(
43
session_manager=ThreadSafeSessionManager(),
44
memory_mode="always",
45
),
46
)
47
48
server = TACFastAPIServer(
49
tac=tac,
50
voice_channel=connector.voice,
51
messaging_channels=[connector.sms],
52
)
53
54
if __name__ == "__main__":
55
server.start()

Add WebSocket for voice optimization

add-websocket-for-voice-optimization page anchor

For lower latency on the Voice channel (approximately 50ms vs 200ms), add a WebSocket configuration. The connector uses WebSocket for voice and falls back to HTTP for SMS.

1
import websockets
2
from bedrock_agentcore.runtime import AgentCoreRuntimeClient
3
from websockets.client import WebSocketClientProtocol
4
5
agentcore_client = AgentCoreRuntimeClient(region="us-east-1")
6
7
8
async def create_websocket(context: ConversationSession) -> WebSocketClientProtocol:
9
ws_url, headers = agentcore_client.generate_ws_connection(
10
runtime_arn=AGENT_ARN,
11
session_id=context.conversation_id,
12
)
13
return await websockets.connect(ws_url, additional_headers=headers)
14
15
16
def build_websocket_payload(
17
context: ConversationSession,
18
user_message: str,
19
memory_context: str | None,
20
) -> dict:
21
payload = {"type": "prompt", "voicePrompt": user_message}
22
if memory_context:
23
payload["memoryContext"] = memory_context
24
return payload
25
26
27
connector = BedrockAgentCoreConnector(
28
tac=tac,
29
runtime=RuntimeConfig(
30
http=invoke_agent_http,
31
websocket=WebSocketConfig(
32
factory=create_websocket,
33
payload_fn=build_websocket_payload,
34
),
35
),
36
voice_config=VoiceChannelConfig(
37
session_manager=ThreadSafeSessionManager(),
38
memory_mode="always",
39
),
40
)

The connector pools WebSocket connections per conversation and automatically cleans them up when conversations end.


To start from a working example instead of writing the server code yourself, clone the twilio-agent-connect-aws repository and run one of the included examples.

  1. Clone the repository and install dependencies:

    1
    git clone https://github.com/twilio/twilio-agent-connect-aws.git
    2
    cd twilio-agent-connect-aws
    3
    make sync
    4
    make dev-setup
  2. Create a .env file in the examples directory:

    cp getting_started/examples/.env.example getting_started/examples/.env
  3. Fill in your TAC credentials and the AWS variables for the connector you want to run:

    StrandsBedrock AgentAgentCore

    Strands uses the standard AWS credential chain — no Bedrock agent IDs needed.

    AWS_REGION=us-east-1
  4. From the repository root, start the example server:

    StrandsBedrock AgentAgentCore
    uv run getting_started/examples/strands_agents.py
  5. Expose your local server with ngrok(link takes you to an external page) so Twilio can reach it, then configure your Twilio webhooks to point at the ngrok domain. For detailed steps, see Expose your local server with ngrok and Configure Twilio webhooks.


  1. Start your server and make sure ngrok is running.
  2. Send an SMS to your Twilio phone number and verify that you receive a response.
  3. Call your Twilio phone number and verify that the voice channel works.
  4. If you configured Conversation Memory, verify that responses include personalized context from the customer's profile.