Build a Voice Agent
In this guide you build a voice agent that listens through your microphone, speaks through your speakers, and calls tools while you talk. You’ll ask it for the time, talk over one of its replies, and end the conversation by saying goodbye.
The example uses Amazon Nova Sonic, which requires Python 3.12 or later. You’ll also need a microphone and speakers or headphones.
Install the SDK
Section titled “Install the SDK”Microphone and speaker access goes through PyAudio, which needs the PortAudio system library:
brew install portaudiosudo apt-get install portaudio19-devPyAudio’s Windows wheels include PortAudio, so there’s nothing to install here.
Then install the SDK with Nova Sonic, local audio, and echo cancellation support:
pip install "strands-agents[bidi,bidi-io,bidi-pyaudio,bidi-aec]"Configure credentials
Section titled “Configure credentials”Set up AWS credentials with permission to invoke Nova Sonic, then set the region:
export AWS_DEFAULT_REGION=us-east-1Run the agent
Section titled “Run the agent”Save this as voice_agent.py. It gives the agent two tools: get_current_time reads
your computer’s clock, and end_conversation lets the agent hang up when you’re done.
import asynciofrom datetime import datetime
from strands import ToolContext, toolfrom strands.bidi import BidiAgentfrom strands.bidi.io import AudioIOfrom strands.bidi.models import BedrockNovaSonicModel
@tooldef get_current_time() -> str: """Get the current date and time in the computer's local time zone.""" return datetime.now().astimezone().isoformat(timespec="seconds")
@tool(context=True)def end_conversation(tool_context: ToolContext[BidiAgent]) -> str: """End the conversation when the user says goodbye or asks to stop.""" tool_context.agent.cancel() return "Ending the conversation."
async def main() -> None: agent = BidiAgent( model=BedrockNovaSonicModel(model_id="amazon.nova-2-5-sonic"), tools=[get_current_time, end_conversation], system_prompt="You are a friendly voice assistant. Keep replies short.", ) # One AudioIO drives both the microphone and the speakers audio_io = AudioIO() await agent.run(inputs=[audio_io.input()], outputs=[audio_io.output()])
asyncio.run(main())Start it:
python voice_agent.pyThe terminal shows a Speak… prompt. AudioIO streams your microphone to the agent,
plays the agent’s replies, and prints transcripts and tool calls as they happen.
Try a conversation
Section titled “Try a conversation”Ask for the time
Section titled “Ask for the time”Say “What time is it?” The agent can call get_current_time and read the result
back to you. You’ll see the tool call appear in the terminal.
Talk over the agent
Section titled “Talk over the agent”Say “Tell me three things to do in Lisbon.” While the agent is answering, say “Actually, make that Paris.”
The agent should stop mid-sentence and switch to Paris. This is called barge-in: the
model hears you speaking over its reply and stops, and AudioIO throws away any
audio still queued for the speakers so playback stops right away. See
Barge-in to react when it happens.
End the conversation by voice
Section titled “End the conversation by voice”Say “Goodbye.” The agent calls end_conversation, closes the connection, and
run() returns. You can also press Ctrl+C at any time. Python prints a
KeyboardInterrupt traceback when you do; that’s expected.
Cancel echo on open speakers
Section titled “Cancel echo on open speakers”Without headphones, the agent may cut itself off a few words into every reply. The microphone picks up the agent’s voice from the speakers, and the model hears that as you talking over it.
Turn on audio processing to fix it:
audio_io = AudioIO(audio_processor=True)AudioIO now subtracts the audio it plays from the microphone signal before the
model hears it. For other audio settings, see Audio processing.
Use a different provider
Section titled “Use a different provider”Install the provider’s extra and set its API key. Then, in
voice_agent.py, replace the BedrockNovaSonicModel import with the provider’s
import and pass the new model to BidiAgent as model=:
pip install "strands-agents[bidi-io,bidi-pyaudio,bidi-aec,bidi-google]"export GOOGLE_API_KEY=your_api_keyfrom strands.bidi.models import GoogleGeminiLiveModel
model = GoogleGeminiLiveModel(model_id="gemini-3.8-live")pip install "strands-agents[bidi-io,bidi-pyaudio,bidi-aec,bidi-openai]"export OPENAI_API_KEY=your_api_keyfrom strands.bidi.models import OpenAIRealtimeModel
# OpenAI transcribes your speech with a separate model; pass None to skip itmodel = OpenAIRealtimeModel( model_id="gpt-realtime-2.1", transcription_model_id="gpt-transcribe",)Next steps
Section titled “Next steps”- BidiAgent: configure the agent and control its lifecycle.
- I/O Streams: tune
AudioIO, type to the agent withConsoleIO, or connect a browser. - Stream Events: handle transcripts, tool results, and barge-ins yourself.