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://api.ph0ny.com/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://api.ph0ny.com/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://api.ph0ny.com/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
Phone call defaults
Every phone call prompt carries the call's date and time. The default line gives US Eastern, Pacific and UTC; set metadata.timeZone to an IANA zone name to use that zone instead.
Phone calls get a built-in look_up tool for current facts: news, prices, scores, weather and schedules. It asks the router's search model for one or two spoken sentences, without links or citations. It uses the same router key as the voice model, so it needs no credential of its own. The prompt tells the agent to answer general questions itself and to call look_up for anything current.
| Metadata key | Default | Effect |
|---|---|---|
lookUp | true | false removes the look_up tool from the agent's calls |
lookUpModel | gpt-5-search-api | Router model that answers look_up |
timeZone | none | IANA zone for the date line, e.g. Europe/Berlin |
directToolSpeech | false | Speak completed look_up and ask_workspace answers directly without a second model pass |
directToolSpeechPercent | 0 | Stable percentage of calls with direct tool speech when directToolSpeech is unset |
Set metadata.directToolSpeech: false to disable direct speech for an agent immediately.
While a tool runs, the agent speaks short fillers such as "One sec." and "Still checking.". The first filler comes 0.4 s after the tool starts, then one every 4 s, at most 3 per tool round.
A webhook tool can answer {"status": "pending", "ticket": "<id>"} when its answer is not ready. The call then asks the same webhook with {"ticket": "<id>"} until it answers, for up to 2 minutes. The agent speaks the answer at the caller's next pause, and the caller can interrupt it.
Managing Tools
# Add a tool to an agent
curl -X POST https://api.ph0ny.com/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://api.ph0ny.com/v1/agents/:id/tools \
-H "Authorization: Bearer $PH0NY_API_KEY"
# Delete a tool
curl -X DELETE https://api.ph0ny.com/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://api.ph0ny.com/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://api.ph0ny.com/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://api.ph0ny.com/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://api.ph0ny.com/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.