Skip to content

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.

Microphone and speaker access goes through PyAudio, which needs the PortAudio system library:

Terminal window
brew install portaudio

Then install the SDK with Nova Sonic, local audio, and echo cancellation support:

Terminal window
pip install "strands-agents[bidi,bidi-io,bidi-pyaudio,bidi-aec]"

Set up AWS credentials with permission to invoke Nova Sonic, then set the region:

Terminal window
export AWS_DEFAULT_REGION=us-east-1

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 asyncio
from datetime import datetime
from strands import ToolContext, tool
from strands.bidi import BidiAgent
from strands.bidi.io import AudioIO
from strands.bidi.models import BedrockNovaSonicModel
@tool
def 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:

Terminal window
python voice_agent.py

The 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.

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.

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.

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.

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.

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=:

Terminal window
pip install "strands-agents[bidi-io,bidi-pyaudio,bidi-aec,bidi-google]"
export GOOGLE_API_KEY=your_api_key
from strands.bidi.models import GoogleGeminiLiveModel
model = GoogleGeminiLiveModel(model_id="gemini-3.8-live")
  • BidiAgent: configure the agent and control its lifecycle.
  • I/O Streams: tune AudioIO, type to the agent with ConsoleIO, or connect a browser.
  • Stream Events: handle transcripts, tool results, and barge-ins yourself.