Claude for Developers

Build Voice AI with Claude and ElevenLabs: Transcription to Response Loops

Build lifelike voice AI agents that transcribe speech, reason with Claude, and respond in natural voices using ElevenLabs. Follow this step-by-step tutorial for real-time conversational loops.

J

Jennifer Yu

Workflow Automation Specialist

December 14, 2025 min read
Share:

Introduction

Voice AI is transforming how we interact with technology, enabling natural spoken conversations with AI agents. This tutorial shows you how to create a complete voice AI system using Claude API for intelligent reasoning and ElevenLabs for high-quality speech-to-text (STT) transcription and text-to-speech (TTS) synthesis.

We'll build a real-time conversation loop:

  • Capture audio from your microphone.
  • Transcribe it using ElevenLabs STT.
  • Send the transcript to Claude (Sonnet 3.5) for a thoughtful response.
  • Convert the response to speech with ElevenLabs TTS and play it back.

This setup is perfect for AI agents, virtual assistants, or interactive demos. It's Claude-specific, leveraging its superior reasoning for context-aware replies while maintaining conversation history.

Note: ElevenLabs provides both STT and TTS via their APIs. This tutorial uses Python for a simple, local console app. For production, deploy to a server with WebSockets (e.g., via FastAPI).

Prerequisites

Before starting:

Step 1: Install Dependencies

Create a new directory and virtual environment:

git clone <your-repo> voice-claude-agent  # or mkdir voice-claude-agent
cd voice-claude-agent
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

Install required packages:

pip install anthropic elevenlabs pyaudio pydub simpleaudio soundfile numpy requests

Why these?

  • anthropic: Official Claude SDK.
  • elevenlabs: Official TTS/STT client.
  • pyaudio: Microphone input.
  • pydub & soundfile: Audio handling.
  • simpleaudio: Playback (cross-platform).

ElevenLabs STT Note: ElevenLabs offers real-time STT via WebSockets. For simplicity, we'll use their batch STT API with short recordings. Upgrade to WebSockets for production low-latency.

Step 2: Set Up API Keys

Create a .env file:

ANTHROPIC_API_KEY=your_anthropic_key_here
ELEVENLABS_API_KEY=your_elevenlabs_key_here

Load them in code using python-dotenv (install if needed: pip install python-dotenv):

import os
from dotenv import load_dotenv
load_dotenv()
claude_key = os.getenv('ANTHROPIC_API_KEY')
xi_key = os.getenv('ELEVENLABS_API_KEY')

Step 3: Audio Recording Function

Record 5-second audio clips from the mic. Press Enter to stop early if needed, but for demo, fixed duration.

import pyaudio
import wave
import numpy as np

def record_audio(duration=5, filename='input.wav', sample_rate=16000):
    chunk = 1024
    format = pyaudio.paInt16
    channels = 1

    p = pyaudio.PyAudio()
    stream = p.open(format=format, channels=channels, rate=sample_rate,
                    input=True, frames_per_buffer=chunk)

    print(f"Recording for {duration} seconds... Speak now!")
    frames = []

    for _ in range(0, int(sample_rate / chunk * duration)):
        data = stream.read(chunk)
        frames.append(data)

    stream.stop_stream()
    stream.close()
    p.terminate()

    wf = wave.open(filename, 'wb')
    wf.setnchannels(channels)
    wf.setsampwidth(p.get_sample_size(format))
    wf.setframerate(sample_rate)
    wf.writeframes(b''.join(frames))
    wf.close()
    print("Recording complete.")

    return filename

This saves mono 16kHz WAV, optimal for STT.

Step 4: Speech-to-Text with ElevenLabs

ElevenLabs STT API transcribes audio files. (For real-time, see their WebSocket docs.)

from elevenlabs.client import ElevenLabs
from elevenlabs.api import AudioTranscribeResponse

client = ElevenLabs(api_key=xi_key)

def transcribe_audio(audio_file):
    with open(audio_file, 'rb') as f:
        audio = f.read()
    response = client.transcribe(
        audio=audio,
        model_id="eleven_stt_v1",  # Latest model
        language_code="en"  # Adjust as needed
    )
    return response.text.strip()

Pro Tip: ElevenLabs STT excels at noisy environments and accents—better than basic Whisper for voice agents.

Step 5: Query Claude for Response

Use Anthropic SDK with conversation history for context.

from anthropic import Anthropic, HUMAN_PROMPT, AI_PROMPT

client = Anthropic(api_key=claude_key)

# Global history
conversation_history = []

def get_claude_response(user_input):
    global conversation_history
    conversation_history.append(f"{HUMAN_PROMPT} {user_input}{'\
\
' + AI_PROMPT}")

    full_context = ''.join(conversation_history[-10:])  # Last 10 exchanges
    full_context += f"{HUMAN_PROMPT} {user_input}\
\
{AI_PROMPT}"

    message = client.messages.create(
        model="claude-3-5-sonnet-20240620",
        max_tokens=500,
        temperature=0.7,
        system="You are a helpful voice assistant. Keep responses concise and conversational.",
        messages=[{"role": "user", "content": full_context}]
    )
    response = message.content[0].text

    conversation_history.append(response + '\
\
')
    return response

Claude's long context (200K tokens) handles extended convos effortlessly.

Step 6: Text-to-Speech with ElevenLabs

Generate and play natural speech. Choose voices like "Adam" or clone your own.

import simpleaudio as sa
import io

def speak_response(text, voice_id="pNInz6obpgDQGcFmaJgB"):  # Adam voice
    audio = client.generate(
        text=text,
        voice=voice_id,
        model="eleven_multilingual_v2",
        output_format="pcm_16000"  # Matches recording
    )

    # Play with simpleaudio
    audio_data = np.frombuffer(audio, dtype=np.int16)
    play_obj = sa.play_buffer(audio_data, 1, 2, 16000)
    play_obj.wait_done()

Customization: List voices via client.voices.list(). Use stream=True for streaming TTS in prod.

Step 7: The Main Conversation Loop

Tie it all together:

def main():
    global conversation_history
    print("Voice AI ready! Say 'exit' to quit.")

    while True:
        try:
            audio_file = record_audio()
            transcript = transcribe_audio(audio_file)
            print(f"You: {transcript}")

            if 'exit' in transcript.lower():
                print("Goodbye!")
                break

            response = get_claude_response(transcript)
            print(f"Claude: {response}")
            speak_response(response)

        except KeyboardInterrupt:
            print("\
Goodbye!")
            break
        except Exception as e:
            print(f"Error: {e}")

if __name__ == "__main__":
    main()

Run with python voice_agent.py. Speak, listen to Claude's voice reply!

Enhancements for Production

  • Real-time STT/TTS: Use ElevenLabs WebSockets for <500ms latency.
    # Example WebSocket snippet (adapt from docs)
    from elevenlabs import stream_stt_websocket
    
  • Streaming Claude: stream=True in messages.create for partial responses.
  • Tools & Agents: Add Claude's tool_use for actions (e.g., weather API).
    tools = [{"name": "get_weather", "input_schema": {...}}]
    
  • Deployment: FastAPI + WebSockets for phone integration (Twilio).
  • Context Management: Use MCP servers for persistent memory.
  • Multi-turn Optimization: Summarize history with Claude to fit token limits.

Word count tip: This basic loop is ~200 LOC, expandable to agents.

Troubleshooting

IssueSolution
PyAudio errorsInstall portaudio: brew install portaudio (Mac), or use pip install pipwin on Win.
Rate limitsUpgrade ElevenLabs/Anthropic plans.
LatencyShorten record duration; use streaming.
No audioCheck mic permissions.

Why Claude + ElevenLabs?

  • Claude: Best reasoning, handles nuance/ambiguity in speech.
  • ElevenLabs: Ultra-realistic voices, low-latency audio.
  • Beats GPT + basic TTS: Claude's safety + ElevenLabs expressiveness.

Comparisons:

  • Vs. GPT-4o: Claude cheaper, safer for enterprise.
  • Vs. Gemini: Better creative responses.

Build your voice agent today—fork on GitHub! Share your tweaks in comments.

~1450 words

The #1 Newsletter in AI

Stay ahead of the AI curve

The most important updates, news, and content — delivered in one weekly newsletter.

No spam. Unsubscribe anytime. Privacy policy

Claude API
ElevenLabs
Voice AI
Speech to Text
AI Agents
ai-agents
J

About Jennifer Yu

Workflow Automation Specialist

Jennifer covers workflow strategy, no-code platforms, and clear implementation guidance for teams adopting automation.

Comments (0)