Custom Personas (Agents)
An agent is the saved config you point a call at. It holds the persona, the conversation flow, the AI stack, the runtime knobs, and the post-call settings in one record you reuse across every call. Build one in the Agent Studio by filling the sections, or send the same fields as JSON to the API.
Agent Structure
An agent is built from layered configuration:
┌──────────────────────────┐
│ System Prompt (raw) │ ← Simple mode: just a string
├──────────────────────────┤
│ Persona │ ← Structured: role, tone, audience, voice
├──────────────────────────┤
│ Playbook │ ← Conversation flow: opener, scripts, CTAs
├──────────────────────────┤
│ Settings │ ← Runtime controls: barge-in, silence, turns
├──────────────────────────┤
│ Features │ ← Toggles: recording, transcription
├──────────────────────────┤
│ AI Stack │ ← LLM, STT, TTS provider/model selection
├──────────────────────────┤
│ Post-Call Intelligence │ ← Summary, extraction, evaluation config
└──────────────────────────┘Simple Mode vs Structured Mode
Simple Mode
Pass a system_prompt string and Rymi uses it directly as the LLM context:
{
"name": "Alex - Support Agent",
"system_prompt": "You are Alex, a friendly customer support agent for TechCorp..."
}Structured Mode
Use persona and playbook objects for more control. Rymi's Prompt Compiler merges these into an optimized system prompt at call time.
{
"name": "Priya - Sales Specialist",
"persona": {
"name": "Priya",
"role": "Insurance sales specialist",
"toneOverride": "Warm and confident",
"audienceDescription": "Small business owners in India",
"companyName": "Acme Insurance",
"successCriteria": ["Qualify the lead", "Book a follow-up call"],
"voiceConfig": {
"voiceId": "Aoede",
"language": "en-US"
},
"callerPersonas": [
{ "type": "interested", "approach": "Mirror enthusiasm, move to qualification" },
{ "type": "skeptical", "approach": "Lead with social proof and case studies" }
]
},
"playbook": {
"opener": "Hi, this is Priya from Acme Insurance. Is this a good time?",
"qualificationFlow": [
{ "question": "How many employees does your company have?", "listensFor": "Company size" },
{ "question": "What's your current insurance provider?", "listensFor": "Current provider" }
],
"objectionHandlers": [
{ "trigger": "too expensive", "response": "I understand cost is important. Our plans start at just..." }
],
"closingCTA": "I'd love to set up a quick demo. Does Thursday work for you?",
"fallbackCTA": "Can I send you some information to review at your convenience?"
}
}Rymi compiles the agent instructions from the persona and playbook fields and returns the compiled prompt with the agent.
AI Stack Configuration
On a custom agent (the default agent_kind) you choose the LLM, STT, and TTS yourself. There are two stack shapes:
| Stack | Pipeline | Best For |
|---|---|---|
| Pipeline | Separate STT → LLM → TTS | Full control over each component; mix any providers, swap voices freely |
| Realtime | Bundled realtime model (Gemini Live / OpenAI Realtime) | Lowest latency, end-to-end; the model handles STT and TTS itself |
(For a managed agent, set agent_kind: "managed" and a managed_sku_id instead. The stack is locked by the SKU.)
Setting a pipeline stack
{
"llm_model": "gemini-2.5-flash",
"stt_provider": "google",
"tts_provider": "google",
"tts_model": "gemini-2.5-flash-tts",
"voice": "Aoede"
}Setting a realtime stack
With a realtime model, STT and TTS are handled by the model itself. Leave them empty:
{
"llm_model": "gemini-live"
}Use GET /v1/agents/llm-options to fetch the catalog of available models and voices.
Language Routing
Rymi derives the provider route from the primary language, supported languages, and provider capabilities. Set language to a locale such as en-US or hi-IN, and use supported_languages for every language the agent may run. Rymi resolves a valid STT, LLM, and TTS stack for each selected language before save. Automatic language detection is not default MVP behavior.
Runtime Controls
The advanced object tunes how the agent behaves during calls:
{
"advanced": {
"maxTurnLength": 30,
"postSilenceHangup": 15,
"turnEndpointer": "smart-turn-v3",
"smartEndpointing": true,
"waitAfterSentence": 300,
"stt_eot_timeout_ms": 2000
}
}| Control | Type | Description |
|---|---|---|
maxTurnLength | number | Maximum agent response duration in seconds |
postSilenceHangup | number | End call after this many seconds of user silence |
turnEndpointer | "smart-turn-v3" | "timer" | End-of-turn detection engine. smart-turn-v3 uses the audio endpointer; timer relies on silence only |
smartEndpointing | boolean | Content-aware end-of-turn detection |
waitAfterSentence | number | Milliseconds to wait after a completed sentence before ending the turn |
stt_eot_timeout_ms | number | Max milliseconds of silence before forcing end-of-turn (Deepgram Flux) |
Barge-in (letting the caller interrupt the agent mid-response) is configured on the persona, not in advanced:
{
"persona": {
"voiceConfig": { "bargeInEnabled": true }
}
}TIP
These controls are enforced at runtime by the gateway. They override any contradictory instructions in the system prompt.
Feature Flags
Toggle capabilities per agent:
{
"features": {
"recording_enabled": true,
"transcription_enabled": true
}
}| Feature | Effect When Disabled |
|---|---|
recording_enabled | No call recording is started |
transcription_enabled | No transcript persistence, no transcript data packets, no post-call transcript analysis |
Post-Call Intelligence
Configure what analysis runs after each call ends. See the Post-Call Intelligence guide for full details.
{
"post_call": {
"summary": { "enabled": true },
"structured_extraction": {
"json_schema": {
"type": "object",
"properties": {
"appointment_booked": { "type": "boolean" },
"follow_up_date": { "type": "string" }
}
}
},
"evaluation": {
"rubric": "Did the agent successfully qualify the lead and book a follow-up?"
}
}
}Auto-Generation
Describe your ideal agent in plain English and let Rymi generate the full persona/playbook bundle:
curl -X POST https://api.rymi.live/v1/agents/generate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A friendly female sales agent who speaks English with an American accent and sells insurance plans",
"options": { "llm_provider": "gemini", "voice": "Aoede" }
}'The response includes a draft object and a compiled_prompt_preview you can review before creating the agent.

