Skip to main content
Events are typed Python objects for communication between your agent and the Cartesia platform. Your agent receives input events from the harness and yields output events to control the conversation.
To learn which events trigger your agent and how to customize this behavior (e.g., responding to DTMF, preventing interruptions), see Controlling the Conversational Loop.

Input Events

Input events are received by your agent from the Cartesia harness. All input events include an optional history field containing the complete conversation history. When history is None, the event is being used within a history list; when history contains a list, the event has the full conversation context attached.

Call Lifecycle

EventDescription
CallStartedThe call has connected
CallEndedThe call has ended
from line.events import CallStarted, CallEnded

async def process(self, env, event):
    if isinstance(event, CallStarted):
        yield AgentSendText(text="Hello! How can I help?")
    elif isinstance(event, CallEnded):
        # Perform cleanup
        pass

User Turn Events

EventDescription
UserTurnStartedThe user started speaking (triggers interruption by default)
UserTurnEndedThe user finished speaking (triggers new agent turn by default)
UserTextSentUser text content (within UserTurnEnded.content)
UserDtmfSentUser pressed a DTMF button
from line.events import UserTurnEnded, UserTextSent

if isinstance(event, UserTurnEnded):
    for content in event.content:
        if isinstance(content, UserTextSent):
            user_message = content.content

Agent Turn Events (in history)

EventDescription
AgentTurnStartedAgent started its turn
AgentTurnEndedAgent finished its turn
AgentTextSentAgent text that was spoken
AgentDtmfSentDTMF tone sent by agent

Handoff Event

EventDescription
AgentHandedOffControl transferred to a handoff tool

Custom Event

EventDescription
UserCustomSentCustom metadata sent from the client via the WebSocket custom event
Received when your client application sends a custom WebSocket event to the call stream. The event carries a metadata dict with whatever key-value pairs the client included:
from line.events import UserCustomSent

async def process(self, env, event):
    if isinstance(event, UserCustomSent):
        action = event.metadata.get("action")
        # React to client-side triggers (e.g., button clicks, form submissions)

Output Events

Output events are yielded by your agent to control the conversation.

Speech

from line.events import AgentSendText

yield AgentSendText(text="Hello! How can I help you today?")

Call Control

from line.events import AgentEndCall, AgentTransferCall, AgentSendDtmf

# End the call
yield AgentEndCall()

# Transfer to another number
yield AgentTransferCall(target_phone_number="+14155551234")

# Send DTMF tone
yield AgentSendDtmf(button="1")

Dynamic Configuration

Update call settings (voice, pronunciation, language) mid-conversation:
from line.events import AgentUpdateCall

# Change voice
yield AgentUpdateCall(voice_id="5ee9feff-1265-424a-9d7f-8e4d431a12c7")

# Change pronunciation dictionary
yield AgentUpdateCall(pronunciation_dict_id="dict-123")

# Change language
yield AgentUpdateCall(language="es")
FieldTypeDescription
voice_idOptional[str]Updates the agent’s voice
pronunciation_dict_idOptional[str]Updates the pronunciation dictionary
languageOptional[str]Updates the language used on speech-to-text (STT) and text-to-speech (STT) models
All fields are optional—only set fields are updated.

Tool Events

These are emitted by LlmAgent to track tool execution:
from line.events import AgentToolCalled, AgentToolReturned

# Emitted when LLM calls a tool
yield AgentToolCalled(
    tool_call_id="call_123",
    tool_name="get_weather",
    tool_args={"city": "San Francisco"}
)

# Emitted when tool returns
yield AgentToolReturned(
    tool_call_id="call_123",
    tool_name="get_weather",
    tool_args={"city": "San Francisco"},
    result="72°F and sunny"
)

Logging

from line.events import LogMetric, LogMessage

# Log a metric
yield LogMetric(name="response_time_ms", value=150)

# Log a message
yield LogMessage(
    name="order_lookup",
    level="info",
    message="Found order #12345",
    metadata={"order_id": "12345"}
)

Custom Events

Send arbitrary metadata from your agent to the harness:
from line.events import AgentSendCustom

yield AgentSendCustom(metadata={"action": "show_form", "form_id": "checkout"})
Pair with UserCustomSent for bidirectional metadata exchange.

Voice & Language Control

Change voice or speech recognition language mid-call:
from line.events import AgentUpdateCall

# Switch to Spanish voice and speech recognition
yield AgentUpdateCall(voice_id="spanish-voice-id", language="es")

# Enable multilingual auto-detect mode
yield AgentUpdateCall(language="multilingual")
The language field sets the ASR (speech recognition) language. Pass any language code supported by Ink STT, or "multilingual" for automatic language detection.

Event History

All input events include an optional history field containing the conversation history. When history is None, the event is inside a history list; when it contains a list, full conversation context is attached. LlmAgent handles this automatically—you only need to understand history if building custom agents.

Accessing History

from line.events import UserTextSent, AgentTextSent

async def process(self, env, event):
    for past_event in event.history:
        if isinstance(past_event, UserTextSent):
            print(f"User said: {past_event.content}")
        elif isinstance(past_event, AgentTextSent):
            print(f"Agent said: {past_event.content}")
Events in the history list have history=None to avoid redundant nesting. The event types are the same as regular input events:
Event TypeDescription
CallStartedCall began
UserTurnStartedUser started speaking
UserTextSentUser’s transcribed speech
UserDtmfSentUser’s DTMF button press
UserTurnEndedUser finished speaking
AgentTurnStartedAgent started responding
AgentTextSentAgent’s spoken text
AgentDtmfSentAgent’s DTMF tone
AgentTurnEndedAgent finished responding
CallEndedCall ended
LlmAgent automatically converts the event history to LLM messages:
  • User messages: From UserTextSent events
  • Assistant messages: From AgentTextSent events
  • Tool calls: From AgentToolCalled and AgentToolReturned events
This means the LLM sees full context including previous tool calls and results, enabling it to reference that information without making redundant API calls.
If building a custom agent (not using LlmAgent), you can use history for context, summarization, or pattern detection:
class CustomAgent:
    async def process(self, env, event):
        user_turns = sum(
            1 for e in event.history
            if isinstance(e, UserTurnEnded)
        )

        if user_turns > 5:
            yield AgentSendText(text="We've been chatting for a while! Is there anything else I can help with?")