Agents
Agents are the core abstraction in ph0ny. An agent combines a system prompt, an LLM, a TTS voice, and optional knowledge and tools into a conversational AI persona.
Creating an Agent
curl -X POST https://persona-labsvoice-api-production.up.railway.app/v1/agents \
-H "Authorization: Bearer $PH0NY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Sales Agent",
"systemPrompt": "You are a friendly sales assistant for Acme Corp...",
"firstMessage": "Hey! Welcome to Acme. What can I help you find?",
"voiceId": "default",
"ttsProvider": "cartesia",
"llmProvider": "openai",
"llmModel": "gpt-4.1",
"language": "en",
"temperature": 0.7,
"maxTokens": 4096
}'Fields
| Field | Type | Default | Description |
|---|---|---|---|
name | string | required | Display name (1-100 chars) |
systemPrompt | string | - | Instructions for the LLM (up to 10,000 chars) |
firstMessage | string | - | Greeting spoken when a session starts |
voiceId | string | "default" | TTS voice identifier |
ttsProvider | string | "default" | TTS provider (cartesia, elevenlabs, deepgram, etc.) |
ttsModel | string | - | Provider-specific model override |
llmProvider | string | "openai" | LLM provider (openai, anthropic, groq) |
llmModel | string | - | Model name (e.g., gpt-4.1, claude-sonnet-4) |
collectionId | string | - | RAG collection for knowledge retrieval |
language | string | "en" | Agent language code |
temperature | number | 0.7 | LLM temperature (0-2) |
maxTokens | number | - | Max LLM output tokens (1-16384) |
metadata | object | - | Arbitrary key-value metadata |
Provisioning
The provision endpoint creates an agent, a knowledge collection, and ingests initial content in a single atomic request:
curl -X POST https://persona-labsvoice-api-production.up.railway.app/v1/agents/provision \
-H "Authorization: Bearer $PH0NY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "FAQ Bot",
"systemPrompt": "Answer user questions from the knowledge base.",
"collection": {
"name": "FAQ Collection"
},
"initialContent": [
{
"content": "Our store hours are 9am to 5pm Monday through Friday.",
"contentType": "text"
},
{
"content": "Returns are accepted within 30 days with receipt.",
"contentType": "text"
}
]
}'Chat
Send a text message to an agent and get a response:
curl -X POST https://persona-labsvoice-api-production.up.railway.app/v1/agents/:id/chat \
-H "Authorization: Bearer $PH0NY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"message": "What are your hours?",
"conversationId": "conv_abc123"
}'Pass conversationId to continue a multi-turn conversation. Omit it to start a new one.
Chat with Instance Context
Agents support instances — per-caller or per-use-case configurations that override the base agent:
{
"message": "Hello",
"instanceId": "inst_abc123"
}Or auto-match by caller phone:
{
"message": "Hello",
"callerPhone": "+19005551234"
}Tools
Agents can be equipped with tools that execute during conversations:
- webhook — call external APIs during a turn
- mcp — Model Context Protocol tool servers
- knowledge_search — RAG retrieval
- send_message — send SMS during a call
- collect_info — structured data collection
- human_handoff — transfer to a human
- calendar — check/book appointments
- contacts — look up contact information
- end_call — terminate the call
- transfer — transfer to another number
- dtmf — send DTMF tones
- memory — persistent memory across conversations
- wait — pause before responding
- guardrails — content filtering
- action_items — extract action items
- route — route to different agents
- translate — real-time translation
Managing Tools
# Add a tool to an agent
curl -X POST https://persona-labsvoice-api-production.up.railway.app/v1/agents/:id/tools \
-H "Authorization: Bearer $PH0NY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "webhook",
"name": "check_inventory",
"description": "Check product inventory levels",
"config": {
"url": "https://api.acme.com/inventory",
"method": "POST"
}
}'
# List tools
curl https://persona-labsvoice-api-production.up.railway.app/v1/agents/:id/tools \
-H "Authorization: Bearer $PH0NY_API_KEY"
# Delete a tool
curl -X DELETE https://persona-labsvoice-api-production.up.railway.app/v1/agents/:id/tools/:toolId \
-H "Authorization: Bearer $PH0NY_API_KEY"Instances
Instances let you customize an agent per caller or deployment context without duplicating the entire agent:
curl -X POST https://persona-labsvoice-api-production.up.railway.app/v1/agents/:id/instances \
-H "Authorization: Bearer $PH0NY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "VIP Caller",
"phoneNumber": "+19005551234",
"systemPromptOverride": "This is a VIP customer. Be extra attentive.",
"priority": 1
}'Audience Groups
Group instances for shared configuration:
curl -X POST https://persona-labsvoice-api-production.up.railway.app/v1/audience-groups \
-H "Authorization: Bearer $PH0NY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Enterprise Tier",
"description": "Enterprise customer group"
}'Testing Agents
Self-Play
Run automated multi-turn conversations where agents talk to each other:
curl -X POST https://persona-labsvoice-api-production.up.railway.app/v1/agents/:id/tests/run-selfplay \
-H "Authorization: Bearer $PH0NY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"turns": 10,
"participants": [
{ "agentId": "agent_abc", "speaker": "Agent", "task": "Answer questions about products" },
{ "agentId": "agent_xyz", "speaker": "Caller", "task": "Ask about return policies" }
],
"overlapMode": "duplex"
}'Streaming Self-Play (SSE)
For real-time monitoring, use the streaming endpoint:
curl -N https://persona-labsvoice-api-production.up.railway.app/v1/agents/:id/tests/run-selfplay/stream \
-H "Authorization: Bearer $PH0NY_API_KEY" \
-H "Content-Type: application/json" \
-d '{...}'Events: run_started, turn, audio, stt_partial, interrupt_decision, turn_interrupted, run_completed, run_failed.