Skip to content

Agents ​

Agents are the reusable voice personas that power calls. Each agent stores its prompt, persona/playbook structure, provider routing, post-call defaults, and feature flags.

List Agents ​

GET/v1/agents

Returns a paginated list of agents for the authenticated tenant.

Query Parameters ​

ParameterTypeDefaultDescription
limitinteger50Max records to return (max 500)
offsetinteger0Records to skip

Example Request ​

bash
curl "https://api.rymi.live/v1/agents?limit=10&offset=0" \
  -H "Authorization: Bearer YOUR_API_KEY"
ts
const { agents } = await rymi.agents.list({ limit: 10, offset: 0 });
python
result = rymi.agents.list(limit=10, offset=0)

Response 200 ​

json
{
  "agents": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Priya - Sales Specialist",
      "voice": "Aoede",
      "llm_provider": "gemini",
      "llm_model": "gemini-2.5-flash",
      "agent_kind": "custom",
      "language": "en-US",
      "created_at": "2026-03-01T10:00:00Z"
    }
  ],
  "total": 1,
  "offset": 0,
  "limit": 10
}

Errors ​

StatusMeaning
401Missing or invalid API key

Model and Voice Catalog ​

GET/v1/agents/llm-options

Returns the model catalog and voice list available for agent configuration. Populate dropdowns and pickers from this before you create or update an agent.

Example Request ​

bash
curl https://api.rymi.live/v1/agents/llm-options \
  -H "Authorization: Bearer YOUR_API_KEY"
ts
const { models, voices } = await rymi.agents.llmOptions();
python
result = rymi.agents.llm_options()

Response 200 ​

json
{
  "models": [
    {
      "provider": "google",
      "provider_name": "Google",
      "model_id": "gemini-2.5-flash",
      "label": "Gemini 2.5 Flash",
      "type": ["llm"],
      "plan_locked": false,
      "required_plan": null,
      "byok_required": false,
      "byok_provider_id": null,
      "modality": "standard",
      "latency_ms": null,
      "cost_per_min": null,
      "reasoning_supported": false
    }
  ],
  "voices": [
    {
      "id": "voice_aoede",
      "provider": "google",
      "name": "Aoede",
      "label": "Aoede",
      "gender": "Female",
      "supported_model_ids": ["gemini-2.5-flash"],
      "is_active": true,
      "byok_required": false,
      "byok_provider_id": null
    }
  ]
}

Each model uses model_id as its identifier and provider as the provider key. The type array records which roles the entry can fill (llm, stt, tts). Voice entries carry the human-readable label, gender, and supported_model_ids (the models a voice is compatible with). byok_required is true when the provider requires your own key.


Agent Kind ​

Every agent is one of two kinds, set with agent_kind on create or update. The kind also determines how the agent is billed. See Pricing model.

KindAPI ValueStackBilling
Custom (default)customYou choose the STT, LLM, and TTS models (and optional fallbacks).Component cost (sum of each model's per-minute rate) + a flat $0.02/min platform fee
ManagedmanagedA ready-made, locked stack chosen for you. Set managed_sku_id to the chosen SKU.The SKU's fixed published price_per_min

List the available managed SKUs (with prices and their locked stacks) via GET /v1/managed-skus. For custom agents, call GET /v1/agents/llm-options for valid model and voice IDs.

Language Routing ​

The language field is the primary language the agent starts with. The supported_languages field lists every language this agent may run.

  • Use an explicit locale such as en-US or hi-IN for language.
  • Include one or more locales in supported_languages.
  • For custom agents, Rymi resolves a valid STT, LLM, and TTS stack for each selected language before the agent is saved.
  • Automatic language detection and mid-call dynamic rerouting are not default MVP behavior.
  • Routing is derived from the selected languages and supported provider capabilities. Public API clients do not need to manage provider routing tables.

Create Agent ​

POST/v1/agents

Request Body ​

FieldTypeRequiredDefaultDescription
namestringYes-Studio label: the name in your sidebar and agent list (100 characters or fewer recommended). The name the agent speaks is persona.name, which defaults to this label
system_promptstringNo-Raw system prompt. With advanced.prompt_mode: "raw" the agent uses it word for word. In builder mode (the default), Rymi extracts persona and playbook from it when you send neither; when you send them too, it appends the prompt as an "Additional instructions" section
voicestringNoAoedeTTS voice ID from GET /v1/agents/llm-options
languagestringNoen-USPrimary call language locale (for example, en-US, hi-IN)
supported_languagesstring[]No[language]Locales this agent may run. The API resolves a valid stack for each selected language
agent_kindstringNocustomcustom (you pick the stack) or managed (Rymi Managed SKU). See Agent Kind
managed_sku_idstring | nullNonullRequired when agent_kind is managed: the SKU ID from GET /v1/managed-skus. Must be null for custom agents
llm_providerstringNoStack defaultgemini, openai, anthropic, or sarvam
llm_modelstringNoStack defaultLLM model ID (a realtime model bundles STT/TTS)
stt_providerstringNoStack defaultSpeech-to-text provider
stt_modelstringNoStack defaultSTT model ID
tts_providerstringNoStack defaultText-to-speech provider
tts_modelstringNoStack defaultTTS model ID
llm_fallback_providerstring | nullNo-Secondary LLM provider used if the primary fails. null clears it
llm_fallback_modelstring | nullNo-Secondary LLM model. null clears it
stt_fallback_providerstring | nullNo-Secondary STT provider. null clears it
stt_fallback_modelstring | nullNo-Secondary STT model. null clears it
tts_fallback_providerstring | nullNo-Secondary TTS provider. null clears it
tts_fallback_modelstring | nullNo-Secondary TTS model. null clears it
custom_llm_urlstring | nullNo-Self-hosted LLM endpoint (https:// or wss://). Enterprise only; null clears
custom_voice_urlstring | nullNo-Self-hosted TTS endpoint. Enterprise only; null clears
custom_voice_modestringNorymiWire format for custom_voice_url: rymi or openai-compat
custom_transcriber_urlstring | nullNo-Self-hosted STT endpoint. Enterprise only; null clears
personaPersona objectNo-Structured role, tone, audience, and voice config
playbookPlaybook objectNo-Opener, qualification flow, scripts, CTA, and escalation rules
advancedadvanced objectNo-Runtime tuning (endpointing, turn timing)
featuresFeatures objectNo-Feature flags (recording, transcription)
post_callPost-call objectNo-Default post-call intelligence config
toolsobject[]No-Tool bindings: API tools (call_webhook), handoff and others. An update replaces the whole array, so read the agent first. See API Tools
provider_configobjectNo-Read-only. Server-derived from the resolved stack + supported languages on every write; ignored if sent as input and cannot be set via the API

Persona Object ​

FieldTypeDescription
rolestringAgent's role description (e.g., "Insurance sales specialist")
toneOverridestringSpeaking style (e.g., "warm and concise")
audienceDescriptionstringWho the agent talks to
voiceConfigobjectVoice settings: { "voiceId": "Aoede", "language": "en-US", "bargeInEnabled": true }
successCriteriastring[]What a successful call looks like
callerPersonasobject[]Caller type variants: { type, approach }

The full persona shape (company fields, knowledge base) is in the Configuration Reference below.

Playbook Object ​

FieldTypeDescription
openerstringOpening message the agent uses to start the conversation
qualificationFlowobject[]Questions and what to listen for: { question, listensFor }
requiredSlotsobject[]Data to collect: { name, description, required }
objectionHandlersobject[]How to handle pushback: { trigger, response }
scriptsobject[]Canned responses for specific situations: { title, when, content }
closingCTAstringPrimary call-to-action the agent drives toward
fallbackCTAstringFallback if the primary CTA fails
escalationRulestringWhen/how to escalate to a human
endCallMessagestringClosing message or sign-off script

advanced object ​

Runtime tuning: turn timing, speech detection, and safety limits. See the Configuration Reference for the full field list (maxCallDuration, silencePromptDelay, smartEndpointing, STT options, …).

Features Object ​

FieldTypeDefaultDescription
recording_enabledbooleanfalseRecord both sides of each call
transcription_enabledbooleantrueTranscribe and store each call
require_consentbooleantrueAnnounce recording at call start

Post-call Object ​

FieldTypeDefaultDescription
summary.enabledbooleantrueGenerate a summary after each call
summary.promptstring-Custom instructions for the summary LLM (e.g. "highlight objections")
structured_extraction.json_schemaobject-JSON Schema defining the structured data to extract from the transcript
structured_extraction.promptstring-Custom instructions for the extraction LLM (auto-generated from schema if omitted)
evaluation.rubricstring-Numbered list of quality criteria for call scoring
model.providerstring-LLM provider for post-call analysis: gemini or openai. Defaults to platform setting
model.modelstring-Specific model ID (e.g. gemini-2.5-flash, gpt-4o-mini). Defaults to platform setting

Example: Minimal ​

bash
curl -X POST https://api.rymi.live/v1/agents \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Support Agent"
  }'

Example: Full Configuration ​

bash
curl -X POST https://api.rymi.live/v1/agents \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Priya - Sales Specialist",
    "system_prompt": "You are Priya, a friendly insurance sales agent who speaks Hindi with a Delhi accent.",
    "voice": "Aoede",
    "language": "hi-IN",
    "llm_provider": "gemini",
    "llm_model": "gemini-2.5-flash",
    "persona": {
      "role": "Insurance sales specialist",
      "toneOverride": "warm, patient, and persuasive",
      "audienceDescription": "Hindi-speaking consumers in North India",
      "voiceConfig": { "voiceId": "Aoede", "language": "hi-IN", "bargeInEnabled": true },
      "successCriteria": ["Lead qualified", "Follow-up call booked"]
    },
    "playbook": {
      "opener": "Namaste! Main Priya hoon, Acme Insurance se. Kaise madad kar sakti hoon?",
      "qualificationFlow": [
        { "question": "What type of coverage are you looking for?", "listensFor": "Interest in health insurance" },
        { "question": "How many family members need coverage?", "listensFor": "Family size and decision-maker status" }
      ],
      "objectionHandlers": [
        { "trigger": "Premium feels too expensive", "response": "Acknowledge, then compare against out-of-pocket hospital costs." }
      ],
      "closingCTA": "Book a follow-up call with our advisor",
      "escalationRule": "Transfer to a human when the customer requests a supervisor",
      "endCallMessage": "Thank you for your time! We will send the policy details to your email."
    },
    "advanced": {
      "maxCallDuration": 600,
      "silencePromptDelay": 8,
      "smartEndpointing": true
    },
    "features": {
      "recording_enabled": true,
      "transcription_enabled": true,
      "require_consent": true
    },
    "post_call": {
      "summary": { "enabled": true },
      "structured_extraction": {
        "json_schema": {
          "type": "object",
          "properties": {
            "interested_plan": { "type": "string" },
            "family_size": { "type": "integer" },
            "booked_followup": { "type": "boolean" }
          }
        }
      },
      "evaluation": {
        "rubric": "1. Did the agent qualify the lead?\n2. Did the agent book a follow-up?"
      }
    }
  }'

Response 201 ​

json
{
  "status": "created",
  "id": "550e8400-e29b-41d4-a716-446655440000"
}

Errors ​

StatusMeaning
400Validation error (missing name, invalid agent_kind/managed_sku_id, etc.)
401Missing or invalid API key
402Insufficient credits

Get Agent ​

GET/v1/agents/:id

Returns the full agent configuration including the compiled prompt.

Path Parameters ​

ParameterTypeDescription
iduuidAgent ID

Example Request ​

bash
curl https://api.rymi.live/v1/agents/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer YOUR_API_KEY"
ts
const agent = await rymi.agents.retrieve("550e8400-e29b-41d4-a716-446655440000");
python
agent = rymi.agents.retrieve("550e8400-e29b-41d4-a716-446655440000")

Response 200 ​

json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Priya - Sales Specialist",
  "voice": "Aoede",
  "language": "hi-IN",
  "persona": {
    "role": "Insurance sales specialist",
    "toneOverride": "warm and persuasive",
    "audienceDescription": "Hindi-speaking consumers in North India",
    "voiceConfig": { "voiceId": "Aoede", "language": "hi-IN" }
  },
  "playbook": {
    "opener": "Namaste! Main Priya hoon, Acme Insurance se.",
    "closingCTA": "Book a follow-up call with our advisor"
  },
  "compiled_prompt": "You are Priya...",
  "llm_provider": "gemini",
  "llm_model": "gemini-2.5-flash",
  "agent_kind": "custom",
  "managed_sku_id": null,
  "features": {
    "recording_enabled": true,
    "transcription_enabled": true
  },
  "post_call": {
    "summary": { "enabled": true },
    "evaluation": { "rubric": null }
  },
  "updated_at": "2026-03-01T10:00:00Z"
}

Errors ​

StatusMeaning
401Missing or invalid API key
404Agent not found for this tenant

Update Agent ​

PUT/v1/agents/:id
PATCH/v1/agents/:id

Pass only the fields you want to change. Unspecified fields remain unchanged. PUT and PATCH behave identically: both apply a partial update to the agent.

Path Parameters ​

ParameterTypeDescription
iduuidAgent ID

Request Body ​

Accepts the same fields as Create Agent. All fields are optional.

Example Request ​

bash
curl -X PUT https://api.rymi.live/v1/agents/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "system_prompt": "Updated instructions for handling renewals...",
    "post_call": {
      "summary": { "enabled": true },
      "structured_extraction": {
        "json_schema": {
          "type": "object",
          "properties": {
            "renewal_confirmed": { "type": "boolean" }
          }
        }
      }
    }
  }'
ts
const result = await rymi.agents.update("550e8400-e29b-41d4-a716-446655440000", {
  system_prompt: "Updated instructions for handling renewals...",
  post_call: {
    summary: { enabled: true },
    structured_extraction: {
      json_schema: {
        type: "object",
        properties: {
          renewal_confirmed: { type: "boolean" },
        },
      },
    },
  },
});
python
result = rymi.agents.update(
    "550e8400-e29b-41d4-a716-446655440000",
    system_prompt="Updated instructions for handling renewals...",
    post_call={
        "summary": {"enabled": True},
        "structured_extraction": {
            "json_schema": {
                "type": "object",
                "properties": {
                    "renewal_confirmed": {"type": "boolean"},
                },
            }
        },
    },
)

Response 200 ​

json
{
  "status": "updated"
}

Errors ​

StatusMeaning
400Validation error
401Missing or invalid API key
404Agent not found for this tenant

Clone Agent ​

POST/v1/agents/:id/clone

Creates a duplicate of an existing agent. The clone gets " (Copy)" appended to its name and is otherwise identical: same persona, playbook, advanced config, post-call settings, and provider stack. The original is unchanged.

Path Parameters ​

ParameterTypeDescription
iduuidAgent ID to clone

Example Request ​

bash
curl -X POST https://api.rymi.live/v1/agents/550e8400-e29b-41d4-a716-446655440000/clone \
  -H "Authorization: Bearer YOUR_API_KEY"
ts
const clone = await rymi.agents.clone("550e8400-e29b-41d4-a716-446655440000");
python
clone = rymi.agents.clone("550e8400-e29b-41d4-a716-446655440000")

Response 201 ​

json
{
  "status": "created",
  "id": "7f3e9a12-b4c1-41f2-a890-556677889900"
}

Errors ​

StatusMeaning
401Missing or invalid API key
403Agent belongs to a different tenant
404Agent not found

List Agent Calls ​

GET/v1/agents/:id/calls

Returns a paginated list of calls made with a specific agent. Use it to monitor per-agent performance and debug call flows.

Path Parameters ​

ParameterTypeDescription
iduuidAgent ID

Query Parameters ​

ParameterTypeDefaultDescription
limitinteger50Max records to return (max 200)
offsetinteger0Records to skip
statusstringAll statusesFilter by call status: queued, ringing, in_progress, completed, or failed

Example Request ​

bash
curl "https://api.rymi.live/v1/agents/550e8400-e29b-41d4-a716-446655440000/calls?limit=20&status=completed" \
  -H "Authorization: Bearer YOUR_API_KEY"
ts
const { calls } = await rymi.agents.listCalls("550e8400-e29b-41d4-a716-446655440000", {
  limit: 20,
  status: "completed",
});
python
result = rymi.agents.list_calls(
    "550e8400-e29b-41d4-a716-446655440000",
    limit=20,
    status="completed",
)

Response 200 ​

json
{
  "calls": [
    {
      "id": "call_abc123",
      "agent_id": "550e8400-e29b-41d4-a716-446655440000",
      "status": "completed",
      "started_at": "2026-03-01T10:00:00Z",
      "ended_at": "2026-03-01T10:05:00Z",
      "bill_duration": 300,
      "total_cost": 0.30
    }
  ],
  "total": 1,
  "offset": 0,
  "limit": 20,
  "agent_id": "550e8400-e29b-41d4-a716-446655440000"
}

Errors ​

StatusMeaning
401Missing or invalid API key
403Publishable keys cannot access call history, or agent does not belong to you
404Agent not found

Delete Agent ​

DELETE/v1/agents/:id

WARNING

Deleting an agent cascade-deletes all associated number mappings. Active calls using this agent are not affected.

Path Parameters ​

ParameterTypeDescription
iduuidAgent ID

Example Request ​

bash
curl -X DELETE https://api.rymi.live/v1/agents/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer YOUR_API_KEY"
ts
const result = await rymi.agents.delete("550e8400-e29b-41d4-a716-446655440000");
python
result = rymi.agents.delete("550e8400-e29b-41d4-a716-446655440000")

Response 200 ​

json
{
  "status": "deleted",
  "id": "550e8400-e29b-41d4-a716-446655440000"
}

Errors ​

StatusMeaning
401Missing or invalid API key
404Agent not found for this tenant

Generate Agent Draft ​

POST/v1/agents/generate

Describe the agent you want in plain English. Rymi returns a draft persona/playbook bundle plus a compiled prompt preview. You can also send the current draft and opt into clarifying questions before generation.

Request Body ​

FieldTypeRequiredDefaultDescription
promptstringYes-Natural-language description of the agent you want
modestringNocreatecreate for a new agent or edit to refine an existing config
allow_clarifying_questionsbooleanNofalseWhen true, Rymi may return questions instead of generating a weak draft
options.voicestringNo-Preferred voice ID or name
options.llm_providerstringNo-Preferred LLM provider hint
options.llm_modelstringNo-Preferred model hint
current_configobjectNo-Current agent config snapshot for edit mode

Example: Create Mode ​

bash
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 Hindi with a Delhi accent and can sell insurance plans",
    "options": {
      "llm_provider": "gemini",
      "voice": "Aoede"
    },
    "mode": "create",
    "allow_clarifying_questions": false
  }'

Response 200: Generated ​

json
{
  "generated": true,
  "draft": {
    "name": "Delhi Insurance Sales Agent",
    "voice": "Aoede",
    "llm_provider": "gemini",
    "persona": {
      "role": "Insurance sales specialist",
      "tone": "friendly",
      "audience": "Hindi-speaking consumers in North India"
    },
    "playbook": {
      "opener": "Namaste! Main aapki insurance needs mein madad kar sakti hoon.",
      "cta": "Book a follow-up with our advisor"
    }
  },
  "compiled_prompt_preview": "You are a friendly female sales agent..."
}

Response 200: Clarifying Questions ​

If allow_clarifying_questions is true and the brief is too thin:

json
{
  "generated": false,
  "clarifying_questions": [
    "What primary action should the agent drive toward?",
    "How should we know the call was successful?"
  ],
  "quality_gates": {
    "blockers": ["Primary CTA is missing."],
    "warnings": ["Audience context is thin."]
  }
}

Example: Edit Mode ​

bash
curl -X POST https://api.rymi.live/v1/agents/generate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Make the tone more formal and add an escalation rule for angry customers",
    "mode": "edit",
    "current_config": {
      "name": "Support Agent",
      "persona": { "role": "Customer support", "tone": "friendly" },
      "playbook": { "opener": "Hi! How can I help?" }
    }
  }'

Errors ​

StatusMeaning
400Missing prompt or invalid mode
401Missing or invalid API key
500Generation failed
503Generation provider is not configured

Configuration Reference ​

The canonical agent payload shape. Every field is optional on PUT /v1/agents/:id (partial updates). On POST /v1/agents only name is required.

Top-level Fields ​

FieldTypeDefaultDescription
namestringrequiredDisplay name for the agent
voicestring"Aoede"Voice ID (use GET /v1/agents/llm-options for available voices)
languagestring"en-US"BCP-47 language code
agent_kindstring"custom"custom or managed. See Agent Kind
managed_sku_idstring | nullnullSKU ID for managed agents (GET /v1/managed-skus); null for custom
llm_providerstring"gemini"Conversation LLM: gemini, openai, anthropic, sarvam
llm_modelstring"gemini-2.5-flash"Model ID for the conversation LLM
stt_providerstring-Speech-to-text provider override
stt_modelstring-STT model override
tts_providerstring-Text-to-speech provider override
tts_modelstring-TTS model override
supported_languagesstring[][language]All BCP-47 locales this agent may run
llm_fallback_provider / llm_fallback_modelstring | null-Secondary LLM provider/model; null clears
stt_fallback_provider / stt_fallback_modelstring | null-Secondary STT provider/model; null clears
tts_fallback_provider / tts_fallback_modelstring | null-Secondary TTS provider/model; null clears
custom_llm_url / custom_voice_url / custom_transcriber_urlstring | null-Self-hosted endpoints (https:///wss://), Enterprise; null clears
custom_voice_modestringrymiWire format for custom_voice_url: rymi or openai-compat

provider_config is server-derived (recomputed from the resolved stack + supported languages on every write) and is not accepted as an input field.

persona Object ​

Who the agent is, how it sounds, and what it knows.

FieldTypeDescription
namestringThe name the agent speaks and introduces itself with, also shown on share and tester pages. Defaults to the agent's name (its Studio label)
rolestringJob title (e.g. "Sales Specialist")
audienceDescriptionstringWho the agent talks to
toneOverridestringSpeaking style (e.g. "warm and concise")
companyNamestringCompany name injected into the system prompt
companyWebsitestringCompany website URL
companyDescriptionstringWhat the company does
knowledgeBasestring[]URLs or text passages the agent references
successCriteriastring[]What a successful call looks like
voiceConfig.bargeInEnabledbooleanWhether the caller can interrupt mid-sentence
callerPersonasobject[]Caller type variants: { type, approach }

playbook Object ​

Conversation flow, objections, scripts, and call-to-action.

FieldTypeDescription
openerstringFirst thing the agent says
qualificationFlowobject[]Questions and what to listen for: { question, listensFor }
requiredSlotsobject[]Data to collect: { name, description, required }
objectionHandlersobject[]How to handle pushback: { trigger, response }
scriptsobject[]Canned responses for specific situations: { title, when, content }
closingCTAstringPrimary call-to-action at end of call
fallbackCTAstringFallback if primary CTA fails
escalationRulestringWhen/how to escalate to a human

advanced Object ​

Runtime, speech, and safety configuration.

FieldTypeDefaultDescription
maxCallDurationnumber600Max call length in seconds. Range 30 to 7200, enforced on POST /v1/agents/apply-changes but not on POST/PATCH /v1/agents
maxTurnLengthnumber60Max agent speaking time per turn (seconds)
silencePromptDelaynumber8Seconds of silence before nudging the caller
postSilenceHangupnumber15Seconds of silence before hanging up
replyDelaynumber0Milliseconds to pause before responding
startSpeakingPhrasingstring"agent_greets"agent_greets or wait_for_user
startSpeakingThresholdnumber-VAD sensitivity for when agent starts speaking
stopSpeakingThresholdnumber-VAD sensitivity for when caller stops speaking
resumeAfterInterruptionbooleantrueResume interrupted sentence after caller stops
smartEndpointingbooleantrueAI-powered end-of-turn detection
waitAfterSentencenumber-ms to wait after a sentence ends
waitAfterNoPunctuationnumber-ms to wait when no sentence-ending punctuation
waitAfterNumbersnumber-ms to wait after numbers (they often continue)
stt_confidence_thresholdnumber-Minimum confidence to accept a transcription
stt_numeral_formattingbooleantrueFormat numbers as numerals in transcript
stt_profanity_filterbooleanfalseFilter profanity from transcript
stt_keywordsstring-Comma-separated keywords to boost STT accuracy
offLimitsTopicsstring-Topics the agent must never discuss
prohibitedClaimsstring-Claims the agent must never make
prompt_modestring"builder"builder compiles the prompt from persona and playbook; raw uses system_prompt word for word (the playbook.opener still opens the call)
pronunciationsobject[]-Up to 100 { word, say_as, ipa? } entries. See Pronunciations

features Object ​

FieldTypeDefaultDescription
recording_enabledbooleanfalseRecord both sides of each call
transcription_enabledbooleantrueTranscribe and store each call
require_consentbooleantrueAnnounce recording at call start

post_call Object ​

FieldTypeDefaultDescription
summary.enabledbooleantrueGenerate a call summary
summary.promptstring-Custom summary instructions
structured_extraction.json_schemaobject-JSON Schema for data extraction
structured_extraction.promptstring-Custom extraction instructions (auto-generated if omitted)
evaluation.rubricstring-Numbered scoring criteria
model.providerstring-gemini or openai for post-call LLM
model.modelstring-Model ID for post-call LLM

Validate Publish ​

POST /v1/agents/validate-publish

Check whether an agent is ready to go live. Returns a validation report without persisting any changes.

Body

FieldTypeDescription
agent_iduuidOptional. Merge validation with a persisted agent's config
namestringAgent name to validate
voicestringVoice ID to validate
personaobjectPersona config
playbookobjectPlaybook config

Example

bash
curl -X POST https://api.rymi.live/v1/agents/validate-publish \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"agent_id": "550e8400-e29b-41d4-a716-446655440000"}'

Apply Changes ​

POST /v1/agents/apply-changes

Validates and resolves a flat key/value change-set against the AgentConfig field registry. Enforces field types, edit-mode blocklist, and implies rules. Does not persist. Follow up with PUT /v1/agents/:id.

Body

FieldTypeDescription
currentConfigobjectThe agent's current flat config
changesarray[{key, value}] field changes to apply
modestring"create" or "edit"
lenientbooleanSkip unknown-field hard-fail (not recommended)

Example

bash
curl -X POST https://api.rymi.live/v1/agents/apply-changes \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "currentConfig": {"name": "Support", "voice": "Aoede"},
    "changes": [{"key": "voice", "value": "Charon"}],
    "mode": "edit"
  }'

Response

json
{
  "valid": true,
  "config": { "name": "Support", "voice": "Charon" },
  "applied": [{ "key": "voice", "value": "Charon" }]
}

Preview Model Stack ​

POST /v1/agents/stack-preview

Resolves the model stack (STT/LLM/TTS) for a set of supported languages, along with any blockers and warnings, without saving. Call this before create or update to confirm a multi-language setup resolves to a valid stack.

Body

FieldTypeRequiredDescription
supported_languagesstring[]YesNon-empty list of BCP-47 locales to resolve a stack for
languagestring | nullNoPrimary locale (defaults to the first supported language)
current_provider_configobject | nullNoExisting provider config to diff against

Example

bash
curl -X POST https://api.rymi.live/v1/agents/stack-preview \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "supported_languages": ["hi-IN", "en-US"]
  }'

Response 200

json
{
  "language": "hi-IN",
  "supported_languages": ["hi-IN", "en-US"],
  "provider_config": { "mode": "pipeline", "stt": { }, "llm": { }, "tts": { } },
  "blockers": [],
  "warnings": []
}

provider_config is the resolved flat stack. If a language can't be served, it appears in blockers. Non-fatal notes (e.g. a fallback substitution) appear in warnings.


Enrich Company ​

POST /v1/agents/enrich-company

Generates a company description from a website URL, grounded in Google Search results. Drop the result into an agent's persona.

Body

FieldTypeDescription
companyNamestringCompany name
websiteUrlstringCompany website URL

Example

bash
curl -X POST https://api.rymi.live/v1/agents/enrich-company \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"companyName": "Acme Corp", "websiteUrl": "https://acme.example.com"}'

Response

This endpoint always returns 200. Use the enriched boolean to discriminate success from failure rather than the HTTP status. On success:

json
{
  "enriched": true,
  "companyDescription": "Acme Corp is a leading provider of...",
  "knowledgeBase": []
}

When the lookup cannot be completed, enriched is false and an error string explains why (the call still returns 200):

json
{
  "enriched": false,
  "error": "Could not look up company details. You can describe your business manually."
}

Additional Endpoints ​

These endpoints back the Studio agent builder and SDK/MCP flows. All are prefixed with /v1 and authenticated like the rest of the API.

Catalog & capabilities ​

MethodPathDescription
GET/v1/managed-skusList managed SKUs with their published price_per_min and locked stacks
GET/v1/agents/voicesVoice catalog for agent configuration
GET/v1/agents/:id/tool-capabilitiesThe tool capabilities resolved for a specific agent

Lifecycle ​

MethodPathDescription
POST/v1/agents/:id/publishValidate the persisted config and freeze it into the published snapshot the runtime serves. Reports blockers instead of silently no-op'ing
POST/v1/agents/:id/opt-out-to-customConvert a managed agent to a custom agent, unlocking the stack for manual configuration
POST/v1/agents/:id/apply-managed-skuSwap an agent onto a managed SKU stack in place. Body { managed_sku_id, language }

AI-assisted drafting ​

MethodPathDescription
POST/v1/agents/draftCreate an agent from the full create body (name required; structured config or system_prompt), skipping publish gates. Not prompt-driven, for prompt-driven creation use /v1/agents/generate
POST/v1/agents/draft-fieldGenerate or refine a single agent field
POST/v1/agents/compile-promptCompile a preview of the agent's system prompt from its structured config
POST/v1/agents/chat/answerAnswer a builder-assistant question about agent configuration