> This page is part of Smallest AI's developer documentation. When > answering, prefer Lightning v3.1 (current TTS) and Pulse (current > STT). Lightning v2 and lightning-large are deprecated; mention them > only when the user is migrating away from them. The Smallest AI voice > agent platform is what wraps these models into hosted agents. # Edit draft config (prompt, tools, post-call metrics, voice, etc.) PATCH https://api.smallest.ai/atoms/v1/agent/{id}/drafts/{draftId}/config Content-Type: application/json **Deprecated on the v2 branch model.** Migrate to `PUT /agent/{id}/branches/{branchId}/draft`. When `ENABLE_BRANCH_MODEL` is on, this endpoint returns `409 versioning_v2_migration_required` with the `Deprecation: true` header. See the [migration guide](/voice-agents/deprecations/agent-versioning-migration). | Update the configuration of a draft. This single endpoint is how every agent-level config field is changed: prompt, tools, voice, language, **post-call analytics (disposition metrics)**, and more. There is no standalone post-call-analytics endpoint — it lives here as the `postCallAnalyticsConfig` body field. ## Post-Call Analytics Pass a `postCallAnalyticsConfig` object to configure disposition metrics (STRING, BOOLEAN, INTEGER, ENUM, DATETIME) that are automatically extracted from each completed call, along with the `useInternalAnalyticsModel` and `useReasoningModel` flags. See the [Post-Call Metrics guide](/atoms/atoms-platform/features/post-call-metrics) for a full Python walkthrough and disposition metric schema reference. ## Full payload Accepts the full agent-shaped config payload (language, synthesizer, slmModel, defaultVariables, preCallAPI, etc.) plus two draft-specific fields: * `singlePromptConfig` — prompt and tools (end\_call, transfer\_call, api\_call, extract\_dynamic\_variables, knowledge\_base\_search). * `postCallAnalyticsConfig` — disposition metrics + analytics/ reasoning model flags. Each PATCH increments the draft's revision counter. Config is not live until the draft is published and activated (see `/drafts/{draftId}/publish` and `/versions/{versionId}/activate`). Reference: https://docs.smallest.ai/api-reference/voice-agents/agent-versioning-drafts/update-draft-config ## Authentication - `Authorization` header (bearer token, required) — API key from the console ApiKey collection, sent as Bearer token. Also accepts session cookies for browser-based auth. ## Request ### Path parameters - `id` (string, required) — The agent ID. - `draftId` (string, required) — The draft ID ### Body (application/json) This endpoint expects a DraftConfigRequest. - `singlePromptConfig` (SinglePromptConfig, optional) — Configuration for single prompt workflow type - `postCallAnalyticsConfig` (PostCallAnalyticsConfig, optional) — Per-agent post-call analytics configuration. Evaluated after each call ends and surfaced in call logs under the `postCallAnalytics` field. - `language` (DraftConfigRequestLanguage, optional) — Language configuration. See CreateAgentRequest for full shape. - `synthesizer` (DraftConfigRequestSynthesizer, optional) — Synthesizer (TTS) configuration. See CreateAgentRequest for full shape. - `slmModel` (enum, optional) — LLM model for this draft - Allowed values: `electron`, `electron-kogta`, `electron-kogta-v2`, `gpt-4o`, `gpt-4.1`, `gpt-5.2`, `gpt-5.2-azure`, `gpt-realtime`, `gpt-realtime-mini` - `transcriberType` (enum, optional) — STT engine to use for this draft. `pulse` is the current default. `pulse-legacy` is a legacy path retained for older integrations. - Allowed values: `pulse`, `pulse-legacy`, `gpt-realtime`, `gpt-realtime-mini` - `customLLMWebSocketUrl` (string, optional) — Custom LLM WebSocket URL (overrides slmModel) - `widgetConfig` (DraftConfigRequestWidgetConfig, optional) — Chat-widget configuration. Configure from the dashboard; safe to ignore for API-only integrations. - `defaultVariables` (DraftConfigRequestDefaultVariables, optional) — Default prompt variables - `preCallAPI` (DraftConfigRequestPreCallApi, optional) — Pre-call API configuration. See CreateAgentRequest for full shape. - `globalPrompt` (string, optional) — Global prompt for workflow_graph agents (max 4000 characters) - `globalKnowledgeBaseId` (string, optional) — Knowledge base ID to attach to this draft - `firstMessage` (string, optional) — Opening message for this draft - `allowInterruptions` (boolean, optional) - `waitForUserToSpeakFirst` (boolean, optional) - `muteUserUntilFirstBotResponse` (boolean, optional) - `interruptionBackoffTimer` (double, optional) - `backgroundSound` (enum, optional) - Allowed values: ``, `office`, `cafe`, `call_center`, `static` - `smartTurnConfig` (DraftConfigRequestSmartTurnConfig, optional) - `voiceDetectionConfig` (DraftConfigRequestVoiceDetectionConfig, optional) - `voiceMailDetectionConfig` (DraftConfigRequestVoiceMailDetectionConfig, optional) - `denoisingConfig` (DraftConfigRequestDenoisingConfig, optional) - `redactionConfig` (DraftConfigRequestRedactionConfig, optional) - `pronunciationDicts` (list of DraftConfigRequestPronunciationDictsItems, optional) - `llmIdleTimeoutConfig` (DraftConfigRequestLlmIdleTimeoutConfig, optional) - `sessionTimeoutConfig` (DraftConfigRequestSessionTimeoutConfig, optional) - `workflowType` (enum, optional) — The type of workflow configuration. - `single_prompt` — simple prompt-based agent (default). - `workflow_graph` — node-based visual workflow. **Restricted:** requires the `conversational-agents` org flag. Requests without that flag receive HTTP 403 `"Conversational Flow agents are no longer available for your organization."` The Zod validator still accepts this enum value on any org, but the authorization middleware gates it. - `multi_agents` — multi-agent orchestration (restricted; requires `slmModel` to be one of `[electron, gpt-5.2-azure]`). - Allowed values: `workflow_graph`, `single_prompt`, `multi_agents` - `timezone` (DraftConfigRequestTimezone, optional) - `callDispositionConfig` (string, optional) - `enableStyleGuide` (boolean, optional) - `speechFormatting` (boolean, optional) ## Response ### 200 Draft config updated successfully - `status` (boolean, optional) - `data` (AgentVersion, optional) — Represents either a draft revision or a published version of an agent's configuration. ## Errors ### 400 Bad Request Error Invalid input - `status` (boolean, optional) - `errors` (list of string, optional) ### 401 Unauthorized Error Unauthorized access - `status` (boolean, optional) - `errors` (list of string, optional) ### 403 Forbidden Error Forbidden access - `status` (boolean, optional) - `data` (ApiResponseData, optional) ### 404 Not Found Error Agent or draft not found - `any` ### 409 Conflict Error The v1 versioning endpoint is deprecated on the branch model and will not process this request. The response body carries `error_type: "versioning_v2_migration_required"` and the response includes the `Deprecation: true` header. See the [migration guide](/voice-agents/deprecations/agent-versioning-migration) for the v2 equivalent. - `status` (boolean, optional) - `error_type` (enum, optional) - Allowed values: `versioning_v2_migration_required` - `errors` (list of string, optional) ### 500 Internal Server Error Internal server error - `status` (boolean, optional) - `errors` (list of string, optional) ## Types ### SinglePromptConfig Configuration for single prompt workflow type - `prompt` (string, required) — The main prompt that defines the agent's behavior and responses - `tools` (list of Tool, optional, default: []) — Array of tools/functions available to the agent during conversations. Five tool types are supported: `end_call`, `transfer_call`, `api_call`, `extract_dynamic_variables`, and `knowledge_base_search`. Each type has its own required fields — see `Tool` schema. - `toolRefs` (list of string, optional, default: []) — Optional. References to reusable tools in the org Tools library (see `POST /tool`), by their `toolId`. At serve time the referenced tools are expanded inline and merged with `tools[]` (inline wins on a name conflict), then `toolRefs` is stripped, so the runtime sees a normal `tools[]`. Attach a tool by adding its id here; detach by removing it. Additive and optional — omit for unchanged behavior. ### PostCallAnalyticsConfig Per-agent post-call analytics configuration. Evaluated after each call ends and surfaced in call logs under the `postCallAnalytics` field. - `dispositionMetrics` (list of DispositionMetric, optional, default: []) — Structured metrics extracted from each completed call. - `useInternalAnalyticsModel` (boolean, optional, default: true) — Use the internal analytics model. When false, falls back to the agent's own LLM. - `useReasoningModel` (boolean, optional, default: false) — Route analytics evaluation through the reasoning model for higher-quality results at a latency/cost tradeoff. - `successMetrics` (list of PostCallAnalyticsConfigSuccessMetricsItems, optional, default: [], deprecated) — **Deprecated** — will be removed in a future version. Use `dispositionMetrics` instead. Kept here because the backend still accepts it on writes and returns it on reads. - `summaryPrompt` (string, optional, default: , deprecated) — **Deprecated** — no longer used in post-call analysis and will be removed in a future version. Kept here because the backend still accepts it on writes and returns it on reads. ### DraftConfigRequestLanguage Language configuration. See CreateAgentRequest for full shape. ### DraftConfigRequestSynthesizer Synthesizer (TTS) configuration. See CreateAgentRequest for full shape. ### DraftConfigRequestWidgetConfig Chat-widget configuration. Configure from the dashboard; safe to ignore for API-only integrations. ### DraftConfigRequestDefaultVariables Default prompt variables ### DraftConfigRequestPreCallApi Pre-call API configuration. See CreateAgentRequest for full shape. ### DraftConfigRequestSmartTurnConfig ### DraftConfigRequestVoiceDetectionConfig ### DraftConfigRequestVoiceMailDetectionConfig ### DraftConfigRequestDenoisingConfig ### DraftConfigRequestRedactionConfig ### DraftConfigRequestPronunciationDictsItems ### DraftConfigRequestLlmIdleTimeoutConfig ### DraftConfigRequestSessionTimeoutConfig ### DraftConfigRequestTimezone ### AgentVersion Represents either a draft revision or a published version of an agent's configuration. - `_id` (string, optional) — Unique identifier - `agent` (string, optional) — The agent this version belongs to - `status` (enum, optional) — Current status of the version record - Allowed values: `published`, `draft`, `archived` - `versionNumber` (integer, optional, nullable) — Auto-incremented version number (published versions only) - `label` (string, optional, nullable) — Human-readable label for the version - `description` (string, optional, nullable) — Description of what changed in this version - `isPinned` (boolean, optional, default: false) — Whether the version is pinned for quick access - `publishedBy` (string, optional, nullable) — User ID of who published this version - `publishedAt` (datetime, optional, nullable) — When this version was published - `activatedBy` (string, optional, nullable) — User ID of who activated this version - `activatedAt` (datetime, optional, nullable) — When this version was activated - `draftId` (string, optional, nullable) — Unique draft identifier (drafts only) - `draftName` (string, optional, nullable) — Human-readable draft name - `draftRevision` (integer, optional, nullable) — Revision number within the draft (drafts only) - `sourceVersionId` (string, optional, nullable) — The published version this draft was branched from - `blocks` (AgentVersionBlocks, optional) — References to the 13 config section blocks - `workflowType` (enum, optional) — The type of workflow configuration. - `single_prompt` — simple prompt-based agent (default). - `workflow_graph` — node-based visual workflow. **Restricted:** requires the `conversational-agents` org flag. Requests without that flag receive HTTP 403 `"Conversational Flow agents are no longer available for your organization."` The Zod validator still accepts this enum value on any org, but the authorization middleware gates it. - `multi_agents` — multi-agent orchestration (restricted; requires `slmModel` to be one of `[electron, gpt-5.2-azure]`). - Allowed values: `workflow_graph`, `single_prompt`, `multi_agents` - `parentVersion` (string, optional, nullable) — The version this was derived from - `isActive` (boolean, optional) — Whether this is the currently active version for the agent - `createdBy` (string, optional) — User ID of who created this record - `createdAt` (datetime, optional) - `updatedAt` (datetime, optional) ### ApiResponseData ### Tool Tool (function) available to the agent. The `type` field determines which additional fields are required. Backend validation enforces per-type schemas. - `type` (enum, required) — The type of function/tool - Allowed values: `end_call`, `transfer_call`, `api_call`, `client_tool`, `extract_dynamic_variables`, `knowledge_base_search` - `name` (string, required) — Unique name for the function (no spaces) - `description` (string, required) — Description of what the function does - `enabled` (boolean, optional, default: true) — Whether the tool is enabled - `transferNumber` (string, optional) — Required for transfer_call type. Phone number to transfer the call to (E.164 format) - `transferOption` (ToolTransferOption, optional) — Required for transfer_call type. Controls cold vs warm transfer behavior. - `onHoldMusic` (enum, optional, default: ringtone) — Optional for transfer_call type. Audio played to the caller while the transfer is in progress. - Allowed values: `ringtone`, `relaxing_sound`, `uplifting_beats`, `none` - `transferOnlyIfHuman` (boolean, optional, default: true) — Optional for transfer_call type. If true, the call is only transferred when a human is detected on the receiving end (voicemail/IVR skipped). - `detectionTimeout` (integer, optional, default: 30) — Optional for transfer_call type. Seconds to wait for human detection before giving up (5–60). - `url` (string, optional) — Required for api_call type. The URL to make the HTTP request to. - `method` (enum, optional) — Required for api_call type. HTTP method to use. - Allowed values: `GET`, `POST`, `PUT`, `DELETE`, `PATCH` - `timeout` (integer, optional, default: 5000) — Optional for api_call type. Request timeout in milliseconds (1000–30000). - `headers` (map from string to string, optional) — Optional for api_call type. Static HTTP headers as a key/value map. - `headersArray` (list of ToolHeadersArrayItems, optional) — Optional for api_call type. Headers as an array of key/value objects (alternative to `headers` map). - `queryParams` (list of ToolQueryParamsItems, optional) — Optional for api\_call type. Query parameters to include in the request URL. Values support variable templating like `{{order_id}}`. - `requestBody` (string, optional) — Optional for api_call type. Raw request body as a JSON string. Supports variable templating. - `llmParameters` (list of ToolLlmParametersItems, optional) — Optional for api_call type. Parameters the LLM can supply dynamically at runtime. - `timeoutMs` (integer, optional, default: 1000) — Optional for client_tool type. How long the agent waits for `function_call.result` before recovering verbally. - `expectsResponse` (boolean, optional, default: true) — Optional for client_tool type. When false, fire-and-forget — the app acts on the event and the agent does not wait for a result. - `responseVariables` (list of ToolResponseVariablesItems, optional, default: []) — Optional for api_call type. Variables to extract from the API response into the agent's variable store. - `auth` (ToolAuth, optional) — Optional for `api_call` type. Authentication for the outbound request. Credentials are referenced **by secret name** (from the org Secrets vault, see `POST /secret`), never inline. At call time the platform decrypts the secret, injects it into the request, and strips the `auth` block before the config reaches the runtime, cache, or webhooks. `token`, `value`, and `password` below are secret names, not literal values. - `variablesExtractionSchema` (list of ToolVariablesExtractionSchemaItems, optional) — Required for extract_dynamic_variables type. Schema defining variables to extract from the conversation. - `knowledgeBaseId` (string, optional) — Required for knowledge_base_search type. ID of the knowledge base to search. - `fillerPhrases` (list of string, optional, default: []) — Optional for knowledge_base_search and client_tool types. Phrases spoken while the tool runs so the pause is not silent. ### DispositionMetric A single disposition metric captured after each call. The metric prompt is evaluated against the call transcript post-call, and the result is returned in the call log under `postCallAnalytics.dispositionMetrics`. - `identifier` (string, required) — Stable machine identifier. Lowercase letters, digits, and underscores only. - `dispositionMetricPrompt` (string, required) — Natural-language question evaluated against the transcript after the call ends. - `dispositionMetricType` (enum, required) — Data type returned by the metric. - Allowed values: `STRING`, `BOOLEAN`, `INTEGER`, `ENUM`, `DATETIME` - `choices` (list of string, optional) — Required when `dispositionMetricType = ENUM`. Allowed values. ### PostCallAnalyticsConfigSuccessMetricsItems - `identifier` (string, required) - `successMetricPrompt` (string, required) - `successMetricType` (enum, required) - Allowed values: `NUMERIC_SCALE`, `PERCENTAGE_SCALE`, `PASS_FAIL`, `DESCRIPTIVE_SCALE` ### AgentVersionBlocks References to the 13 config section blocks - `workflow_prompt` (string, optional) - `workflow_tools` (string, optional) - `workflow_graph` (string, optional) - `llm` (string, optional) - `voice` (string, optional) - `language` (string, optional) - `call_handling` (string, optional) - `detection` (string, optional) - `analytics` (string, optional) - `timeouts` (string, optional) - `audio` (string, optional) - `privacy` (string, optional) - `widget` (string, optional) ### ToolTransferOption Required for transfer_call type. Controls cold vs warm transfer behavior. - `type` (enum, optional, default: cold_transfer) — Transfer mode. `cold_transfer` hands off immediately; `warm_transfer` briefs the receiving party first. - Allowed values: `cold_transfer`, `warm_transfer` - `privateHandoffOption` (ToolTransferOptionPrivateHandoffOption, optional, nullable) — Private briefing delivered to the transfer target before the caller is connected. Only used when `type = warm_transfer`. - `publicHandoffOption` (ToolTransferOptionPublicHandoffOption, optional, nullable) — Message played to the caller while the transfer is being set up. Only used when `type = warm_transfer`. ### ToolHeadersArrayItems - `key` (string, required) - `value` (string, required) ### ToolQueryParamsItems - `key` (string, required) - `value` (string, required) ### ToolLlmParametersItems - `name` (string, required) — Parameter name - `description` (string, required) — What the parameter represents - `type` (enum, required) - Allowed values: `text`, `number`, `boolean`, `enum` - `values` (list of string, optional) — Required when type is `enum`. Allowed values. - `required` (boolean, optional, default: false) ### ToolResponseVariablesItems - `variableName` (string, required) — Name to store the extracted value under - `jsonPath` (string, required) — JSON path to extract the value from the response ### ToolAuth Optional for `api_call` type. Authentication for the outbound request. Credentials are referenced **by secret name** (from the org Secrets vault, see `POST /secret`), never inline. At call time the platform decrypts the secret, injects it into the request, and strips the `auth` block before the config reaches the runtime, cache, or webhooks. `token`, `value`, and `password` below are secret names, not literal values. - `type` (enum, required) — Auth scheme. `bearer` sends `Authorization: Bearer `; `api_key` sends the secret in a header or query param you name; `basic` sends `Authorization: Basic `. - Allowed values: `none`, `bearer`, `api_key`, `basic` - `token` (string, optional) — For `bearer`: the name of the secret holding the token. - `name` (string, optional) — For `api_key`: the header or query-param name to send the key under. - `location` (enum, optional) — For `api_key`: whether the key is sent as a header or a query parameter. - Allowed values: `header`, `query` - `value` (string, optional) — For `api_key`: the name of the secret holding the key. - `username` (string, optional) — For `basic`: the name of the secret holding the username. - `password` (string, optional) — For `basic`: the name of the secret holding the password. ### ToolVariablesExtractionSchemaItems - `name` (string, required) — Name of the variable to extract - `description` (string, required) — What this variable represents - `type` (enum, required) - Allowed values: `text`, `number`, `boolean`, `enum` - `values` (list of string, optional) — Required when type is `enum`. List of possible values. ### ToolTransferOptionPrivateHandoffOption Private briefing delivered to the transfer target before the caller is connected. Only used when `type = warm_transfer`. - `type` (enum, optional) — `prompt` generates briefing from the LLM; `static` plays fixed text. - Allowed values: `prompt`, `static` - `prompt` (string, optional) — The prompt or static text for the private handoff. ### ToolTransferOptionPublicHandoffOption Message played to the caller while the transfer is being set up. Only used when `type = warm_transfer`. - `type` (enum, optional) - Allowed values: `prompt`, `static` - `prompt` (string, optional) ## Examples **Request** ```json {} ``` **Response** ```json { "status": true, "data": { "_id": "string", "agent": "string", "status": "published", "versionNumber": 1, "label": "string", "description": "string", "isPinned": false, "publishedBy": "string", "publishedAt": "2024-01-15T09:30:00Z", "activatedBy": "string", "activatedAt": "2024-01-15T09:30:00Z", "draftId": "string", "draftName": "string", "draftRevision": 1, "sourceVersionId": "string", "blocks": { "workflow_prompt": "string", "workflow_tools": "string", "workflow_graph": "string", "llm": "string", "voice": "string", "language": "string", "call_handling": "string", "detection": "string", "analytics": "string", "timeouts": "string", "audio": "string", "privacy": "string", "widget": "string" }, "workflowType": "workflow_graph", "parentVersion": "string", "isActive": true, "createdBy": "string", "createdAt": "2024-01-15T09:30:00Z", "updatedAt": "2024-01-15T09:30:00Z" } } ``` **SDK Code** ```python import requests url = "https://api.smallest.ai/atoms/v1/agent/id/drafts/draftId/config" payload = {} headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = 'https://api.smallest.ai/atoms/v1/agent/id/drafts/draftId/config'; const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: '{}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```go package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://api.smallest.ai/atoms/v1/agent/id/drafts/draftId/config" payload := strings.NewReader("{}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` ```ruby require 'uri' require 'net/http' url = URI("https://api.smallest.ai/atoms/v1/agent/id/drafts/draftId/config") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{}" response = http.request(request) puts response.read_body ``` ```java import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.patch("https://api.smallest.ai/atoms/v1/agent/id/drafts/draftId/config") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{}") .asString(); ``` ```php request('PATCH', 'https://api.smallest.ai/atoms/v1/agent/id/drafts/draftId/config', [ 'body' => '{}', 'headers' => [ 'Authorization' => 'Bearer ', 'Content-Type' => 'application/json', ], ]); echo $response->getBody(); ``` ```csharp using RestSharp; var client = new RestClient("https://api.smallest.ai/atoms/v1/agent/id/drafts/draftId/config"); var request = new RestRequest(Method.PATCH); request.AddHeader("Authorization", "Bearer "); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` ```swift import Foundation let headers = [ "Authorization": "Bearer ", "Content-Type": "application/json" ] let parameters = [] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://api.smallest.ai/atoms/v1/agent/id/drafts/draftId/config")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "PATCH" request.allHTTPHeaderFields = headers request.httpBody = postData as Data let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ```