Skip to main content

Open-source voice AI SDK — connect any AI agent to real phone calls in 4 lines of code

Project description

Patter Python SDK

Connect AI agents to phone numbers with 4 lines of code

PyPI MIT License Python 3.11+

QuickstartFeaturesConfigurationVoice ModesAPI ReferenceContributing


Patter is the open-source SDK that gives your AI agent a phone number. Point it at any function that returns a string, and Patter handles the rest: telephony, speech-to-text, text-to-speech, and real-time audio streaming. You build the agent — we connect it to the phone.

Quickstart

pip install getpatter
import asyncio
from patter import Patter

async def main():
    phone = Patter(
        twilio_sid="AC...", twilio_token="...",
        openai_key="sk-...",
        phone_number="+1...",
    )

    agent = phone.agent(
        system_prompt="You are a friendly customer service agent for Acme Corp.",
        voice="alloy",
        first_message="Hello! Thanks for calling. How can I help?",
    )

    await phone.serve(agent=agent, port=8000)

asyncio.run(main())

Features

Feature Method Example
Inbound calls phone.serve(agent) Answer calls as an AI
Outbound calls + AMD phone.call(to, machineDetection) Place calls with voicemail detection
Tool calling (webhooks) agent(tools=[...]) Agent calls external APIs mid-conversation
Custom STT + TTS agent(provider="pipeline") Bring your own voice providers
Dynamic variables agent(variables={...}) Personalize prompts per caller
Custom LLM (any model) serve(onMessage=handler) Claude, Mistral, LLaMA, etc.
Call recording serve(recording=True) Record all calls
Call transfer transfer_call (auto-injected) Transfer to a human
Voicemail drop call(voicemailMessage="...") Play message on voicemail

Configuration

Environment Variables

Variable Required Description
OPENAI_API_KEY Yes (Realtime mode) OpenAI API key with Realtime access
TWILIO_ACCOUNT_SID Yes Twilio account SID
TWILIO_AUTH_TOKEN Yes Twilio auth token
TWILIO_PHONE_NUMBER Yes Your Twilio phone number (E.164)
DEEPGRAM_API_KEY Pipeline mode Deepgram STT key
ELEVENLABS_API_KEY Pipeline mode ElevenLabs TTS key
ANTHROPIC_API_KEY Custom LLM For bringing your own model
WEBHOOK_URL No Public URL (auto-tunneled via Cloudflare if omitted)
cp .env.example .env
# Edit .env with your API keys

Telnyx: Telnyx is a fully supported telephony provider alternative to Twilio. Both carriers receive equal support for DTMF, transfer, recording, and metrics.

Voice Modes

Mode Latency Quality Best For
OpenAI Realtime Lowest High Fluid, low-latency conversations
Deepgram + ElevenLabs Low High Independent control over STT and TTS
ElevenLabs ConvAI Low High ElevenLabs-managed conversation flow

API Reference

Patter Constructor

Patter(
    twilio_sid: str,
    twilio_token: str,
    openai_key: str,
    phone_number: str,
    webhook_url: str = None,  # Optional; auto-tunneled via Cloudflare if omitted
)
Parameter Type Description
twilio_sid str Twilio account SID
twilio_token str Twilio auth token
openai_key str OpenAI API key
phone_number str Your Twilio phone number (E.164 format)
webhook_url str Public URL for Twilio webhooks (optional)

phone.agent() Method

agent = phone.agent(
    system_prompt: str,
    voice: str = "alloy",
    first_message: str = None,
    variables: dict = None,
    tools: list = None,
)
Parameter Type Description
system_prompt str Prompt with optional {variable} placeholders
voice str TTS voice name (e.g., "alloy", "echo", "fable")
first_message str Opening message (supports {variable} placeholders)
variables dict Values substituted into prompts
tools list Tool definitions: {name, description, parameters, webhook_url}

phone.serve() Method

await phone.serve(
    agent: Agent,
    port: int = 8000,
    dashboard: bool = False,
    recording: bool = False,
    onCallStart: callable = None,
    onCallEnd: callable = None,
    onTranscript: callable = None,
)
Parameter Type Description
agent Agent Agent configuration to use for calls
port int Port to listen on (default: 8000)
dashboard bool Enable the built-in monitoring dashboard
recording bool Enable call recording via the telephony provider
onCallStart callable Called when a call connects; receives data.caller, data.call_id
onCallEnd callable Called when a call ends; receives data.history, data.transcript, data.duration
onTranscript callable Called on each transcript turn; receives data.role, data.text, data.history

phone.call() Method

await phone.call(
    to: str,
    first_message: str = None,
    machine_detection: bool = False,
    voicemail_message: str = None,
)
Parameter Type Description
to str Destination phone number (E.164 format)
first_message str Opening message for the outbound call
machine_detection bool Enable answering machine detection
voicemail_message str Message to play when voicemail is detected

Static Provider Helpers

Patter.deepgram(api_key: str, language: str = "en") -> STT
Patter.elevenlabs(api_key: str, voice: str = "aria") -> TTS
Patter.openai_tts(api_key: str, voice: str = "alloy") -> TTS
Patter.whisper(api_key: str, language: str = "en") -> STT

Examples

Inbound Calls (AI answers the phone)

import asyncio
from patter import Patter, IncomingMessage

async def agent(msg: IncomingMessage) -> str:
    if "hours" in msg.text.lower():
        return "We're open Monday through Friday, 9 to 5."
    return "How can I help you today?"

async def main():
    phone = Patter(
        twilio_sid="AC...", twilio_token="...",
        openai_key="sk-...",
        phone_number="+1...",
    )

    await phone.serve(
        agent=phone.agent(
            system_prompt="You are a helpful customer service agent.",
            first_message="Hello! How can I help?",
        ),
        port=8000,
        onCallStart=lambda data: print(f"Call from {data['caller']}"),
        onCallEnd=lambda data: print("Call ended"),
    )

asyncio.run(main())

Outbound Calls (AI calls someone)

import asyncio
from patter import Patter, IncomingMessage

async def agent(msg: IncomingMessage) -> str:
    return "Thanks for picking up. This is a reminder about your appointment tomorrow."

async def main():
    phone = Patter(
        twilio_sid="AC...", twilio_token="...",
        openai_key="sk-...",
        phone_number="+1...",
    )

    agent_config = phone.agent(
        system_prompt="You are making reminder calls.",
        first_message="Hi, this is an automated reminder from Acme Corp.",
    )

    await phone.serve(agent=agent_config, port=8000)
    await phone.call(to="+14155551234", first_message="Hi, just checking in.")

asyncio.run(main())

Tool Calling (Agent calls external APIs)

agent = phone.agent(
    system_prompt="You are a booking assistant. Check availability before confirming.",
    tools=[{
        "name": "check_availability",
        "description": "Check appointment availability for a given date",
        "parameters": {
            "type": "object",
            "properties": {
                "date": {"type": "string", "description": "ISO date, e.g. 2025-06-15"},
            },
            "required": ["date"],
        },
        "webhook_url": "https://api.example.com/availability",
    }],
)

Custom Voice (Deepgram STT + ElevenLabs TTS)

phone = Patter(
    twilio_sid="AC...", twilio_token="...",
    openai_key="sk-...",
    phone_number="+1...",
)

agent = phone.agent(
    system_prompt="You are a helpful voice assistant.",
    voice="aria",
)

# Use custom STT and TTS in pipeline mode
await phone.serve(
    agent=agent,
    port=8000,
    stt=Patter.deepgram(api_key="dg_...", language="en"),
    tts=Patter.elevenlabs(api_key="el_...", voice="aria"),
)

Call Recording

await phone.serve(
    agent=agent,
    port=8000,
    recording=True,  # Records all inbound and outbound calls
)

Dynamic Variables in Prompts

agent = phone.agent(
    system_prompt="You are helping {customer_name}, account #{account_id}.",
    first_message="Hi {customer_name}! How can I help you today?",
    variables={
        "customer_name": "Jane",
        "account_id": "A-789",
    },
)

Contributing

Pull requests are welcome.

cd sdk-py && pip install -e ".[dev]" && pytest tests/ -v

Please open an issue before submitting large changes so we can discuss the approach first.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

getpatter-0.4.2.tar.gz (4.2 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

getpatter-0.4.2-py3-none-any.whl (4.2 MB view details)

Uploaded Python 3

File details

Details for the file getpatter-0.4.2.tar.gz.

File metadata

  • Download URL: getpatter-0.4.2.tar.gz
  • Upload date:
  • Size: 4.2 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for getpatter-0.4.2.tar.gz
Algorithm Hash digest
SHA256 fd5f050f9db64a0ed2fc85e7646d2b075ff11284385de8825687c77a28569ad7
MD5 9c6ea5862c3829a4dffc3a06096356d9
BLAKE2b-256 f8354ea7c869fb6fdc649ea7ed28ba9b343f695ef7596a18caa0035a38cf531c

See more details on using hashes here.

Provenance

The following attestation bundles were made for getpatter-0.4.2.tar.gz:

Publisher: release.yml on PatterAI/Patter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file getpatter-0.4.2-py3-none-any.whl.

File metadata

  • Download URL: getpatter-0.4.2-py3-none-any.whl
  • Upload date:
  • Size: 4.2 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for getpatter-0.4.2-py3-none-any.whl
Algorithm Hash digest
SHA256 ae2a299f04573b6f83dc78428ebf5db3a032aa2fa6be0281ca8bf71979549aef
MD5 6c4c456f660556419b7cc7d20cb8b425
BLAKE2b-256 7c65506aab7a3243067c65305b502cd0e585ab2e5e6a263b78458ac174631143

See more details on using hashes here.

Provenance

The following attestation bundles were made for getpatter-0.4.2-py3-none-any.whl:

Publisher: release.yml on PatterAI/Patter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page