AgentPhone Python SDK — give your AI agents phone numbers, SMS, and voice calls
Project description
AgentPhone Python SDK
Official Python SDK for AgentPhone — give your AI agents real phone numbers, SMS, and voice calls.
Installation
pip install agentphone
For async support:
pip install agentphone[async]
Quickstart
import os
from agentphone import AgentPhone
client = AgentPhone(api_key=os.environ["AGENTPHONE_API_KEY"])
# Create an agent with hosted voice
agent = client.agents.create(
name="My Agent",
voice_mode="hosted",
system_prompt="Schedule appointments for a dentist office.",
voice="alloy",
)
# Buy a number and attach it
number = client.numbers.buy(country="US", agent_id=agent.id)
# Make an AI conversation call — no webhook needed
call = client.calls.make(
agent_id=agent.id,
to_number="+14155551234",
system_prompt="Schedule a dentist appointment for next Tuesday at 2pm",
initial_greeting="Hi, I'm calling to schedule an appointment.",
)
print(call.status)
Async
import os
from agentphone import AsyncAgentPhone
async with AsyncAgentPhone(api_key=os.environ["AGENTPHONE_API_KEY"]) as client:
numbers = await client.numbers.list()
call = await client.calls.make(
agent_id="agent_123",
to_number="+14155551234",
system_prompt="Ask about their return policy",
)
Resources
| Resource | Methods |
|---|---|
client.numbers |
list(), buy(), release(), get_messages(), list_calls() |
client.contacts |
list(), create(), get(), update(), delete() |
client.agents |
list(), create(), get(), update(), delete(), attach_number(), detach_number(), list_calls(), list_conversations(), list_voices(), set_webhook(), get_webhook(), delete_webhook(), list_webhook_deliveries(), test_webhook() |
client.calls |
list(), get(), make(), create_web_call(), get_recording(), get_transcript(), stream_transcript() |
client.messages |
send(), react() |
client.conversations |
list(), get(), update(), get_messages() |
client.webhooks |
get(), set(), delete(), list_deliveries(), test(), get_delivery_stats(), get_all_time_stats() |
client.usage |
get(), get_daily(), get_monthly(), get_by_number() |
Contacts
# Create a contact
contact = client.contacts.create(
phone_number="+14155551234",
name="Jane Doe",
email="jane@example.com",
notes="VIP customer",
)
# List contacts with search
contacts = client.contacts.list(search="Jane")
# Get, update, delete
contact = client.contacts.get("contact_123")
client.contacts.update("contact_123", name="Jane Smith")
client.contacts.delete("contact_123")
Agents
# Create with full voice config
agent = client.agents.create(
name="Support Bot",
description="Handles customer support",
voice_mode="hosted",
model_tier="balanced", # "turbo", "balanced", or "max"
system_prompt="Handle customer support inquiries.",
begin_message="Hello, how can I help you today?",
voice="alloy",
stt_mode="fast", # "fast" or "accurate"
)
# Update
client.agents.update(agent.id, name="Updated Bot", voice="nova")
# Delete
client.agents.delete(agent.id)
# Attach / detach numbers
client.agents.attach_number(agent.id, number_id="num_123")
client.agents.detach_number(agent.id, number_id="num_123")
# List available voices
voices = client.agents.list_voices()
for v in voices:
print(v["name"])
# Agent-specific webhooks
client.agents.set_webhook(agent.id, url="https://my-server.com/hook")
client.agents.get_webhook(agent.id)
client.agents.delete_webhook(agent.id)
client.agents.list_webhook_deliveries(agent.id)
client.agents.test_webhook(agent.id)
# List agent's calls and conversations
calls = client.agents.list_calls(agent.id)
convos = client.agents.list_conversations(agent.id)
Calls
# Webhook-based call (your server handles the conversation)
call = client.calls.make(
agent_id=agent.id,
to_number="+14155551234",
from_number_id="num_123", # optional: pick which number to call from
voice="alloy", # optional: override voice
)
# AI conversation call (no webhook needed) — pass system_prompt
call = client.calls.make(
agent_id=agent.id,
to_number="+14155551234",
system_prompt="Ask about their return policy",
initial_greeting="Hi, I'm calling about a recent order.",
from_number_id="num_123",
voice="alloy",
)
# List calls with filters
calls = client.calls.list(status="completed", direction="outbound", limit=10)
# Get call details and transcript
call = client.calls.get("call_123")
for t in call.transcripts:
print(f"[{t.created_at}] {t.transcript}")
# Dedicated transcript endpoint
transcript = client.calls.get_transcript("call_123")
# Stream transcript in real time (SSE)
for event in client.calls.stream_transcript("call_123"):
if event["event"] == "turn":
print(f"[{event['data']['role']}] {event['data']['content']}")
elif event["event"] == "ended":
print(f"Call ended — {event['data']['durationSeconds']}s")
Sending Messages
# Send an outbound SMS
client.messages.send(
agent_id="agent_123",
to_number="+14155551234",
body="Your appointment is confirmed for Tuesday at 2pm.",
)
# Send with media
client.messages.send(
agent_id="agent_123",
to_number="+14155551234",
body="Here's your receipt",
media_url="https://example.com/receipt.pdf",
)
# React to a message (iMessage only)
client.messages.react("msg_123", reaction="love")
Conversations & SMS
# List conversations
convos = client.conversations.list()
# Get conversation with messages
convo = client.conversations.get("conv_123", message_limit=100)
for msg in convo.messages:
print(f"{msg.from_number}: {msg.body}")
# Paginated messages
messages = client.conversations.get_messages("conv_123", limit=50, before="msg_456")
# Update conversation metadata
client.conversations.update("conv_123", metadata={"tag": "vip"})
Usage
# Current usage summary
usage = client.usage.get()
print(f"Plan: {usage.plan.name}")
print(f"Numbers: {usage.numbers.used}/{usage.numbers.limit}")
print(f"Calls (30d): {usage.stats.calls_last_30d}")
# Daily and monthly breakdowns
daily = client.usage.get_daily(days=7)
monthly = client.usage.get_monthly(months=3)
Webhooks
# Project-level webhook
webhook = client.webhooks.set(url="https://my-server.com/hook", context_limit=10)
client.webhooks.get()
client.webhooks.delete()
# Delivery monitoring
deliveries = client.webhooks.list_deliveries(limit=50)
stats = client.webhooks.get_delivery_stats(hours=24)
print(f"Success rate: {stats.success_rate}%")
Webhook Verification
from agentphone import construct_event, WebhookVerificationError
@app.post("/webhook")
async def handle(request: Request):
body = await request.body()
sig = request.headers["X-Webhook-Signature"]
try:
event = construct_event(body, sig, secret=os.environ["WEBHOOK_SECRET"])
except WebhookVerificationError:
return Response(status_code=403)
if event.event == "agent.message":
print(f"SMS from {event.data.from_number}: {event.data.message}")
Error Handling
from agentphone import AgentPhoneError, AuthenticationError, NotFoundError, RateLimitError
try:
call = client.calls.get("bad-id")
except NotFoundError:
print("Call not found")
except RateLimitError:
print("Rate limited — back off and retry")
except AuthenticationError:
print("Invalid API key")
except AgentPhoneError as e:
print(f"API error {e.status}: {e.message}")
Requirements
- Python 3.9+
requests(sync client)httpx(async client, optional)
Links
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
agentphone-0.5.2.tar.gz
(14.7 kB
view details)
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agentphone-0.5.2.tar.gz.
File metadata
- Download URL: agentphone-0.5.2.tar.gz
- Upload date:
- Size: 14.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2470964d2916ee06923afb3178955b1e6540204ffd358ecd178b791d9f69814a
|
|
| MD5 |
3e0b7caa2eb8938a1677b74d8de0caf8
|
|
| BLAKE2b-256 |
d47ce12b1be946315351eade5db2a7a7e59c74479eb32d287dcf2e8c5ba8c709
|
File details
Details for the file agentphone-0.5.2-py3-none-any.whl.
File metadata
- Download URL: agentphone-0.5.2-py3-none-any.whl
- Upload date:
- Size: 17.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
beeb82ef0891394b3a1faee5523202c43c8bbdcf80022808f4b40050cad1ca64
|
|
| MD5 |
5a1dbc50a6543d8692626f58cd3453d2
|
|
| BLAKE2b-256 |
8e89cd72b479bdb7c64eb63d294e3ed94f40887253e716a47417021d474d3f71
|