Retell AI

Retell AI runs the conversations. The application creates calls, manages agents and imports numbers through Retell’s API, and receives call outcomes as webhooks.

Concern File

Client wrapper

lib/retellai/client.ts

Types

lib/retellai/types.ts

Agent config, voice and model lists

lib/retellai/agent-config.ts

Post-call analysis schema

lib/retellai/post-call-analysis.ts

Agent platform operations

lib/services/retell-agent-service.ts

Agent definitions and sync script

scripts/retelai/

Configuration

NEXT_RETELLAI_API_KEY=          # read into RETELLAI_API_KEY in lib/constants.ts
NEXT_RETELLAI_BASE_URL=         # optional override
NEXT_RETELL_OUTBOUND_AGENT_ID=  # default outbound agent

RETELL_SMS_AGENT_ID is hardcoded in lib/constants.ts as agent_dc036c59f7365da0f463b16e72 — every outbound SMS uses it.

Client surface

RetellClient (lib/retellai/client.ts) wraps retell-sdk. Every method goes through a private wrapCall helper that converts SDK failures into RetellError, so callers never see the SDK’s error shape.

Method Purpose

createPhoneCall(options)

Outbound call: fromNumber, toNumber, overrideAgentId, metadata, retellLlmDynamicVariables

createWebCall(options)

Browser-based call

getCall(callId), updateCall(callId, updates), deleteCall(callId)

Call record management

createSmsChat(options)

Start an SMS conversation

createRetellPhoneNumber(…​)

Buy a number through Retell

registerPhoneNumber(phoneNumber)

Register an existing number

importNumber(phoneNumber, terminationUri, outboundAgentId)

Import a carrier number over SIP

unregisterPhoneNumber(phoneNumber)

Remove a number

getPhoneNumber(id), listPhoneNumbers()

Number inspection

listVoices(), getVoice(voiceId)

Voice catalogue, exposed at GET /api/retell/voices

Outbound call

await retellClient.createPhoneCall({
  fromNumber: phoneSelection.phoneNumber,
  toNumber: targetPhoneNumber,
  overrideAgentId: overrideAgent.agentId,
  metadata: callMetadata,
  retellLlmDynamicVariables: callMetadata,
})

The same object is passed as both metadata and retellLlmDynamicVariables, because the webhook handler reads metadata.campaignId and metadata.campaignTargetId for correlation, while the agent prompt reads the dynamic variables.

callMetadata contains the target’s payloadJson (every value stringified and null-coalesced to "", because an agent reads a missing variable’s name aloud) plus campaignId, campaignName, campaignTargetId, agentId and agentVersionId.

Agent management

RetellAgentService performs platform operations, mirrored from every write to /api/ai-agents:

createAgent, getAgent, updateAgent, deleteAgent, publishAgent(retellAgentId, version), createAgentVersion(retellAgentId, baseVersion), createLLM, getLLM, updateLLM, syncAgent(…​).

AiAgent.retellAgentId is the link, and AiAgentVersion.configJson holds the full Retell IAgentData for caller agents. See AI agents and test cases.

Agent definitions in the repository

scripts/retelai/agents/<name>/ holds agent.md (the prompt, version-controlled) and index.ts (the config). registry.ts is the single source of the fallback agent id/name list used when a workspace has no database caller agents, and sync.ts pushes definitions to Retell.

Agents currently defined: adrian, brian, cmon, kate, kathrine.

Fixed configuration

HARDCODED_AGENT_CONFIG in lib/retellai/agent-config.ts is applied to every caller agent: stt_mode: 'fast', end_call_after_silence_ms: 25000, max_call_duration_ms: 80000, ring_duration_ms: 30000, begin_message_delay_ms: 1000, allow_user_dtmf: true with a 5 s keypress timeout, is_public: false, vocab_specialization: 'general'. Rationale for each is in Voice and behaviour configuration.

Phone-number import

A carrier number is imported over SIP using the provider’s trunk and termination URL from EXTERNAL_PROVIDER_CONFIGS:

await retellClient.importNumber(phoneNumber, terminationUrl, outboundAgentId)

The resulting Retell id is stored as PhoneNumbers.retellPhoneNumberId. See Carriers, MessagingApp, Nooks and JustCall.

Webhooks

Retell posts to POST /api/webhooks/event-logger. Only call_analyzed is handled; call_started is stored but not dispatched. There is no signature verification on this endpoint — treat the URL as a secret. See Retell AI events.

Key payload paths:

call.call_id
call.to_number, call.from_number, call.direction
call.disconnection_reason, call.channel_type
call.duration_ms, call.call_cost.combined_cost
call.start_timestamp, call.end_timestamp
call.recording_url, call.transcript
call.call_analysis.in_voicemail
call.call_analysis.call_screening_detected
call.call_analysis.ai_suspicion_detected
call.call_analysis.user_sentiment
call.call_analysis.call_summary
call.call_analysis.call_successful
call.call_analysis.custom_analysis_data.*
call.metadata.campaignId
call.metadata.campaignTargetId

SMS

createSmsChat starts a conversation with RETELL_SMS_AGENT_ID, a from number selected from the workspace’s smsEnabled numbers, and every caller-supplied field forwarded as a Retell dynamic variable. Used by the send_sms MCP tool and by the sequence sms step. See send_sms.