How do I list, inspect and load a VARTA agent?
An agent is what you built in the VARTA studio: a language model, a speech recogniser,
a speech synthesiser, a voice and a conversation flow, bundled under one id. GET /v1/agents and GET /v1/agents/{agent_id} read that configuration back; POST /v1/agents/{agent_id}/load is where a conversation actually begins — it opens a
session and returns the opening line with its audio already synthesised, so your
code never assembles a pipeline or a greeting itself.
Tenant isolation on this page applies in enforce mode. The scoping described below — "visible to your tenant", and an id belonging to another tenant reported as
not_found— is enforced only when the instance runs withauth_mode: "enforce". On a default instance that setting is"audit"(backend/app/core/config.py:26), and in audit moderequire_tenantreturns the resource without comparing tenants at all (backend/app/security/ownership.py:51-52). Object-level isolation is then observed but not enforced: becauseGET /v1/agentsfilters purely on that check (backend/app/api/v1/agents.py:90-102), on a default instance it lists every tenant's agents, not just yours. See Authentication.
List agents
GET /v1/agentsReturns every agent visible to your tenant, sorted by id.
curl "$VARTA_BASE_URL/agents" \
-H "Authorization: Bearer $VARTA_API_KEY"{
"data": [
{
"id": "ag_412",
"name": "Collections — Hindi",
"language": "hi",
"voice_id": "voice_7a1",
"agent_name": "Priya",
"agent_gender": "female",
"llm": { "provider": "openai", "model": "gpt-4o-mini", "source": "agent" },
"stt": { "provider": null, "source": "deployment_default" },
"tts": { "provider": "elevenlabs", "voice_id": "voice_7a1", "source": "agent" },
"steps": 9
}
],
"has_more": false,
"next_cursor": null
}llm, stt and tts each carry a source: "agent" when the agent overrides that
provider, "deployment_default" when it falls back to whatever this deployment runs
by default. A null provider with source: "deployment_default" is normal, not a
misconfiguration — it means the agent doesn't pin one.
has_more and next_cursor are always false / null today: this endpoint does not
yet paginate.
Errors: none specific to this request.
Get an agent
GET /v1/agents/{agent_id}curl "$VARTA_BASE_URL/agents/ag_412" \
-H "Authorization: Bearer $VARTA_API_KEY"Returns the same shape as one item in the GET /v1/agents list above.
Errors: workflow_not_found when agent_id
isn't a value this API ever issued, not_found when it's a
well-formed id that doesn't exist for your tenant — including one that belongs to
another tenant, which is deliberately reported the same way so a cross-tenant id
can't be distinguished from a missing one.
Load an agent
POST /v1/agents/{agent_id}/loadLoading an agent is one call. It resolves the agent's model, speech recognition, speech synthesis, voice and flow, opens a session, and returns the opening line — already synthesised — along with filler clips and the resolved runtime stack.
curl -X POST "$VARTA_BASE_URL/agents/ag_412/load" \
-H "Authorization: Bearer $VARTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"customer_name": "Rahul", "context": {"order_id": "SO-4821"}}'Every field in the body is optional. context is passed through to the pre-call
context initialiser, so the opening line can already name the caller.
{
"session_id": "se_9021",
"agent_id": "ag_412",
"opening": {
"text": "Namaste Rahul, main Priya baat kar rahi hoon...",
"audio_url": "https://.../opening_9021.mp3",
"clips": [
{
"intent_key": "opening_greeting",
"display_order": 0,
"text": "Namaste Rahul, main Priya baat kar rahi hoon...",
"audio_url": "https://.../opening_9021.mp3",
"livekit_wav_url": null,
"requires_user_input": false
}
]
},
"filler_clips": {},
"behavior_clips": {},
"runtime": {
"agent_name": "Priya",
"language": "hi",
"llm": { "provider": "openai", "model": "gpt-4o-mini", "source": "agent" },
"stt": { "provider": null, "source": "deployment_default" },
"tts": { "provider": "elevenlabs", "voice_id": "voice_7a1", "source": "agent" },
"steps": 9
},
"ended": false
}Hold on to session_id — it's what you send to every endpoint on the
Sessions page next. filler_clips and behavior_clips are
pre-synthesised clips your client can play opportunistically (a filler while waiting
on a turn, a scenario-specific reaction); both are commonly empty objects and that's
not an error, it just means this agent has none configured.
A clip object's documented fields are intent_key, display_order, text,
audio_url, livekit_wav_url and requires_user_input. livekit_wav_url is a
WAV-format rendition of the same clip — the telephony path plays this one — but it is
populated for every caller regardless of channel, not only for SIP calls; it may be
null. The runtime attaches other fields to clips internally (for example
_played) — anything not listed here is implementation detail, not part of the
contract.
Like every state-changing call under /v1, this endpoint honours an
Idempotency-Key header — see Idempotency for the replay
semantics; Calls explains why it matters most for a
call that actually dials.
Errors: invalid_request when the body isn't a
JSON object or context isn't, workflow_not_found
when agent_id is malformed, not_found when it's a
well-formed id this tenant doesn't own.