---
name: tavus-cvi-interactions
description: Control Tavus CVI conversations in real-time using the Interactions Protocol. Use when sending text for the replica to speak (echo), interrupting the replica, injecting context mid-conversation, handling tool calls, or listening to conversation events via WebRTC/Daily.
---
# Tavus CVI Interactions Protocol
Control live conversations programmatically via WebRTC data channel.
## Setup: Daily.js Client
```html
```
## Interactions You Can Send
### Echo: Make Replica Speak Text
Bypass LLM, replica speaks exactly what you provide:
```javascript
send({
"message_type": "conversation",
"event_type": "conversation.echo",
"conversation_id": "YOUR_CONVERSATION_ID",
"properties": {
"modality": "text",
"text": "Hello! Let me tell you about our product."
}
});
```
For streaming audio (base64):
```javascript
send({
"message_type": "conversation",
"event_type": "conversation.echo",
"conversation_id": "YOUR_CONVERSATION_ID",
"properties": {
"modality": "audio",
"audio": "BASE64_ENCODED_AUDIO",
"sample_rate": 24000,
"inference_id": "unique-id",
"done": "true"
}
});
```
### Respond: Inject User Input
Treat text as if user spoke it (goes through LLM):
```javascript
send({
"message_type": "conversation",
"event_type": "conversation.respond",
"conversation_id": "YOUR_CONVERSATION_ID",
"properties": {
"text": "What are your pricing plans?"
}
});
```
### Interrupt: Stop Replica Speaking
```javascript
send({
"message_type": "conversation",
"event_type": "conversation.interrupt",
"conversation_id": "YOUR_CONVERSATION_ID"
});
```
### Overwrite Context
Replace the entire conversational context:
```javascript
send({
"message_type": "conversation",
"event_type": "conversation.overwrite_context",
"conversation_id": "YOUR_CONVERSATION_ID",
"properties": {
"context": "User is now asking about enterprise features."
}
});
```
### Append Context
Add to existing context without replacing:
```javascript
send({
"message_type": "conversation",
"event_type": "conversation.append_context",
"conversation_id": "YOUR_CONVERSATION_ID",
"properties": {
"context": "User mentioned they have a team of 50 people."
}
});
```
### Adjust Sensitivity
Change turn-taking sensitivity mid-conversation:
```javascript
send({
"message_type": "conversation",
"event_type": "conversation.sensitivity",
"conversation_id": "YOUR_CONVERSATION_ID",
"properties": {
"participant_pause_sensitivity": "high",
"participant_interrupt_sensitivity": "low"
}
});
```
Values: `low`, `medium`, `high`
## Events You Receive
### Utterance (What Was Said)
```json
{
"event_type": "conversation.utterance",
"properties": {
"role": "user",
"content": "Tell me about your product"
}
}
```
Role: `user` or `replica`
### Replica Started/Stopped Speaking
```json
{
"event_type": "conversation.replica.started_speaking",
"properties": {
"inference_id": "inf-123"
}
}
```
```json
{
"event_type": "conversation.replica.stopped_speaking",
"properties": {
"inference_id": "inf-123",
"duration": 4.5
}
}
```
### User Started/Stopped Speaking
```json
{
"event_type": "conversation.user.started_speaking"
}
```
### Tool Call (Function Calling)
When LLM invokes a tool:
```json
{
"event_type": "conversation.tool_call",
"properties": {
"tool_name": "get_weather",
"arguments": {
"location": "San Francisco, CA"
},
"inference_id": "inf-123"
}
}
```
Handle it, then respond with echo or respond interaction.
### Perception Analysis
When Raven analyzes the user:
```json
{
"event_type": "conversation.perception_analysis",
"properties": {
"analysis": "User appears engaged, smiling, looking at camera"
}
}
```
### Replica Interrupted
Fired when replica was interrupted:
```json
{
"event_type": "conversation.replica.interrupted",
"properties": {
"inference_id": "inf-123"
}
}
```
## Python Client (Daily-Python)
```python
from daily import Daily, CallClient
Daily.init()
client = CallClient()
def on_app_message(message, sender):
print(f"Received: {message}")
client.set_user_name("bot")
client.join(meeting_url, completion=on_join)
# Send interaction
client.send_app_message({
"message_type": "conversation",
"event_type": "conversation.echo",
"conversation_id": "xxx",
"properties": {"text": "Hello!"}
})
```
## Common Patterns
### Echo Mode with Manual Control
1. Create persona with `pipeline_mode: "echo"`
2. Join conversation with Daily client
3. Send `conversation.echo` events to control speech
4. Send `conversation.interrupt` to stop
5. Listen for events to track state
### Hybrid: LLM + Manual Injection
1. Use `pipeline_mode: "full"` for normal conversation
2. Inject context with `conversation.append_context`
3. Override with `conversation.echo` when needed
4. Use `conversation.interrupt` + `conversation.echo` for immediate takeover