Skip to content
Back to skills

760 Quickstart B2f4c424

ASecurity

{{ experimental_feature_warning() }} This quickstart guide shows you how to create your first bidirectional streaming agent for real-time audio and text conversations. You'll learn how to set up audio I/O, handle streaming events, use tools during conversations, and work with different model providers. After completing this guide, you can build voice assistants, interactive chatbots, multi-modal applications, and integrate bidirectional streaming with web servers or custom I/O channels.

  • 9 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added June 1, 2026
ai-agentspythongobashawsdebuggingapisecuritydocumentation

Works with

  • cli
  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 2 files and shows the line behind each finding

Scanned June 1, 2026

npx -y skills add tools-only/X-Skills --skill 760-quickstart_b2f4c424 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 760 Quickstart B2f4c424?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 760 Quickstart B2f4c424
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-760-quickstart-b2f4c424/badge)](https://www.skillsdirectory.com/skills/tools-only-760-quickstart-b2f4c424)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# Quickstart [Experimental]

{{ experimental_feature_warning() }}

This quickstart guide shows you how to create your first bidirectional streaming agent for real-time audio and text conversations. You'll learn how to set up audio I/O, handle streaming events, use tools during conversations, and work with different model providers.

After completing this guide, you can build voice assistants, interactive chatbots, multi-modal applications, and integrate bidirectional streaming with web servers or custom I/O channels.

## Prerequisites

Before starting, ensure you have:

- Python 3.10+ installed (3.12+ required for Nova Sonic)
- Audio hardware (microphone and speakers) for voice conversations
- Model provider credentials configured (AWS, OpenAI, or Google)

## Install the SDK

Bidirectional streaming is included in the Strands Agents SDK as an experimental feature. Install the SDK with bidirectional streaming support:

### For All Providers

To install with support for all bidirectional streaming providers and local audio I/O:

```bash
pip install "strands-agents[bidi-all]"
```

This includes all 3 supported providers (Nova Sonic, OpenAI, and Gemini Live) plus `BidiAudioIO` and `BidiTextIO` for local development.

### For Specific Providers

You can also install support for specific providers:

=== "Amazon Bedrock Nova Sonic"

    ```bash
    # With local audio I/O (BidiAudioIO, BidiTextIO)
    pip install "strands-agents[bidi,bidi-io]"
    
    # Server-side only (no PyAudio dependency)
    pip install "strands-agents[bidi]"
    ```

=== "OpenAI Realtime API"

    ```bash
    # With local audio I/O
    pip install "strands-agents[bidi,bidi-io,bidi-openai]"
    
    # Server-side only
    pip install "strands-agents[bidi,bidi-openai]"
    ```

=== "Google Gemini Live"

    ```bash
    # With local audio I/O
    pip install "strands-agents[bidi,bidi-io,bidi-gemini]"
    
    # Server-side only
    pip install "strands-agents[bidi,bidi-gemini]"
    ```

!!! note "Server-Side Deployments"
    The `bidi-io` extra includes PyAudio for direct microphone/speaker access. For server deployments where audio I/O is handled by clients (browsers, mobile apps), omit `bidi-io` and implement custom I/O handlers using the `BidiInput` and `BidiOutput` protocols. See [I/O Channels](io.md) for details.

### Platform-Specific Audio Setup

=== "macOS"

    ```bash
    brew install portaudio
    pip install "strands-agents[bidi-all]"
    ```

=== "Linux (Ubuntu/Debian)"

    ```bash
    sudo apt-get install portaudio19-dev python3-pyaudio
    pip install "strands-agents[bidi-all]"
    ```

=== "Windows"

    PyAudio typically installs without additional dependencies.

    ```bash
    pip install "strands-agents[bidi-all]"
    ```

## Configuring Credentials

Bidirectional streaming supports multiple model providers. Choose one based on your needs:

=== "Amazon Bedrock Nova Sonic"

    Nova Sonic is Amazon's bidirectional streaming model. Configure AWS credentials:

    ```bash
    export AWS_ACCESS_KEY_ID=your_access_key
    export AWS_SECRET_ACCESS_KEY=your_secret_key
    export AWS_DEFAULT_REGION=us-east-1
    ```

    Enable Nova Sonic model access in the [Amazon Bedrock console](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access-modify.html).

=== "OpenAI Realtime API"

    For OpenAI's Realtime API, set your API key:

    ```bash
    export OPENAI_API_KEY=your_api_key
    ```

=== "Google Gemini Live"

    For Gemini Live API, set your API key:

    ```bash
    export GOOGLE_API_KEY=your_api_key
    ```

## Your First Voice Conversation

Now let's create a simple voice-enabled agent that can have real-time conversations:

```python
import asyncio
from strands.experimental.bidi import BidiAgent, BidiAudioIO
from strands.experimental.bidi.models import BidiNovaSonicModel

# Create a bidirectional streaming model
model = BidiNovaSonicModel()

# Create the agent
agent = BidiAgent(
    model=model,
    system_prompt="You are a helpful voice assistant. Keep responses concise and natural."
)

# Setup audio I/O for microphone and speakers
audio_io = BidiAudioIO()

# Run the conversation
async def main():
    await agent.run(
        inputs=[audio_io.input()],
        outputs=[audio_io.output()]
    )

asyncio.run(main())
```

And that's it! We now have a voice-enabled agent that can:

- Listen to your voice through the microphone
- Process speech in real-time
- Respond with natural voice output
- Handle interruptions when you start speaking

!!! note "Stopping the Conversation"
    The `run()` method runs indefinitely. See [Controlling Conversation Lifecycle](#controlling-conversation-lifecycle) for proper ways to stop conversations.

## Adding Text I/O

Combine audio with text input/output for debugging or multi-modal interactions:

```python
import asyncio
from strands.experimental.bidi import BidiAgent, BidiAudioIO
from strands.experimental.bidi.io import BidiTextIO
from strands.experimental.bidi.models import BidiNovaSonicModel

model = BidiNovaSonicModel()
agent = BidiAgent(
    model=model,
    system_prompt="You are a helpful assistant."
)

# Setup both audio and text I/O
audio_io = BidiAudioIO()
text_io = BidiTextIO()

async def main():
    await agent.run(
        inputs=[audio_io.input()],
        outputs=[audio_io.output(), text_io.output()]  # Both audio and text
    )

asyncio.run(main())
```

Now you'll see transcripts printed to the console while audio plays through your speakers.

## Controlling Conversation Lifecycle

The `run()` method runs indefinitely by default. The simplest way to stop conversations is using `Ctrl+C`:

```python
import asyncio
from strands.experimental.bidi import BidiAgent, BidiAudioIO
from strands.experimental.bidi.models import BidiNovaSonicModel

async def main():
    model = BidiNovaSonicModel()
    agent = BidiAgent(model=model)
    audio_io = BidiAudioIO()
    
    try:
        # Runs indefinitely until interrupted
        await agent.run(
            inputs=[audio_io.input()],
            outputs=[audio_io.output()]
        )
    except asyncio.CancelledError:
        print("\nConversation cancelled by user")
    finally:
        # stop() should only be called after run() exits
        await agent.stop()

asyncio.run(main())
```

!!! warning "Important: Call stop() After Exiting Loops"
    Always call `agent.stop()` **after** exiting the `run()` or `receive()` loop, never during. Calling `stop()` while still receiving events can cause errors.

## Adding Tools to Your Agent

Just like standard Strands agents, bidirectional agents can use tools during conversations:

```python
import asyncio
from strands import tool
from strands.experimental.bidi import BidiAgent, BidiAudioIO
from strands.experimental.bidi.models import BidiNovaSonicModel
from strands_tools import calculator, current_time

# Define a custom tool
@tool
def get_weather(location: str) -> str:
    """
    Get the current weather for a location.
    
    Args:
        location: City name or location
    
    Returns:
        Weather information
    """
    # In a real application, call a weather API
    return f"The weather in {location} is sunny and 72°F"

# Create agent with tools
model = BidiNovaSonicModel()
agent = BidiAgent(
    model=model,
    tools=[calculator, current_time, get_weather],
    system_prompt="You are a helpful assistant with access to tools."
)

audio_io = BidiAudioIO()

async def main():
    await agent.run(
        inputs=[audio_io.input()],
        outputs=[audio_io.output()]
    )

asyncio.run(main())
```

You can now ask questions like:

- "What time is it?"
- "Calculate 25 times 48"
- "What's the weather in San Francisco?"

The agent automatically determines when to use tools and executes them concurrently without blocking the conversation.

## Model Providers

Strands supports three bidirectional streaming providers:

- **[Nova Sonic](models/nova_sonic.md)** - Amazon's bidirectional streaming model via AWS Bedrock
- **[OpenAI Realtime](models/openai_realtime.md)** - OpenAI's Realtime API for voice conversations  
- **[Gemini Live](models/gemini_live.md)** - Google's multimodal streaming API

Each provider has different features, timeout limits, and audio quality. See the individual provider documentation for detailed configuration options.

## Configuring Audio Settings

Customize audio configuration for both the model and I/O:

```python
import asyncio

from strands.experimental.bidi import BidiAgent, BidiAudioIO
from strands.experimental.bidi.models.gemini_live import BidiGeminiLiveModel

# Configure model audio settings
model = BidiGeminiLiveModel(
    provider_config={
        "audio": {
            "input_rate": 48000,   # Higher quality input
            "output_rate": 24000,  # Standard output
            "voice": "Puck"
        }
    }
)

# Configure I/O buffer settings
audio_io = BidiAudioIO(
    input_buffer_size=10,           # Max input queue size
    output_buffer_size=20,          # Max output queue size
    input_frames_per_buffer=512,   # Input chunk size
    output_frames_per_buffer=512   # Output chunk size
)

agent = BidiAgent(model=model)

async def main():
    await agent.run(
        inputs=[audio_io.input()],
        outputs=[audio_io.output()]
    )

asyncio.run(main())
```

The I/O automatically configures hardware to match the model's audio requirements.

## Handling Interruptions

Bidirectional agents automatically handle interruptions when users start speaking:

```python
import asyncio
from strands.experimental.bidi import BidiAgent, BidiAudioIO
from strands.experimental.bidi.models import BidiNovaSonicModel
from strands.experimental.bidi.types.events import BidiInterruptionEvent

model = BidiNovaSonicModel()
agent = BidiAgent(model=model)
audio_io = BidiAudioIO()

async def main():
    await agent.start()
    
    # Start receiving events
    async for event in agent.receive():
        if isinstance(event, BidiInterruptionEvent):
            print(f"User interrupted: {event.reason}")
            # Audio output automatically cleared
            # Model stops generating
            # Ready for new input

asyncio.run(main())
```

Interruptions are detected via voice activity detection (VAD) and handled automatically:

1. User starts speaking
2. Model stops generating
3. Audio output buffer cleared
4. Model ready for new input

## Manual Start and Stop

If you need more control over the agent lifecycle, you can manually call `start()` and `stop()`:

```python
import asyncio
from strands.experimental.bidi import BidiAgent
from strands.experimental.bidi.models import BidiNovaSonicModel
from strands.experimental.bidi.types.events import BidiResponseCompleteEvent

async def main():
    model = BidiNovaSonicModel()
    agent = BidiAgent(model=model)
    
    # Manually start the agent
    await agent.start()
    
    try:
        await agent.send("What is Python?")
        
        async for event in agent.receive():
            if isinstance(event, BidiResponseCompleteEvent):
                break
    finally:
        # Always stop after exiting receive loop
        await agent.stop()

asyncio.run(main())
```

See [Controlling Conversation Lifecycle](#controlling-conversation-lifecycle) for more patterns and best practices.

## Graceful Shutdown

Use the experimental `stop_conversation` tool to allow users to end conversations naturally:

```python
import asyncio
from strands.experimental.bidi import BidiAgent, BidiAudioIO
from strands.experimental.bidi.models import BidiNovaSonicModel
from strands.experimental.bidi.tools import stop_conversation

model = BidiNovaSonicModel()
agent = BidiAgent(
    model=model,
    tools=[stop_conversation],
    system_prompt="You are a helpful assistant. When the user says 'stop conversation', use the stop_conversation tool."
)

audio_io = BidiAudioIO()

async def main():
    await agent.run(
        inputs=[audio_io.input()],
        outputs=[audio_io.output()]
    )
    # Conversation ends when user says "stop conversation"

asyncio.run(main())
```

The agent will gracefully close the connection when the user explicitly requests it.

## Debug Logs

To enable debug logs in your agent, configure the `strands` logger:

```python
import asyncio
import logging
from strands.experimental.bidi import BidiAgent, BidiAudioIO
from strands.experimental.bidi.models import BidiNovaSonicModel

# Enable debug logs
logging.getLogger("strands").setLevel(logging.DEBUG)
logging.basicConfig(
    format="%(levelname)s | %(name)s | %(message)s",
    handlers=[logging.StreamHandler()]
)

model = BidiNovaSonicModel()
agent = BidiAgent(model=model)
audio_io = BidiAudioIO()

async def main():
    await agent.run(
        inputs=[audio_io.input()],
        outputs=[audio_io.output()]
    )

asyncio.run(main())
```

Debug logs show:

- Connection lifecycle events
- Audio buffer operations
- Tool execution details
- Event processing flow

## Common Issues

### Audio Feedback Loop in a Python Console

BidiAudioIO uses PyAudio, which does not support echo cancellation. A headset is required to prevent audio feedback loops.

### No Audio Output

If you don't hear audio:

```python
# List available audio devices
import pyaudio
p = pyaudio.PyAudio()
for i in range(p.get_device_count()):
    info = p.get_device_info_by_index(i)
    print(f"{i}: {info['name']}")

# Specify output device explicitly
audio_io = BidiAudioIO(output_device_index=2)
```

### Microphone Not Working

If the agent doesn't respond to speech:

```python
# Specify input device explicitly
audio_io = BidiAudioIO(input_device_index=1)

# Check system permissions (macOS)
# System Preferences → Security & Privacy → Microphone
```

### Connection Timeouts

If you experience frequent disconnections:

```python
# Use OpenAI for longer timeout (60 min vs Nova's 8 min)
from strands.experimental.bidi.models import BidiOpenAIRealtimeModel
model = BidiOpenAIRealtimeModel()

# Or handle restarts gracefully
async for event in agent.receive():
    if isinstance(event, BidiConnectionRestartEvent):
        print("Reconnecting...")
        continue
```

## Next Steps

Ready to learn more? Check out these resources:

- [Agent](agent.md) - Deep dive into BidiAgent configuration and lifecycle
- [Events](events.md) - Complete guide to bidirectional streaming events
- [I/O Channels](io.md) - Understanding and customizing input/output channels
- **Model Providers:**
    - [Nova Sonic](models/nova_sonic.md) - Amazon Bedrock's bidirectional streaming model
    - [OpenAI Realtime](models/openai_realtime.md) - OpenAI's Realtime API
    - [Gemini Live](models/gemini_live.md) - Google's Gemini Live API
- [API Reference](../../../api-reference/python/experimental/bidi/agent/agent.md) - Complete API documentation

Files in this skill

  • README.md857 B
  • skill.md14.4 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.