Three identifiers with different jobs
For example,
support-agent can receive calls from both support-2026-09-a
and support-2026-09-b. Keep agent.externalId the same for both. Giving each
release a different agent ID creates separate agents that cannot be selected
as the two versions of one experiment.
Declare versions in LiveKit or a custom integration
Send the top-levelversion field on every upload to
POST https://ingest.zelto.ai/webhooks/calls. The wire field is version,
not prompt_version, agent.version, or metadata.version.
The API accepts a string of 1–255 characters after trimming surrounding
whitespace. Labels are case-sensitive: release-a and Release-A are
different. A release tag, immutable build ID, or hash of your complete versioned
configuration works. A prompt-only hash cannot distinguish pipeline-only changes.
Authorization: Bearer $ZELTO_API_KEY, Content-Type: application/json,
and X-Zelto-Provider: livekit for a LiveKit worker, or zelto for custom
uploads. See the LiveKit example
and call-upload contract.
You can register a version before sending calls (see below). Otherwise, the first
processed call with a new label creates the declared version;
later calls with the same agent and label reuse it. A separate version-creation
request is optional. Zelto also assigns a display number such as v1 or
v2 in first-seen order. That number is separate from your label; send your
release label, not a display number inferred from the dashboard.
version is optional for general call ingestion. For integrations intended to
run experiments, send an explicit version on every call so attribution follows
the release that handled it.Keep a label tied to one release
- Change the label for prompt, model, voice, transcription, tool, or workflow changes that should form a distinct version.
- Keep it stable across calls on that release. Do not use a room ID, customer ID, per-call timestamp, or random UUID as the version label.
- Capture the label and configuration from the session that handled the call. A deployment can happen while a call is running; do not label a delayed upload using whichever release is current at upload time.
- On retry, resend the original call ID, version, and snapshots. Do not relabel old calls to make them join a different experiment arm.
- For a rollback to an unchanged release, reuse that release’s label. If you need to distinguish two deployments of identical code, use separate release labels consistently.
Register a version in Zelto
Organization owners and admins can open Agents → your agent → Versions → Register version. Enter the release label, optional system prompt, and the LLM, STT, and TTS providers/models. TTS also has a voice ID field. Expand Additional configuration (JSON) to record tools, workflows, knowledge bases, runtime settings, or any custom context. Extra settings such asllm.temperature can go here; the provider/model fields above take precedence
when both specify the same key. Registration records context; it does not deploy
or run this configuration. Draft prompt candidates remain separate.
Register a version through the API
Use an organization API key owned by an owner or admin. The agent must already exist in that organization. On the platform API host, callPOST /v1/agents/{id}/versions, using the Zelto agent UUID:
version.json
201 with { "id": "<version UUID>", "created": true }. Retrying with the same label and configuration returns
HTTP 200 with created: false. A supplied prompt or configuration that differs
from an existing version returns 409 Conflict: create a new release label
instead of rewriting history. Omitted fields on a retry leave existing values
alone. Internal prefixes draft: and generated: are reserved.
The call-upload endpoint remains on https://ingest.zelto.ai/webhooks/calls.
Registering a release does not make it the fallback for unversioned calls. It becomes observed when a processed call explicitly reports its label.
Registration uses config; call upload uses versionConfig alongside
version. Both write the same version configuration. After registration,
report that label on each call. Do not substitute the returned UUID or Zelto’s
display number for your release label.
Version identity and configuration are separate
version assigns calls to a release. The configuration is context supplied by
your organization: it can describe everything that release uses, including
provider/model choices, voice, tools, retrieval, workflow, deployment settings,
and custom components. All supplied JSON fields are preserved and available in
the version detail and comparison, including experiment setup.
Supply a JSON object, up to 64 KiB when serialized as UTF-8. The keys
llm, stt, and tts are conventions matching the form, not a closed list.
Other keys and nested objects/arrays are supported. Include configuration,
not API keys or other credentials. This is descriptive context; Zelto does not
execute workflows, configure providers, or discover missing settings for you.
Send the actual prompt as systemPrompt, or in a leading system transcript
turn for call uploads. A version label alone does not supply a prompt.
A first call can create the version with versionConfig. Existing snapshots
are not replaced by later call uploads; a missing snapshot can be filled. Send
complete configuration from the start, and register a new label when it changes.
A configuration already captured from legacy call metadata is also an existing
snapshot: later uploads do not merge a new versionConfig into it.
For older versions without explicitly supplied configuration, Zelto shows only
the captured model, transcription, and voice settings from call metadata.
Missing snapshots are unavailable, not evidence of identical pipelines. Full
workflow and tool context is available when your integration or the form supplies
it; it is not collected automatically.
Provider-managed and automatic versions
For LiveKit/custom calls with no explicit
version, Zelto creates an initial
generated version if necessary, then assigns subsequent calls to the latest
deployed version. A weekly job can create another generated version when the
generalized prompt changes. It does not detect pipeline-only changes, and
it does not immediately distinguish two releases running concurrently. Use
explicit labels for experiments.
A draft candidate created in Zelto is for simulations. It has not handled
real calls and cannot be selected as an experiment arm. Deploy the release in
your own stack and upload calls with its version label to make it available.
Verify before launching an experiment
- Send a call from release A and another from release B with the same agent ID, distinct call IDs, and distinct version labels.
- Wait for processing. HTTP
200with{ "received": true }acknowledges acceptance; it does not mean the call and version are already visible. - Open the agent’s Versions tab. Confirm both labels and inspect which calls belong to each. Check prompt/configuration snapshots where available.
- Open Experiments → New experiment and select that agent and those two versions. Review the captured differences and recent call counts.
- Choose configured monitors and use Check recent traffic. Historical traffic checks the setup; it does not backfill the new experiment’s results.
- Enter a name and launch. Keep reporting the actual version on each future
call and route callers consistently in your own platform. Send a stable
endUserIdwhere available for caller-level analysis.

