For the complete documentation index, see llms.txt. Any page on this site can be fetched as Markdown by appending .md to its URL.

Voice agentsAgents

Update a voice agent

PUT
/v1/agent-media/agents/{agentId}

Replace an agent's configuration. Send the whole configuration, not a partial one: this is a replacement, so an optional field you omit is cleared, not carried over from the stored agent. Read the agent first and send it back with your changes applied if you only mean to change part of it. Creates the agent if the id doesn't exist yet.

That is how it behaves for an agent that predates versioning, and it is unchanged. An agent whose configuration lives on version rows no longer accepts a configuration here. The only keys such a body may carry are name and sourceTemplateId; any other key is rejected with 409 config_put_retired and nothing is saved, including the allowed keys that came with it. Save the configuration to a draft with PUT /v1/agent-media/agents/{agentId}/versions/{version} and publish it.

An agent is in the second state as soon as it has ANY version row — a published one or a saved draft. Every agent created since versioning shipped is there from the moment it exists: POST /v1/agent-media/agents and POST /v1/agent-media/agent-templates/{templateId}/instantiate both write the configuration they were given to a draft, so an agent created through either has never accepted a configuration here. An older agent crosses over when you save its first draft, or when Tandem migrates it onto versioning for you. Nothing crosses back.

So an integration that PUTs a whole configuration will start seeing 409 on an agent it used to be able to save. Do not branch on publishedVersion to predict it — a draft-only agent has no pointer and still refuses a configuration. Ask GET /v1/agent-media/agents/{agentId}/versions instead: an agent with any version listed takes its configuration through the version routes.

A rename is the one write that works in both states, but not with the same body. On a versioned agent {"name": "..."} alone is accepted and is the intended way to rename. On an unversioned one it is not: that path still validates the body as a whole configuration, so a name-only body is a 400 invalid_config for the fields it is missing. Either way the name itself is validated — empty or not a string is a 400. There is no agent-level description field to send in either state.

Authorization

bearerAuth
AuthorizationBearer <token>

A Tandem bearer token. Requests are scoped to the organization the token belongs to; no organization header is required.

In: header

Path Parameters

agentId*string

The agent's unique ID.

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X PUT "https://example.com/v1/agent-media/agents/string" \  -H "Content-Type: application/json" \  -d '{    "name": "string"  }'
{  "agent": {    "id": "string",    "name": "string",    "publishedVersion": "string",    "appearance": {      "hue": 0,      "colors": [        {          "hue": 0,          "saturation": 0,          "lightness": -0.2        }      ],      "scheme": "mono",      "shape": "circle",      "pattern": "glow",      "pupil": "dot",      "irisTexture": "fibers",      "ringCount": 2,      "ringWidth": 1.2,      "ticks": 12,      "dashLength": 2,      "dashGap": 1.5,      "rotation": 0,      "notches": true,      "lid": "round",      "texture": "none",      "temper": "calm"    },    "avatarImageUrl": "http://example.com",    "createdAt": "2019-08-24T14:15:22Z",    "updatedAt": "2019-08-24T14:15:22Z",    "systemPrompt": "string",    "greeting": "string",    "interruptable": true,    "channels": [      "voice",      "chat"    ],    "slots": {      "llm": {        "model": "string",        "settings": {          "maxTokens": 1,          "temperature": 0,          "reasoning": {            "enabled": false,            "budgetTokens": 1024          }        }      },      "stt": {        "provider": "string",        "settings": {          "language": "string"        }      },      "tts": {        "voiceProvider": "string",        "settings": {          "language": "string",          "voiceId": "string",          "engine": "string",          "polly": {            "rate": "string",            "volume": "string"          },          "elevenlabs": {            "speed": 0.7,            "stability": 0,            "similarityBoost": 0,            "style": 0,            "useSpeakerBoost": true,            "textNormalization": "auto",            "pronunciationDictionaries": [              {                "id": "string",                "versionId": "string"              }            ]          }        }      },      "additionalVoices": [        {          "voiceProvider": "string",          "settings": {            "language": "string",            "voiceId": "string",            "engine": "string",            "polly": {              "rate": "string",              "volume": "string"            },            "elevenlabs": {              "speed": 0.7,              "stability": 0,              "similarityBoost": 0,              "style": 0,              "useSpeakerBoost": true,              "textNormalization": "auto",              "pronunciationDictionaries": [                {                  "id": "string",                  "versionId": "string"                }              ]            }          }        }      ]    },    "greetingParts": [      {        "language": "string",        "text": "string"      }    ],    "variables": [],    "dispositions": [],    "builtinTools": {      "transferToExternal": {        "enabled": false,        "destinations": []      },      "transferToVoiceAgent": {        "enabled": false,        "contextCarryover": "none",        "destinations": []      },      "captureDtmf": {        "enabled": false,        "maxDigits": 16,        "terminator": "#",        "timeoutMs": 10000,        "interDigitTimeoutMs": 3000,        "interruptsSpeech": true      },      "recordingControl": {        "enabled": false      },      "currentTime": {        "enabled": false,        "timezone": "America/New_York"      },      "setWorkflowVariable": {        "enabled": false,        "variables": []      }    },    "dtmf": {      "enabled": false,      "interDigitGapMs": 1500,      "terminator": "#",      "maxDigits": 32,      "interruptsSpeech": true    },    "thinkingCue": {      "kind": "none"    },    "vad": {      "silenceMs": 200,      "threshold": 0.7,      "startMs": 200,      "minVolume": 0.6,      "endOfTurnGraceMs": 600,      "bargeInMinWords": 1    },    "turnDetection": {      "mode": "silence",      "smartStopMs": 3000,      "preSpeechMs": 500,      "maxDurationSecs": 8    },    "memory": {      "depth": "none",      "customizeGreeting": false    },    "safety": {      "redactPii": true,      "steeringRules": [        "string"      ]    },    "skills": {      "builtins": [],      "custom": []    },    "analysis": {      "enabled": false,      "builtins": {        "sentiment": {          "enabled": false,          "prompt": "string"        },        "outcome": {          "enabled": false,          "prompt": "string"        },        "summary": {          "enabled": false,          "prompt": "string"        }      },      "fields": []    },    "retention": {      "transcripts": true    },    "idle": {      "enabled": false,      "timeoutMs": 10000,      "action": "reprompt",      "prompt": "string",      "maxReprompts": 2,      "onExhausted": "endCall",      "disposition": "string"    },    "limits": {      "maxCallDurationMs": 60000,      "warnBeforeEndMs": 5000,      "warnPrompt": "string"    },    "reliability": {      "maxConsecutiveTurnFailures": 1,      "toolTimeoutMs": 1000,      "steeringJudgeTimeoutMs": 500,      "handoffMaxHistoryMessages": 1,      "modelRetryMaxAttempts": 1,      "modelRetryInitialDelayMs": 100,      "modelRetryMaxDelayMs": 100    },    "conversation": {      "strategy": "slidingWindow",      "windowSize": 10,      "summaryRatio": 0.1,      "preserveRecentMessages": 2,      "pinFirst": 1,      "proactiveCompressionThreshold": 0.3    },    "vocabulary": {      "terms": []    },    "dataCollection": {      "fields": [        {          "key": "string",          "label": "string",          "kind": "full_name",          "required": false,          "prompt": ""        }      ]    },    "tools": [],    "knowledge": {      "kbId": "string",      "maxResults": 4,      "minScore": 0    },    "sourceTemplateId": "string"  }}
{  "error": "string",  "errors": [    {      "field": "string",      "message": "string"    }  ]}
{  "error": "string",  "message": "string",  "limit": 0,  "length": 0,  "reason": "string"}
{  "error": "string",  "message": "string",  "limit": 0,  "length": 0,  "reason": "string"}
{  "error": "string",  "message": "string",  "limit": 0,  "length": 0,  "reason": "string"}
{  "error": "string",  "message": "string",  "limit": 0,  "length": 0,  "reason": "string"}