# Versioning (/docs/agents/voice-agents/versioning)

> For the complete documentation index, see [llms.txt](https://docs.tandemcx.ai/llms.txt). Any page on this site can be fetched as Markdown by appending `.md` to its URL.

<Callout type="info">
    **Agents that already existed move one organization at a time.** Yours are moved in a single
    pass: each agent's current configuration is saved as version `1.0` and published, so nothing
    changes for callers. Until that pass runs, those agents keep answering exactly as they did, but
    the editor shows no version number for them and the agent pickers mark them `not published —
    can't answer calls`. That label is wrong for those agents specifically, and it goes when the
    pass runs. Agents created from now on are versioned from the start.
</Callout>

A voice agent's configuration is stored as numbered **versions**. One of them is **published**,
and that one is the configuration every call to the agent runs. The rest are drafts: saved,
editable, and serving nobody.

## Drafts and the published version

- **Draft** — a saved version that is not live. Edit it, publish it, or delete it. Nothing about
  it reaches a caller.
- **Published version** — the configuration the agent answers with. It can't be overwritten or
  deleted while it's published. You can edit it in the editor, but the edits save as a new draft.

The agent's name isn't versioned: renaming it takes effect when you save, on every version,
including the published one.

Changing a live agent is two steps: save the change as a new draft, then publish that draft.
Publishing points the agent at the new version, and the version it was on becomes an ordinary
draft again: editable, and available to publish if you need to go back.

The published version is resolved when a call connects, so a call already in progress keeps the
configuration it started with. Publishing never changes a conversation part-way through.

## Version numbers

A version number is `major.minor` and you choose it. When you save a new draft, Tandem offers the
next number for you: a **minor** step for an ordinary change, a **major** one for a change you'll
want to find again later. Numbers are ordered numerically rather than alphabetically, so `1.10`
is newer than `1.2`.

Each version can carry a short note saying what changed. It's optional, and it's the only record
of intent the version list has.

An agent holds at most **20 versions**. Saving a 21st is refused, so delete one you no longer
need first. A published version can't be deleted, so publish a different version before removing
the one that's live.

## Publishing

Publishing is the only action that changes what callers get.

It's also the point at which the rules only the server can check run. How much a draft save
checks depends on where the draft comes from. The editor's **Save Configuration** and **Save as
New Draft** both refuse an incomplete draft: a missing system prompt, model, or voice stops the
save with the field's own message, such as "System prompt is required." Over the API, a draft
save checks the shape of what you sent and little else — you can write a draft with no system
prompt and no voice picked, and stop half-way through building one. Publish runs every rule a
live call depends on, whichever way the draft was saved, so a draft written over the API can
surface several problems here at once.

Publish is refused when:

- a required field is empty, or a set of fields required in combination is incomplete
- the agent uses an ElevenLabs voice and the ElevenLabs integration isn't connected for your
  organization
- an [agent tool](/docs/agents/voice-agents/tools#add-an-agent-tool) points at an agent with no
  published version of its own, so the hand-off would reach an agent that can't answer
- the configuration references a [secret](/docs/overview/secrets-and-variables) and you aren't an
  organization admin
- the version you picked is already the published one

Each problem names the field it's about, and several can come back at once. Nothing is saved and
nothing changes for callers until a publish succeeds.

## An agent with nothing published

Creating an agent saves its configuration as version `0.1` and publishes nothing. The editor
opens it editable, and **Save Configuration** keeps revising that same `0.1` draft, so creating an
agent and starting to build it are one step. Publishing is a separate action you take when the
agent is ready to answer.

Every agent therefore begins with nothing published, and stays there until you publish. An agent
in that state can't answer: a call routed to it doesn't connect, and neither does a chat. That
makes attaching it to anything pointless, so Tandem says so at the point of attachment rather
than after:

- Picking an agent in **Phone Numbers** or on a SIP trunk, in a chat widget, as a
  `transfer_to_voice_agent` destination, or as an
  [agent tool](/docs/agents/voice-agents/tools#add-an-agent-tool) target shows it as
  `not published — can't answer calls`, and the option can't be chosen. It stays in the list
  rather than disappearing, so an agent that's already attached doesn't vanish from the picker
  holding it.
- The **AI Voice Agent** workflow node's agent picker says nothing about publish state, and lets
  you pick any agent. That picker is built on the server, from agent records that don't carry the
  published pointer.
- An agent's own **Phone Numbers** card warns when the agent you're editing has nothing published,
  since there's no option to disable there — the agent is fixed and the rows are numbers.

Over the API a draft can still reference an unpublished agent; nothing checks it until you
publish, which is what makes a half-built configuration saveable.

An agent that was already answering calls before your organization moved onto versioning keeps
answering: its existing configuration becomes its published version, with nothing for you to do.

## Testing a draft before you publish

**Call Agent** in the editor places a browser preview call against the configuration on screen,
including edits you haven't saved. It's the way to hear a draft, and it's unaffected by which
version is published. [Preview Calls](/docs/agents/voice-agents/preview-calls) covers what such a
call does and doesn't exercise.

There is no way to route a real phone call to a draft. If you need one, publish the draft on an
agent that isn't in front of customers.

## Limits and defaults

| Setting             | Value                                                      |
| ------------------- | ---------------------------------------------------------- |
| Versions per agent  | 20                                                         |
| Version number      | `major.minor`; each part a whole number, up to nine digits |
| Version note        | Optional; up to 2,000 characters                           |
| Published versions  | Exactly one per agent, or none                             |
| Editing or deleting | Drafts only; the published version is refused              |

## Versioning over the API

Everything above is available over the API. Creating an agent saves its configuration as version
`0.1` and publishes nothing, so an integration that creates an agent has to publish a version
before that agent can answer. See
[List an agent's versions](/docs/api/voice-agents/agent-versions/listAgentVersions) for the
endpoints and
[Publish a version](/docs/api/voice-agents/agent-versions/publishAgentVersion) for the publish
call.

Two consequences matter if you write configurations from your own code.

`PUT /v1/agent-media/agents/{agentId}` stops accepting a configuration once the agent holds any
version at all — a published one or a draft — which, since a create writes a `0.1` draft, means
from the moment the agent exists. The only keys it still takes are `name` and `sourceTemplateId`,
and a body carrying anything else is rejected with `409 config_put_retired` without saving. Write
the configuration to a draft with `PUT /v1/agent-media/agents/{agentId}/versions/{version}` and
publish it.

`POST /v1/agent-media/agents` also no longer overwrites. Supplying an `agentId` that already
exists is rejected with `409 create_upsert_retired`, whatever versions that agent has: a create
writes identity to the agent record and the configuration to a `0.1` draft, so repeating one over
a live agent would take its configuration off the record and publish nothing in its place. Edit
through the version endpoints instead. A create with no `agentId`, or with one that is genuinely
new, is unaffected.

The [changelog entry](/docs/changelog) has the full note.

## Troubleshooting

**The fields are all greyed out.** You're on a published version, which is immutable. Save it as
a new draft to make changes. A draft is editable, so this never happens on an agent you have just
created.

**A version number comes back as already taken.** That number is in use. Pick another, or open
the existing version and edit it.

**Saving a version is refused for the version limit.** The agent already holds 20. Delete one
first; the published version isn't deletable until you publish a different one.

**Publish reports several field errors at once.** The draft was written over the API, where a
save doesn't check completeness the way the editor's Save does, so the first publish is where
they all surface. Fix them and publish again.

**Publish reports that a linked agent has no published version.** The agent tool's target can't
answer. Publish a version of the target agent, then publish this one.

**An agent is marked "not published" in a picker.** It has no published version, so the option
isn't selectable. Publish a version of that agent, then reopen the picker. The one exception is an
agent that predates versioning in an organization the rollout hasn't reached yet: it carries no
published version and is labelled this way, but it is still answering calls.

**Your integration gets `409 config_put_retired`.** That agent's configuration lives on its
version rows, which is true of every agent created since versioning shipped — a `publishedVersion`
of `null` does not mean the old route still works. Write configuration through
`PUT /v1/agent-media/agents/{agentId}/versions/{version}` and keep the agent PUT for `name` and
`sourceTemplateId`.

**Your integration gets `409 create_upsert_retired`.** You posted an `agentId` that already
exists. Creating is no longer a way to overwrite one. Write a draft with
`PUT /v1/agent-media/agents/{agentId}/versions/{version}` and publish it.

## Next steps

<Cards>
    <Card
        title="Getting Started"
        href="/docs/agents/voice-agents/getting-started"
        description="Build a working voice agent and take a call with it."
    />
    <Card
        title="Using an Agent in a Workflow"
        href="/docs/agents/voice-agents/using-in-workflows"
        description="Route on how the call ended."
    />
    <Card
        title="Tools"
        href="/docs/agents/voice-agents/tools"
        description="Let the agent run workflows, call your APIs, and consult other agents."
    />
</Cards>
