Conversational Video Interface (CVI) is a framework for creating real-time multimodal video interactions with AI. It enables an AI agent to see, hear, and respond naturally, mirroring human conversation.
CVI is the world’s fastest interface of its kind. It allows you to map a human face and conversational ability onto your AI agent. With CVI, you can achieve utterance-to-utterance latency with SLAs under 1 second. This is the full round-trip time for a participant to say something and the replica to reply.
CVI provides a comprehensive solution, with the option to plug in your existing components as required.
Key Concepts
CVI is built around three core concepts that work together to create real-time, humanlike interactions with an AI agent:
Key Features
Natural Interaction CVI uses facial cues, body language, and real-time turn-taking to enable natural, human-like conversations.
Modular pipeline Customize the Perception, STT, LLM and TTS layers to control identity, behavior, and responses.
Lifelike AI replicas Choose from over 100+ hyper-realistic digital twins or customize your own with human-like voice and expression.
Multilingual support Hold natural conversations in 30+ languages using the supported TTS engines.
World's lowest latency Experience real-time interactions with ~600ms response time and smooth turn-taking.
Layers
The Conversational Video Interface (CVI) is built on a modular layer system, where each layer handles a specific part of the interaction. Together, they capture input, process it, and generate a real-time, human-like response.
Here’s how the layers work together:
Handles real-time audio and video streaming using WebRTC (powered by Daily). This layer captures the user’s microphone and camera input and delivers output back to the user. This layer is always enabled. You can configure input/output for audio (mic) and video (camera).
3. Speech Recognition (STT)
4. Large Language Model (LLM)
Converts the LLM response into speech using the supported TTS Engines (Cartesia (Default) , ElevenLabs). Click here to learn how to configure the Text-to-Speech (TTS) layer.
Most layers are configurable via the Persona .
Getting Started
You can quickly create a conversation by using the Developer Portal or following the steps in the Quickstart guide.
If you use Cursor, use this pre-built prompt to get started faster: Copy
✅ System Prompt for AI: React (Vite) + Tavus CVI Integration Purpose:
Generate React (TypeScript) apps with Tavus CVI using Vite , following the official docs and GitHub examples:
https://docs.tavus.io/sections/integrations/embedding-cvi ✅ AI MUST ALWAYS DO THE FOLLOWING: 1. Setup React App Using Vite npm create vite@latest my-tavus-app -- --template react-ts
cd my-tavus-app
npm install
2. Install Tavus CVI UI Components npx @tavus/cvi-ui@latest init
npx @tavus/cvi-ui@latest add conversation
✅ This creates: src/components/cvi/components/
cvi-provider.tsx
conversation.tsx
3. Wrap App with CVIProvider
Update src/App.tsx
: import { CVIProvider } from "./components/cvi/components/cvi-provider" ;
function App () {
return < CVIProvider > { /* Your app content */ } </ CVIProvider > ;
}
4. Create Conversation API Call Always use this pattern: const response = await fetch ( "https://tavusapi.com/v2/conversations" , {
method: "POST" ,
headers: {
"Content-Type" : "application/json" ,
"x-api-key" : import . meta . env . VITE_TAVUS_API_KEY || "" ,
},
body: JSON . stringify ({
replica_id: import . meta . env . VITE_REPLICA_ID || "rfe12d8b9597" , // Default
persona_id: import . meta . env . VITE_PERSONA_ID || "pdced222244b" , // Default
}),
});
const data = await response . json ();
setConversationUrl ( data . conversation_url );
✅ Explain: conversation_url
from API response is used inside <Conversation>
. 5. Render Conversation
Inside CVIProvider
< Conversation
conversationUrl = { conversationUrl }
onLeave = { () => setConversationUrl ( null ) }
/>
6. Add Environment Variable Create .env
in the my-tavus-app
folder (if not already there): VITE_TAVUS_API_KEY=your_api_key_here
VITE_REPLICA_ID=rfe12d8b9597 // Default replica_id, can be overridden in .env
VITE_PERSONA_ID=pdced222244b // Default persona_id, can be overridden in .env
Important : DO NOT create .env
outside of the my-tavus-app
folder. It must be inside your project directory where src
exists.
Access via: import . meta . env . VITE_TAVUS_API_KEY
import . meta . env . VITE_REPLICA_ID
import . meta . env . VITE_PERSONA_ID
7. Create cvi-components.json
by Default Ensure that the cvi-components.json
file is generated in the my-tavus-app
folder with the following content: ✅ Expected AI Output Example src/App.tsx
:import React , { useState } from "react" ;
import { CVIProvider } from "./components/cvi/components/cvi-provider" ;
import { Conversation } from "./components/cvi/components/conversation" ;
const App : React . FC = () => {
const [ conversationUrl , setConversationUrl ] = useState < string | null >( null );
const createConversation = async () => {
const response = await fetch ( "https://tavusapi.com/v2/conversations" , {
method: "POST" ,
headers: {
"Content-Type" : "application/json" ,
"x-api-key" : import . meta . env . VITE_TAVUS_API_KEY || "" ,
},
body: JSON . stringify ({
replica_id: import . meta . env . VITE_REPLICA_ID || "rfe12d8b9597" ,
persona_id: import . meta . env . VITE_PERSONA_ID || "pdced222244b" ,
}),
});
const data = await response . json ();
setConversationUrl ( data . conversation_url );
};
return (
< CVIProvider >
< div
style = { {
display: "flex" ,
justifyContent: "center" ,
alignItems: "center" ,
width: "100vw" ,
height: "100vh" ,
backgroundColor: "#1e1e1e" ,
color: "#fff" ,
textAlign: "center" ,
flexDirection: "column" ,
margin: 0 ,
padding: 0 ,
} }
>
< h1 style = { { marginBottom: "1rem" } } > Tavus CVI Integration (Vite) </ h1 >
{ ! conversationUrl ? (
< button
onClick = { createConversation }
style = { {
padding: "0.75rem 1.5rem" ,
fontSize: "1rem" ,
background: "#6a0dad" , // Purple for light and dark modes
color: "#fff" ,
border: "none" ,
borderRadius: "6px" ,
cursor: "pointer" ,
} }
>
Start Conversation
</ button >
) : (
< div style = { { width: "100%" , maxWidth: "800px" } } >
< Conversation
conversationUrl = { conversationUrl }
onLeave = { () => setConversationUrl ( null ) }
/>
</ div >
) }
</ div >
</ CVIProvider >
);
};
export default App ;
✅ Checklist for AI Output
✅ Uses Vite + React TypeScript (npm create vite@latest --template react-ts
)
✅ Includes npx @tavus/cvi-ui init
and add conversation
✅ Imports CVIProvider
and Conversation
from src/components/cvi/components/
✅ Uses correct API call with:
https://tavusapi.com/v2/conversations
Headers: Content-Type
, x-api-key
Body: replica_id
& persona_id
✅ Uses import.meta.env.VITE_TAVUS_API_KEY
✅ Renders <Conversation>
inside <CVIProvider>
✅ Purple button is visible in both light and dark modes
✅ .env
is created inside the correct project folder (my-tavus-app
)
✅ cvi-components.json
is created by default with { "tsx": true }
Keep things in mind:
If you’re already in the my-tavus-app
folder, avoid running cd my-tavus-app
again. Check your current folder before running commands.
After running the necessary setup, remember to run npm run dev
to start your app.
Do NOT place the .env
file outside of the project folder. It must reside within the my-tavus-app
directory.