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_KEYorOPENAI_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:
pip install "voicelayer-agents[openai]"Publishing soon
sdks/python/voicelayer-agents), as shown.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.pyThe 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
| Error | Status | How to fix |
|---|---|---|
unauthorized | 401 | Send Authorization: Bearer <key> with a secret key from the dashboard (Developers → API keys). Test keys start with vl_test_. |
insufficient_scope | 403 | Use a key with the scope named in details.required, or one whose restriction covers this channel or Binding. |
test_address_required | 422 | Use a reserved test address, or a live key to reach a real person. |
test_mode_only | 403 | Use a test key (vl_test_…) from the dashboard. |
test_limit_reached | 429 | Try again after midnight UTC, or ask for a higher test limit. |
Next steps
- The MCP tools: what each tool does and which scope it needs.
- Python SDK: call the API directly.
- Test mode: more ways to simulate people.