Voximplant now includes a native Cartesia Line / Agents connector that connects any Voximplant call to a Cartesia Line voice agent for real-time, speech-to-speech conversations—over PSTN, SIP, WebRTC, or WhatsApp Business Calling—without building custom media gateways or WebSocket streaming infrastructure.
This integration is available as a Voice AI Connector inside VoxEngine, Voximplant’s serverless Voice AI Orchestration environment. You deploy your agent logic on Cartesia Line (code-first, managed runtime), and Voximplant handles the telephony, media conversion, and real-time streaming so you can focus on agent behavior and production call flows.
Highlights
- Cartesia Line voice agents on real calls — Connect Line agents to phone calls, WhatsApp and SIP infrastructure for inbound and outbound call flows
- Leverage Cartesia’s extensive Text-to-Speech capabilities - choose from any of Cartesia’s voices or your own cloned voices without a separate TTS pipeline. Cartesia’s Realtime TTS continues to be available for Voximplant orchestrated pipelines.
- Code-first agent development + managed runtime — Line runs your agent code in Cartesia’s managed runtime with auto-scaling and built-in audio orchestration, so you don’t need to stand up your own agent-serving stack for production voice.
- Advanced telephony routing and control — manage simple to advanced call control, transfers, surveys, escalation logic, SIP routing, and compliance inside VoxEngine—while Line handles the agent conversation loop.
Developer notes
- Native VoxEngine module — Load the integration with
require(Modules.Cartesia);and create a client viaCartesia.createAgentsClient({ apiKey, agentId, cartesiaVersion, ... }). Cartesia Calls API over WebSocket — VoxEngine bridges call audio to Cartesia Line via Line’s Calls API (WebSocket streaming) - this is handled automatically without any additional configuration.- Line Agent→VoxEngine coordination - Use VoxEngine’s
AppEvents.HttpRequestto handle `POSTmessages from the Cartesia line script for coordinating tool calls and routing information. - VoxEngine→Line Agent configuration - pass telephony related information and HTTP endpoints to the Line Agent by passing a metadata object with the agent client start method.
- Barge-in and Turn-taking - interactivity between the agent and the caller/callee is handled completely by the Line Agent
- Redefine telephony tools for Voximplant control — Line’s built-in tools like
end_calland `transfer_callare designed to act inside Line’s calling environment. For Voximplant-controlled routing (warm transfers, surveys, SIP handoff), define your own passthrough tools in Line that signal VoxEngine out-of-band.
Demo video
-
Pricing and availability
The Cartesia Line / Agents connector follows the same Voice AI Connector pricing model as Voximplant’s other Voice AI connectors:
- $0.001 per 15 seconds of audio streaming (0.4¢/min)
- Price includes bidirectional audio (inbound + outbound)
As with Voximplant’s other Voice AI connectors, Voximplant charges for real-time streaming, while Cartesia Line usage is billed according to your Cartesia plan.
Quick start
The VoxEngine scenario below connects a Line Agent and listens for a call transfer command from the agent in response to a tool call.
// Voximplant VoxEngine scenario:
// - Streams caller audio <-> Cartesia Line agent (Agents connector)
// - Supports:
// - end_call: hang up the caller leg
// - call_transfer: place an outbound PSTN consult call and then bridge caller -> consult leg
//
// Configure these keys in Voximplant Application Storage:
// - CARTESIA_API_KEY
// - CARTESIA_AGENT_ID
// - PSTN_CALLER_ID (required for callPSTN; must be a real E.164 number in your Voximplant account)
//
// Call transfer in this demo always dials the public Voximplant demo number shown on the Cartesia Agents product page.
require(Modules.Cartesia);
require(Modules.ApplicationStorage);
require(Modules.ASR);
const CARTESIA_VERSION = "2025-04-16";
const CALL_TRANSFER_NUMBER = "+18339906144";
// Per-session control URL. Any HTTPS request to this URL triggers AppEvents.HttpRequest in this session.
// We'll pass it into Cartesia call metadata so the agent runtime can request telephony actions via HTTP.
let sessionControlUrl = null;
// Current call session state (single-call demo scenario).
let callerLeg = null;
let voiceAIClient = null;
let consultLeg = null;
let transferInProgress = false;
let transferred = false;
VoxEngine.addEventListener(AppEvents.Started, (appEvent) => {
sessionControlUrl = appEvent.accessSecureURL;
Logger.write(`===SESSION_CONTROL_URL_READY===>${JSON.stringify({accessSecureURL: sessionControlUrl}) || ""}`);
});
VoxEngine.addEventListener(AppEvents.HttpRequest, (appEvent) => {
Logger.write(`===HTTP_CONTROL_REQUEST===>${JSON.stringify({method: appEvent.method, path: appEvent.path}) || ""}`);
// Check for and handle control commands
const cmd = JSON.parse(appEvent?.content);
if (cmd.action === "end_call") {
Logger.write(`===CONTROL_END_CALL===>${JSON.stringify(cmd) || ""}`);
callerLeg.hangup();
voiceAIClient?.close();
VoxEngine.terminate();
} else if (cmd.action === "call_transfer") {
Logger.write(`===CONTROL_CALL_TRANSFER===>${JSON.stringify(cmd) || ""}`);
callTransfer(cmd);
} else {
Logger.write(`===CONTROL_COMMAND_UNKNOWN===>${JSON.stringify(cmd) || ""}`);
}
return JSON.stringify({ok: true});
});
async function callTransfer(cmd) {
if (transferInProgress || transferred) return;
if (!callerLeg) return;
transferInProgress = true;
Logger.write(`===CALL_TRANSFER_REQUESTED===>${JSON.stringify(cmd || {}) || ""}`);
// Detach the agent now for a blind transfer. Delay or conference for a warm transfer
if (voiceAIClient) {
VoxEngine.stopMediaBetween(callerLeg, voiceAIClient);
voiceAIClient.close();
voiceAIClient = null;
}
const currentPstnCallerId = (await ApplicationStorage.get("PSTN_CALLER_ID")).value;
consultLeg = VoxEngine.callPSTN(CALL_TRANSFER_NUMBER, currentPstnCallerId, {followDiversion: true});
consultLeg.addEventListener(CallEvents.Failed, () => {
transferInProgress = false;
Logger.write(`===CONSULT_CALL_FAILED===>${JSON.stringify({}) || ""}`);
callerLeg.hangup();
});
consultLeg.addEventListener(CallEvents.Disconnected, (event) => {
Logger.write(`===CONSULT_CALL_DISCONNECTED===>${JSON.stringify(event) || ""}`);
});
consultLeg.addEventListener(CallEvents.Connected, () => {
Logger.write(`===CONSULT_CALL_CONNECTED===>${JSON.stringify({}) || ""}`);
transferInProgress = false;
transferred = true;
VoxEngine.sendMediaBetween(callerLeg, consultLeg);
});
}
function onWebSocketClose(event) {
Logger.write(`===ON_WEB_SOCKET_CLOSE===>${JSON.stringify(event) || ""}`);
// Ignore expected close during transfer
if (transferInProgress || transferred || event.code === 1000) return;
// otherwise end the call
callerLeg.hangup();
VoxEngine.terminate();
}
VoxEngine.addEventListener(AppEvents.CallAlerting, async ({ call }) => {
callerLeg = call;
// Termination functions - add cleanup and logging as needed
call.addEventListener(CallEvents.Disconnected, () => VoxEngine.terminate());
call.addEventListener(CallEvents.Failed, () => VoxEngine.terminate());
try {
call.answer();
call.record({ hd_audio: true, stereo: true }); // Optional: record the call
voiceAIClient = await Cartesia.createAgentsClient({
apiKey: (await ApplicationStorage.get("CARTESIA_API_KEY")).value,
agentId: (await ApplicationStorage.get("CARTESIA_AGENT_ID")).value,
cartesiaVersion: CARTESIA_VERSION,
onWebSocketClose,
});
VoxEngine.sendMediaBetween(call, voiceAIClient);
voiceAIClient.start({
// Optional metadata passed into the Cartesia agent
metadata: {
from: call.callerid(),
to: call.number(),
vox_session_control_url: sessionControlUrl, // Control plane from Cartesia via HTTPS callback
},
});
// "log only" handlers for debugging.
[
Cartesia.AgentsEvents.ACK,
Cartesia.AgentsEvents.Clear,
Cartesia.AgentsEvents.ConnectorInformation,
Cartesia.AgentsEvents.DTMF,
Cartesia.AgentsEvents.Unknown,
Cartesia.AgentsEvents.WebSocketError,
].forEach((eventName) => {
voiceAIClient.addEventListener(eventName, (event) => {
Logger.write(`===${event.name}===>${JSON.stringify(event.data) || ""}`);
});
});
} catch (error) {
Logger.write(`===SOMETHING_WENT_WRONG===>${JSON.stringify(error) || String(error)}`);
VoxEngine.terminate();
}
});
See the corresponding Cartesia Agents code here.
References
Voximplant product information and documentation:
- Cartesia Agents Voice AI Connector Product page: https://voximplant.com/products/cartesia-agents-client
- Cartesia Agents Client API Getting Started guide: http://voximplant.com/docs/voice-ai/cartesia/voice-agents-client
- Cartesia Agents Client API reference: https://voximplant.com/docs/references/voxengine/cartesia
- Voice AI product overview - https://voximplant.ai/
Cartesia Line Agents product information and documentation:
- Announcement: https://cartesia.ai/blog/introducing-line-for-voice-agents
- Agents Docs: https://docs.cartesia.ai/line/introduction




