Tutorial

Python frameworks

Give a Python agent built with the Claude Agent SDK, OpenAI Agents or LangGraph your messaging channels in about ten minutes.

What you'll build

A Python agent that texts a reserved test number with VoiceLayer's message_send tool. You use voicelayer-agents, which gives each framework the VoiceLayer channel tools over MCP. It adds no tools of its own, so they are the same in every framework and language. Each framework is an extra: [claude], [openai] or [langgraph].

Prerequisites

  • Python 3.10 or later.
  • A test key in VOICELAYER_API_KEY (vl_test_…): see Authentication and API keys. With a test key every send goes to a simulated carrier and costs nothing.
  • The model provider key your framework needs (ANTHROPIC_API_KEY or OPENAI_API_KEY).
  • No phone number needed: with a test key, your workspace's free test sender stands in for one.

Install

Pick the extra for your framework. For the OpenAI Agents SDK:

Once published
pip install "voicelayer-agents[openai]"

Publishing soon

Publishing soon: voicelayer-agents is not on PyPI yet. Until it is, install it from a checkout of the VoiceLayer repository (sdks/python/voicelayer-agents), as shown.
Until then: from a checkout of the repository
pip install "./voicelayer/sdks/python/voicelayer-agents[openai]"

Use the extra claude for the Claude Agent SDK, or langgraph for LangGraph. The LangGraph example names its model as a string ("openai:gpt-4.1-mini"), which needs langchain[openai] too.

Give your agent VoiceLayer's tools

VoiceLayer's helpers read VOICELAYER_API_KEY themselves, so no example passes a key. Save one of these as agent.py.

voicelayer_mcp_server() returns the Agents SDK's MCP server, pointed at VoiceLayer. async with connects it and closes it afterwards.

import asyncio

from agents import Agent, Runner
from voicelayer_agents.openai import voicelayer_mcp_server


async def main():
    async with voicelayer_mcp_server() as voicelayer:
        agent = Agent(name="support", instructions="You answer customers in one short sentence.", mcp_servers=[voicelayer])
        result = await Runner.run(agent, 'Text "Hello from VoiceLayer" to +15550101 over sms.')
        print(result.final_output)


asyncio.run(main())
export VOICELAYER_API_KEY=vl_test_...
export OPENAI_API_KEY=...
python agent.py

The agent calls message_send and prints its final answer, for example that the message was sent.

Answer incoming messages

Direct mode works with any framework: your function gets the message and the conversation so far, and returns the reply. Save this as serve.py.

from voicelayer_agents import serve_direct

serve_direct(lambda turn: f"You said: {turn.message.text}").wait()

The lambda stands in for your agent. With the OpenAI Agents SDK, serve_direct(lambda turn: Runner.run_sync(agent, turn.message.text).final_output).wait() answers with agent from the first example. wait() keeps the process running until you press Ctrl+C.

Test it without a person

With serve.py running, simulate a person writing in from a second terminal. simulate_inbound works with test keys only:

from voicelayer_agents import simulate_inbound

print(simulate_inbound("What are your opening hours?")["conversationId"])

The first terminal prints voicelayer: replied in conversation …. Open Conversations in the dashboard and turn on test conversations to see both messages.

Common errors

ErrorStatusHow to fix
unauthorized401Send Authorization: Bearer <key> with a secret key from the dashboard (Developers → API keys). Test keys start with vl_test_.
insufficient_scope403Use a key with the scope named in details.required, or one whose restriction covers this channel or Binding.
test_address_required422Use a reserved test address, or a live key to reach a real person.
test_mode_only403Use a test key (vl_test_…) from the dashboard.
test_limit_reached429Try again after midnight UTC, or ask for a higher test limit.

Next steps

On this page