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
namestringYesHuman-readable agent name (100 characters or fewer recommended; not enforced by the API)
system_promptstringNoRaw system prompt. If you omit persona and playbook, Rymi can extract structure from this prompt
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 | nullNoSecondary LLM provider used if the primary fails. null clears it
llm_fallback_modelstring | nullNoSecondary LLM model. null clears it
stt_fallback_providerstring | nullNoSecondary STT provider. null clears it
stt_fallback_modelstring | nullNoSecondary STT model. null clears it
tts_fallback_providerstring | nullNoSecondary TTS provider. null clears it
tts_fallback_modelstring | nullNoSecondary TTS model. null clears it
custom_llm_urlstring | nullNoSelf-hosted LLM endpoint (https:// or wss://). Enterprise only; null clears
custom_voice_urlstring | nullNoSelf-hosted TTS endpoint. Enterprise only; null clears
custom_voice_modestringNorymiWire format for custom_voice_url: rymi or openai-compat
custom_transcriber_urlstring | nullNoSelf-hosted STT endpoint. Enterprise only; null clears
personaPersona objectNoStructured role, tone, audience, and voice config
playbookPlaybook objectNoOpener, qualification flow, scripts, CTA, and escalation rules
advancedadvanced objectNoRuntime tuning (endpointing, turn timing)
featuresFeatures objectNoFeature flags (recording, transcription)
post_callPost-call objectNoDefault post-call intelligence config
provider_configobjectNoRead-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.promptstringCustom instructions for the summary LLM (e.g. "highlight objections")
structured_extraction.json_schemaobjectJSON Schema defining the structured data to extract from the transcript
structured_extraction.promptstringCustom instructions for the extraction LLM (auto-generated from schema if omitted)
evaluation.rubricstringNumbered list of quality criteria for call scoring
model.providerstringLLM provider for post-call analysis: gemini or openai. Defaults to platform setting
model.modelstringSpecific 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
promptstringYesNatural-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.voicestringNoPreferred voice ID or name
options.llm_providerstringNoPreferred LLM provider hint
options.llm_modelstringNoPreferred model hint
current_configobjectNoCurrent 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_providerstringSpeech-to-text provider override
stt_modelstringSTT model override
tts_providerstringText-to-speech provider override
tts_modelstringTTS model override
supported_languagesstring[][language]All BCP-47 locales this agent may run
llm_fallback_provider / llm_fallback_modelstring | nullSecondary LLM provider/model; null clears
stt_fallback_provider / stt_fallback_modelstring | nullSecondary STT provider/model; null clears
tts_fallback_provider / tts_fallback_modelstring | nullSecondary TTS provider/model; null clears
custom_llm_url / custom_voice_url / custom_transcriber_urlstring | nullSelf-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
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
startSpeakingThresholdnumberVAD sensitivity for when agent starts speaking
stopSpeakingThresholdnumberVAD sensitivity for when caller stops speaking
resumeAfterInterruptionbooleantrueResume interrupted sentence after caller stops
smartEndpointingbooleantrueAI-powered end-of-turn detection
waitAfterSentencenumberms to wait after a sentence ends
waitAfterNoPunctuationnumberms to wait when no sentence-ending punctuation
waitAfterNumbersnumberms to wait after numbers (they often continue)
stt_confidence_thresholdnumberMinimum confidence to accept a transcription
stt_numeral_formattingbooleantrueFormat numbers as numerals in transcript
stt_profanity_filterbooleanfalseFilter profanity from transcript
stt_keywordsstringComma-separated keywords to boost STT accuracy
offLimitsTopicsstringTopics the agent must never discuss
prohibitedClaimsstringClaims the agent must never make

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.promptstringCustom summary instructions
structured_extraction.json_schemaobjectJSON Schema for data extraction
structured_extraction.promptstringCustom extraction instructions (auto-generated if omitted)
evaluation.rubricstringNumbered scoring criteria
model.providerstringgemini or openai for post-call LLM
model.modelstringModel 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