Appearance
Freeform Agents
A freeform agent has a single system prompt and a flat set of tools the LLM can call at any point. No stages, no transitions — the LLM handles everything.
Contents
- Agent Fields
- Example 1 — English Support Agent
- Example 2 — Multilingual Agent (Hindi)
- Example 3 — Agent with Inline Tools
- Example 4 — CRM Lookup on Call Start
- Choosing Providers
- Greeting Modes
- Pipeline Tuning
Agent Fields
| Field | Required | Default | Description |
|---|---|---|---|
name | Yes | — | Unique. No spaces. Used in webhook URL: /telephony/{provider}/inbound/{name} |
prompt | Yes | — | System prompt. Who the agent is and how to behave. |
greeting | No | "Hello! How can I help?" | First thing spoken. Bypasses LLM for ~1.3s faster first audio. |
stt_provider | No | deepgram | deepgram sarvam openai elevenlabs |
stt_model | No | auto | nova-3-general saaras:v3 whisper-1 scribe_v1 |
stt_language | No | en | BCP-47 code. Required for Sarvam. |
stt_mode | No | — | Sarvam only: transcribe translate verbatim |
llm_provider | No | openai | openai google grok |
llm_model | No | gpt-4.1-nano | gpt-4.1-mini gpt-4o gemini-2.5-flash grok-3-beta |
tts_provider | No | cartesia | cartesia elevenlabs sarvam deepgram openai |
tts_model | No | auto | sonic-3 eleven_flash_v2_5 bulbul:v2 aura-2 tts-1 |
voice | No | auto | Voice ID or name. Provider-specific. |
tts_language | No | — | For multilingual TTS providers |
tool_ids | No | [] | UUIDs of webhook tools the LLM can call during the call |
pre_call_tool_ids | No | [] | Tool UUIDs that fire automatically at call start |
stt_settings | No | {} | Provider-specific STT overrides |
llm_settings | No | {} | {"temperature": 0.7, "max_tokens": 200} |
tts_settings | No | {} | Provider-specific TTS overrides |
pipeline_settings | No | {} | VAD, idle timeout, turn detection |
context_variables | No | {} | Schema for outbound call parameters |
webhook_url | No | — | Called on call_started / call_ended events |
webhook_events | No | [] | ["call_started", "call_ended", "no_answer", "failed"] |
Example 1 — English Support Agent
Simple customer support with order lookup and callback scheduling.
json
{
"version": "1",
"agent": {
"name": "support-agent",
"prompt": "You are Maya, a friendly customer support agent for ShopEasy, an online electronics store.\n\nYou help customers with:\n1. Order status — ask for their order ID, then call check_order_status.\n2. Scheduling callbacks — collect name, phone, preferred time, then call schedule_callback.\n\nBe concise and warm. Relay tool results naturally.",
"greeting": "Hi, this is Maya from ShopEasy support. How can I help you today?",
"stt_provider": "deepgram",
"stt_model": "nova-3-general",
"stt_language": "en",
"llm_provider": "openai",
"llm_model": "gpt-4.1-nano",
"tts_provider": "cartesia",
"tts_model": "sonic-3",
"voice": "694f9389-aac1-45b6-b726-9d9369183238",
"tool_ids": ["<check_order_status_uuid>", "<schedule_callback_uuid>"]
},
"tools": [],
"flow_nodes": []
}Key points:
- Tool UUIDs go in
tool_ids— create the tools first via the dashboard orPOST /api/tools - Mention every tool by name in the
promptso the LLM knows when to call it end_callis always available in freeform mode — no configuration needed
Example 2 — Multilingual Agent (Hindi)
Full Hindi voice pipeline using Sarvam STT and TTS.
json
{
"version": "1",
"agent": {
"name": "hindi-support",
"prompt": "You are Priya, a friendly customer support agent for TechMart India. Respond only in Hindi. Be polite and concise.",
"greeting": "नमस्ते! मैं TechMart से प्रिया हूँ। आज मैं आपकी कैसे मदद कर सकती हूँ?",
"stt_provider": "sarvam",
"stt_model": "saaras:v3",
"stt_language": "hi-IN",
"stt_mode": "transcribe",
"llm_provider": "openai",
"llm_model": "gpt-4o",
"tts_provider": "sarvam",
"tts_model": "bulbul:v2",
"voice": "anushka",
"tts_language": "hi-IN"
},
"tools": [],
"flow_nodes": []
}Other Indian language combinations:
| Language | STT | TTS |
|---|---|---|
| Tamil | sarvam / saaras:v3 / ta-IN | sarvam / bulbul:v2 / ta-IN |
| Telugu | sarvam / saaras:v3 / te-IN | sarvam / bulbul:v2 / te-IN |
| Kannada | sarvam / saaras:v3 / kn-IN | sarvam / bulbul:v2 / kn-IN |
| Bengali | sarvam / saaras:v3 / bn-IN | sarvam / bulbul:v2 / bn-IN |
Example 3 — Agent with Inline Tools
Real estate inquiry agent that can check property listings and book site visits.
json
{
"version": "1",
"agent": {
"name": "property-inquiry",
"prompt": "You are Aisha, a property consultant at HomeNest Realty.\n\nWhen callers ask about available properties, call search_properties with their requirements (location, budget, bedrooms).\nWhen callers want to book a site visit, collect their name and preferred date/time, then call book_site_visit.\nIf they want to be called back, collect their preferred time and call schedule_callback.",
"greeting": "Hello! Welcome to HomeNest Realty. I'm Aisha. Are you looking to buy or rent?",
"llm_model": "gpt-4.1-mini",
"tool_ids": ["<search_properties_uuid>", "<book_site_visit_uuid>", "<schedule_callback_uuid>"]
},
"tools": [],
"flow_nodes": []
}Tool prompt instructions — be explicit in the prompt:
Good: "When the caller gives their budget and location, call search_properties."
Bad: "You have access to search_properties."The LLM only calls a tool if the prompt tells it when to. Vague instructions lead to missed tool calls.
Example 4 — CRM Lookup on Call Start
Use pre_call_tool_ids to fetch caller data before the LLM's first response. The greeting plays via TTS while the lookup runs in parallel — zero extra latency.
Step 1 — Create the lookup tool:
bash
curl -X POST https://your-domain.com/api/tools \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "lookup_caller",
"description": "Look up a caller by phone number. Returns their name, account tier, and open support tickets.",
"parameters": {
"properties": {
"phone_number": { "type": "string", "description": "Caller phone number with country code" },
"direction": { "type": "string", "description": "Call direction: inbound or outbound" }
},
"required": ["phone_number"]
},
"webhook_url": "https://your-api.com/crm/lookup",
"webhook_method": "POST",
"timeout_secs": 5
}'Step 2 — Create the agent with pre_call_tool_ids:
json
{
"version": "1",
"agent": {
"name": "premium-support",
"prompt": "You are Rahul, a senior support agent at TechCorp. If the caller context includes their name, use it. If they have an active support ticket, acknowledge it. If they are a premium account, prioritise their issue.",
"greeting": "Thank you for calling TechCorp support. Please hold for just a moment.",
"pre_call_tool_ids": ["<lookup_caller_uuid>"]
},
"tools": [],
"flow_nodes": []
}What happens at call time:
- Call arrives
- Greeting plays: "Thank you for calling TechCorp support. Please hold for just a moment."
- Simultaneously:
lookup_callerfires with{"phone_number": "+919876543210", "direction": "inbound"} - Your webhook returns:
{"name": "Priya Sharma", "tier": "premium", "open_tickets": 1} - LLM context becomes:
Caller context: { "lookup_caller": { "name": "Priya Sharma", "tier": "premium", "open_tickets": 1 } } - When Priya speaks, the LLM says: "Hi Priya! I can see you have an open ticket — let me pull that up for you."
Choosing Providers
| Need | Recommended stack |
|---|---|
| English, cost-efficient | Deepgram + GPT-4.1-nano + Cartesia |
| English, high accuracy | Deepgram + GPT-4o + ElevenLabs |
| Hindi / Indian languages | Sarvam + GPT-4o + Sarvam |
| Low latency | Deepgram + GPT-4.1-nano + Cartesia |
| Most natural voice | ElevenLabs (both STT and TTS) |
Greeting Modes
1. Static greeting — fastest first audio (~1.3s faster than LLM)
json
{ "greeting": "Hi there! Thanks for calling Acme Corp." }2. Template greeting — personalised for outbound calls
json
{ "greeting": "Hi {{customer_name}}, this is Priya calling about your order {{order_id}}." }3. LLM-generated greeting — set greeting to "". The LLM generates it from the system prompt. Slower but dynamic. Only works with flow agents.
json
{ "greeting": "" }Pipeline Tuning
Override defaults via pipeline_settings:
json
{
"pipeline_settings": {
"idle_warn_secs": 25,
"idle_end_secs": 50,
"vad_confidence": 0.5,
"vad_start_secs": 0.2,
"vad_stop_secs": 0.2,
"vad_min_volume": 0.4,
"min_words": 3
}
}| Setting | Default | Description |
|---|---|---|
idle_warn_secs | 25 | Seconds of silence before asking "Are you still there?" |
idle_end_secs | 50 | Seconds of silence before ending the call |
vad_confidence | 0.5 | Voice detection confidence threshold (0–1) |
vad_start_secs | 0.2 | Seconds of speech before VAD triggers |
vad_stop_secs | 0.2 | Seconds of silence before VAD marks end of turn |
vad_min_volume | 0.4 | Minimum volume to be detected as speech |
min_words | 3 | Minimum words required to interrupt the agent (standard mode) |