import {z} from 'zod' export type GetApiGetRetellLlmLlmIdArgs = {llm_id: string, version?: number | undefined}; export type GetApiGetRetellLlmLlmIdOptions = {baseUrl?: string | undefined, apiKey?: string | undefined, fetch?: typeof fetch | undefined}; export const lLMModel = z.enum(["gpt-4.1", "gpt-4.1-mini", "gpt-5", "gpt-5-mini", "gpt-5-nano", "gpt-5.1", "gpt-5.2", "gpt-5.4", "gpt-5.4-mini", "gpt-5.4-nano", "gpt-5.5", "gpt-5.6-terra", "gpt-5.6-luna", "gpt-6-astra", "gpt-6-sol", "gpt-6.1-sol", "gpt-6.1-terra", "gpt-6-luna", "tell-1", "claude-4.6-sonnet", "claude-5-opus", "claude-5.5-opus", "claude-5-sonnet", "claude-5.5-sonnet", "claude-5.5-haiku", "claude-4.5-haiku", "gemini-3.0-flash", "gemini-3.1-flash-lite", "gemini-3.5-flash", "gemini-3.5-flash-lite", "gemini-3.6-flash", "gemini-3.7-flash", "gemini-3.8-flash", "gemini-4-carbon", "gemini-4-argon"]); export const serviceTier = z.enum(["standard", "fast", "ultrafast"]); export const textModelRef = z.object({model: lLMModel, tier: serviceTier.optional()}); export const backupModelRef = z.object({model: lLMModel, tier: serviceTier.optional(), kick_in_timeout_ms: z.number().int().gte(300).lte(60000).optional()}); export const nullableBackupModelRef = z.union([backupModelRef, z.unknown()]); export const modelTemperature = z.number().gte(0).lte(1); export const cascadingModelConfig = z.object({type: z.literal("cascading").optional(), primary: textModelRef.optional(), backup: nullableBackupModelRef.optional(), temperature: modelTemperature.optional()}); export const s2SModel = z.enum(["gpt-realtime-2.1", "gpt-realtime-2.1-mini", "gpt-realtime-2", "gpt-realtime-1.5", "gpt-realtime", "gpt-realtime-mini", "grok-voice-3.0"]); export const s2SModelRef = z.object({model: s2SModel}); export const s2SModelConfig = z.object({type: z.literal("s2s").optional(), primary: s2SModelRef.optional(), temperature: modelTemperature.optional()}); export const duplexModelRef = z.object({model: z.literal("gpt-live-1")}); export const duplexModelConfig = z.object({type: z.literal("duplex").optional(), primary: duplexModelRef.optional(), backend: textModelRef.optional(), backup: nullableBackupModelRef.optional(), temperature: modelTemperature.optional()}); export const modelConfig = z.union([cascadingModelConfig, s2SModelConfig, duplexModelConfig]); export const backupModelChoice = z.object({type: z.literal("cascading"), model: lLMModel, high_priority: z.boolean().optional(), ultrafast: z.boolean().optional(), backup_kick_in_timeout: z.number().int().gte(300).lte(60000).optional()}); export const nullableBackupModelChoice = z.union([backupModelChoice, z.unknown()]); export const nullableLLMModel = z.enum(["gpt-4.1", "gpt-4.1-mini", "gpt-5", "gpt-5-mini", "gpt-5-nano", "gpt-5.1", "gpt-5.2", "gpt-5.4", "gpt-5.4-mini", "gpt-5.4-nano", "gpt-5.5", "gpt-5.6-terra", "gpt-5.6-luna", "gpt-6-astra", "gpt-6-sol", "gpt-6.1-sol", "gpt-6.1-terra", "gpt-6-luna", "tell-1", "claude-4.6-sonnet", "claude-5-opus", "claude-5.5-opus", "claude-5-sonnet", "claude-5.5-sonnet", "claude-5.5-haiku", "claude-4.5-haiku", "gemini-3.0-flash", "gemini-3.1-flash-lite", "gemini-3.5-flash", "gemini-3.5-flash-lite", "gemini-3.6-flash", "gemini-3.7-flash", "gemini-3.8-flash", "gemini-4-carbon", "gemini-4-argon", "null"]).nullable(); export const nullableS2SModel = z.enum(["gpt-realtime-2.1", "gpt-realtime-2.1-mini", "gpt-realtime-2", "gpt-realtime-1.5", "gpt-realtime", "gpt-realtime-mini", "grok-voice-3.0", "null"]).nullable(); export const kBConfig = z.object({top_k: z.number().int().gte(1).lte(10).optional(), filter_score: z.number().gte(0).lte(1).optional()}); export const escalationDestination = z.object({type: z.literal("webhook"), destination: z.object({url: z.string(), method: z.enum(["POST", "PUT"]), timeout_ms: z.number().int().gte(1000).lte(600000).optional(), max_retry: z.number().int().gte(0).lte(5).optional(), headers: z.record(z.string(), z.string()).optional(), query_params: z.record(z.string(), z.string()).optional(), body: z.record(z.string(), z.unknown()).optional()})}); export const escalateChatTool = z.object({type: z.literal("escalate_chat"), name: z.string(), description: z.string().optional(), destination: escalationDestination}); export const endCallTool = z.object({type: z.literal("end_call"), name: z.string(), description: z.string().optional(), custom_sip_headers: z.record(z.string(), z.string()).optional(), speak_during_execution: z.boolean().optional(), execution_message_description: z.string().optional(), execution_message_type: z.enum(["prompt", "static_text"]).optional()}); export const transferDestinationPredefined = z.object({type: z.literal("predefined"), number: z.string(), extension: z.string().optional()}); export const transferDestinationInferred = z.object({type: z.literal("inferred"), prompt: z.string()}); export const transferDestination = z.union([transferDestinationPredefined, transferDestinationInferred]); export const warmTransferPrompt = z.object({type: z.literal("prompt").optional(), prompt: z.string().optional()}); export const agentVersionReference = z.union([z.string().min(1).max(20), z.number().int().gte(0)]); export const transferOption = z.union([z.object({type: z.literal("cold_transfer"), show_transferee_as_caller: z.boolean().optional(), cold_transfer_mode: z.enum(["sip_refer", "sip_invite"]).optional(), on_hold_music: z.enum(["none", "relaxing_sound", "uplifting_beats", "ringtone", "custom"]).optional(), custom_on_hold_music_asset_id: z.string().optional(), transfer_ring_duration_ms: z.number().int().gte(5000).lte(90000).optional()}), z.object({type: z.literal("warm_transfer"), show_transferee_as_caller: z.boolean().optional(), agent_detection_timeout_ms: z.number().gte(10000).lte(300000).optional(), transfer_ring_duration_ms: z.number().int().gte(5000).lte(90000).optional(), on_hold_music: z.enum(["none", "relaxing_sound", "uplifting_beats", "ringtone", "custom"]).optional(), custom_on_hold_music_asset_id: z.string().optional(), public_handoff_option: z.union([z.object({type: z.literal("prompt").optional(), prompt: z.string().optional()}), z.object({type: z.literal("static_message").optional(), message: z.string().optional()})]).optional(), private_handoff_option: z.union([z.object({type: z.literal("prompt").optional(), prompt: z.string().optional()}), z.object({type: z.literal("static_message").optional(), message: z.string().optional()})]).optional(), ivr_option: warmTransferPrompt.optional(), opt_out_human_detection: z.boolean().optional(), enable_bridge_audio_cue: z.boolean().optional()}), z.object({type: z.literal("agentic_warm_transfer"), show_transferee_as_caller: z.boolean().optional(), on_hold_music: z.enum(["none", "relaxing_sound", "uplifting_beats", "ringtone", "custom"]).optional(), custom_on_hold_music_asset_id: z.string().optional(), transfer_ring_duration_ms: z.number().int().gte(5000).lte(90000).optional(), public_handoff_option: z.union([z.object({type: z.literal("prompt").optional(), prompt: z.string().optional()}), z.object({type: z.literal("static_message").optional(), message: z.string().optional()})]).optional(), agentic_transfer_config: z.object({transfer_agent: z.object({agent_id: z.string().min(1), agent_version: agentVersionReference}).optional(), transfer_timeout_ms: z.number().gte(10000).lte(300000).optional(), action_on_timeout: z.enum(["bridge_transfer", "cancel_transfer"]).optional()}), enable_bridge_audio_cue: z.boolean().optional()})]); export const transferCallTool = z.object({type: z.literal("transfer_call"), name: z.string(), description: z.string().optional(), transfer_destination: transferDestination, ignore_e164_validation: z.boolean().optional(), custom_sip_headers: z.record(z.string(), z.string()).optional(), transfer_option: transferOption, speak_during_execution: z.boolean().optional(), execution_message_description: z.string().optional(), execution_message_type: z.enum(["prompt", "static_text"]).optional()}); export const postCallAnalysisSetting = z.enum(["both_agents", "only_destination_agent"]); export const agentSwapWebhookSetting = z.enum(["both_agents", "only_destination_agent", "only_source_agent"]); export const agentSwapTool = z.object({name: z.string(), type: z.literal("agent_swap"), description: z.string().optional(), agent_id: z.string().min(1), agent_version: agentVersionReference.optional(), speak_during_execution: z.boolean().optional(), execution_message_description: z.string().optional(), execution_message_type: z.enum(["prompt", "static_text"]).optional(), post_call_analysis_setting: postCallAnalysisSetting, webhook_setting: agentSwapWebhookSetting.optional(), keep_current_voice: z.boolean().optional(), keep_current_language: z.boolean().optional(), use_swap_agent_max_duration: z.boolean().optional()}); export const pressDigitTool = z.object({type: z.literal("press_digit"), name: z.string(), description: z.string().optional(), delay_ms: z.number().int().optional()}); export const smsContentPredefined = z.object({type: z.literal("predefined").optional(), text: z.string().optional()}); export const smsContentInferred = z.object({type: z.literal("inferred").optional(), prompt: z.string().optional()}); export const smsContentTemplate = z.object({type: z.literal("template"), template: z.literal("info_collection")}); export const smsContent = z.union([smsContentPredefined, smsContentInferred, smsContentTemplate]); export const smsSender = z.union([z.object({type: z.literal("current_number")}), z.object({type: z.literal("retell_long_code")})]); export const smsDestination = z.union([z.object({type: z.literal("customer_number")}), z.object({type: z.literal("phone_number"), phone_number: z.string(), ignore_e164_validation: z.boolean().optional()})]); export const sendSMSTool = z.object({name: z.string(), type: z.literal("send_sms"), description: z.string().optional(), speak_during_execution: z.boolean().optional(), execution_message_description: z.string().optional(), execution_message_type: z.enum(["prompt", "static_text"]).optional(), sms_content: smsContent, sms_sender: z.union([smsSender, z.object({}).nullable()]).optional(), sms_destination: z.union([smsDestination, z.object({}).nullable()]).optional(), speak_after_execution: z.boolean().optional()}); export const toolParameter = z.object({type: z.literal("object"), properties: z.object({}), required: z.array(z.string()).optional(), additionalProperties: z.boolean().optional()}); export const executionStatusVariable = z.string(); export const customTool = z.object({type: z.literal("custom"), name: z.string(), url: z.string(), description: z.string().optional(), method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).optional(), headers: z.record(z.string(), z.string()).optional(), query_params: z.record(z.string(), z.string()).optional(), parameters: toolParameter.optional(), execution_status_variable: executionStatusVariable.optional(), response_variables: z.record(z.string(), z.string()).optional(), speak_during_execution: z.boolean().optional(), speak_after_execution: z.boolean().optional(), execution_message_description: z.string().optional(), execution_message_type: z.enum(["prompt", "static_text"]).optional(), timeout_ms: z.number().int().gte(1000).lte(600000).optional(), max_retry: z.number().int().gte(0).lte(5).optional(), args_at_root: z.boolean().optional(), parameter_type: z.enum(["json", "form"]).optional(), enable_typing_sound: z.boolean().optional()}); export const codeTool = z.object({type: z.literal("code"), name: z.string(), description: z.string().optional(), code: z.string().max(20000), timeout_ms: z.number().int().gte(5000).lte(60000).optional(), execution_status_variable: executionStatusVariable.optional(), response_variables: z.record(z.string(), z.string()).optional(), speak_during_execution: z.boolean().optional(), speak_after_execution: z.boolean().optional(), execution_message_description: z.string().optional(), execution_message_type: z.enum(["prompt", "static_text"]).optional(), enable_typing_sound: z.boolean().optional()}); export const stringAnalysisData = z.object({type: z.literal("string"), name: z.string().min(1), description: z.string(), examples: z.array(z.string()).optional(), required: z.boolean().optional(), conditional_prompt: z.string().optional()}); export const enumAnalysisData = z.object({type: z.literal("enum"), name: z.string().min(1), description: z.string(), choices: z.array(z.string()), required: z.boolean().optional(), conditional_prompt: z.string().optional()}); export const booleanAnalysisData = z.object({type: z.literal("boolean"), name: z.string().min(1), description: z.string(), required: z.boolean().optional(), conditional_prompt: z.string().optional()}); export const numberAnalysisData = z.object({type: z.literal("number"), name: z.string().min(1), description: z.string(), required: z.boolean().optional(), conditional_prompt: z.string().optional()}); export const analysisData = z.union([stringAnalysisData, enumAnalysisData, booleanAnalysisData, numberAnalysisData]); export const extractDynamicVariableTool = z.object({type: z.literal("extract_dynamic_variable"), name: z.string(), description: z.string(), variables: z.array(analysisData), enable_typing_sound: z.boolean().optional()}); export const bridgeTransferTool = z.object({type: z.literal("bridge_transfer"), name: z.string(), description: z.string().optional(), speak_during_execution: z.boolean().optional(), execution_message_description: z.string().optional(), execution_message_type: z.enum(["prompt", "static_text"]).optional()}); export const cancelTransferTool = z.object({type: z.literal("cancel_transfer"), name: z.string(), description: z.string().optional(), speak_during_execution: z.boolean().optional(), execution_message_description: z.string().optional(), execution_message_type: z.enum(["prompt", "static_text"]).optional()}); export const mCPTool = z.object({type: z.literal("mcp"), mcp_id: z.string().optional(), name: z.string(), description: z.string(), input_schema: z.record(z.string(), z.string()).optional(), execution_status_variable: executionStatusVariable.optional(), response_variables: z.record(z.string(), z.string()).optional(), speak_during_execution: z.boolean().optional(), speak_after_execution: z.boolean().optional(), execution_message_description: z.string().optional(), execution_message_type: z.enum(["prompt", "static_text"]).optional(), enable_typing_sound: z.boolean().optional()}); export const outputSelection = z.union([z.object({mode: z.literal("all"), fields: z.array(z.string()).optional()}), z.object({mode: z.literal("subset"), fields: z.array(z.string())})]); export const appTool = z.object({type: z.literal("integration_app"), name: z.string(), app_id: z.string(), provider: z.string(), app_tool_template_name: z.string(), parameters: z.array(toolParameter).optional(), execution_status_variable: executionStatusVariable.optional(), response_variables: z.record(z.string(), z.string()).optional(), output_selection: outputSelection.optional(), description: z.string().optional(), speak_during_execution: z.boolean().optional(), speak_after_execution: z.boolean().optional(), execution_message_description: z.string().optional(), execution_message_type: z.enum(["prompt", "static_text"]).optional(), enable_typing_sound: z.boolean().optional()}); export const tool = z.union([escalateChatTool, endCallTool, transferCallTool, agentSwapTool, pressDigitTool, sendSMSTool, customTool, codeTool, extractDynamicVariableTool, bridgeTransferTool, cancelTransferTool, mCPTool, appTool]); export const stateEdge = z.object({destination_state_name: z.string(), description: z.string(), parameters: toolParameter.optional()}); export const state = z.object({name: z.string(), state_prompt: z.string().optional(), edges: z.array(stateEdge).optional(), tools: z.array(tool).optional()}); export const mCP = z.object({name: z.string(), url: z.string(), headers: z.record(z.string(), z.string()).optional(), query_params: z.record(z.string(), z.string()).optional(), timeout_ms: z.number().int().optional()}); export const retellLLMResponse = z.object({llm_id: z.string(), version: z.number().int().optional(), is_published: z.boolean().optional(), model_config: modelConfig.optional(), backup_model: nullableBackupModelChoice.optional(), model: nullableLLMModel.optional(), s2s_model: nullableS2SModel.optional(), model_temperature: z.number().optional(), model_high_priority: z.boolean().nullable().optional(), model_ultrafast: z.boolean().nullable().optional(), knowledge_base_ids: z.array(z.string()).nullable().optional(), kb_config: kBConfig.optional(), start_speaker: z.enum(["user", "agent"]).optional(), begin_after_user_silence_ms: z.number().int().nullable().optional(), begin_message: z.string().nullable().optional(), general_prompt: z.string().nullable().optional(), voice_prompt: z.string().nullable().optional(), general_tools: z.array(tool).nullable().optional(), states: z.array(state).nullable().optional(), starting_state: z.string().nullable().optional(), default_dynamic_variables: z.record(z.string(), z.string()).nullable().optional(), mcps: z.array(mCP).nullable().optional(), is_transfer_llm: z.boolean().nullable().optional(), last_modification_timestamp: z.number().int()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Retrieve details of a specific Retell LLM Response Engine * * GET /get-retell-llm/{llm_id} */ export const getApiGetRetellLlmLlmId = async (args: GetApiGetRetellLlmLlmIdArgs, options?: GetApiGetRetellLlmLlmIdOptions) => { const {baseUrl = "https://api.retellai.com", fetch: fetchFn = fetch, apiKey} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.version != null) query.append("version", String(args.version)) if (apiKey !== undefined) headers.set('authorization', `Bearer ${apiKey}`) const url = `${baseUrl.replace(/\/+$/, '')}/get-retell-llm/${encodeURIComponent(String(args.llm_id))}${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(retellLLMResponse, await res.json()) };