Appearance
Event Types
Complete reference for all events in the SDK.
Overview
Events are triggered by the AI Flow service and handled by your assistant. All events include session information and are typed with TypeScript.
Base Event Structure
All events extend a base structure with session information:
typescript
interface SessionInfo {
id: string; // UUID of the session
account_id: string; // Account identifier
phone_number: string; // Phone number for this flow session
direction?: "inbound" | "outbound";
from_phone_number: string;
to_phone_number: string;
}Event Types
SessionStart Event
Triggered when a new call session begins.
typescript
interface AiFlowEventSessionStart {
type: "session_start";
session: {
id: string; // UUID of the session
account_id: string; // Account identifier
phone_number: string; // Phone number for this flow session
direction?: "inbound" | "outbound"; // Call direction
from_phone_number: string; // Phone number of the caller
to_phone_number: string; // Phone number of the callee
};
}Example:
typescript
onSessionStart: async (event) => {
// Log session details
console.log(
`${event.session.direction} call from ${event.session.from_phone_number} to ${event.session.to_phone_number}`
);
// Return greeting
return "Welcome to our service!";
};UserSpeechStarted Event
Triggered when the user's speech is first detected, before the full transcript is available. Uses Voice Activity Detection (VAD) and fires 20–120 ms after the user starts speaking.
WebSocket only — this event is not delivered to HTTP webhook handlers.
typescript
interface AiFlowEventUserSpeechStarted {
type: "user_speech_started";
session: SessionInfo;
}Notes:
- Fires at most once per speech turn; resets after
user_speakis received - No return value is expected; returning an action has no effect
Example:
typescript
onUserSpeechStarted: async (event) => {
console.log('User started speaking, session:', event.session.id);
// No return value needed
},UserSpeak Event
Triggered when the user speaks and speech-to-text completes.
typescript
interface AiFlowEventUserSpeak {
type: "user_speak";
text: string; // Recognized speech text
session: SessionInfo;
}Example:
typescript
onUserSpeak: async (event) => {
const intent = analyzeIntent(event.text);
if (intent === "help") {
return "I can help you with billing, support, or sales.";
}
return processUserInput(event.text);
};AssistantSpeak Event
Triggered after the assistant starts speaking. Event may be omitted for some text-to-speech models.
typescript
interface AiFlowEventAssistantSpeak {
type: "assistant_speak";
text?: string; // Text that was spoken
ssml?: string; // SSML that was used (if applicable)
duration_ms: number; // Duration of speech in milliseconds
speech_started_at: number; // Unix timestamp (ms) when speech started
session: SessionInfo;
}Example:
typescript
onAssistantSpeak: async (event) => {
console.log(`Spoke for ${event.duration_ms}ms`);
// Track conversation metrics
trackMetrics({
sessionId: event.session.id,
duration: event.duration_ms,
text: event.text,
});
};AssistantSpeechEnded Event
Triggered after the assistant finishes speaking.
typescript
interface AiFlowEventAssistantSpeechEnded {
type: "assistant_speech_ended";
session: SessionInfo;
}Example:
typescript
onAssistantSpeechEnded: async (event) => {
console.log(`Finished speaking for session ${event.session.id}`);
// Trigger next action if needed
await triggerNextAction(event.session.id);
};UserInputTimeout Event
Triggered when no user speech is detected within the configured timeout period after the assistant finishes speaking.
typescript
interface AiFlowEventUserInputTimeout {
type: "user_input_timeout";
session: SessionInfo;
}When Triggered:
- A
speakaction includes auser_input_timeout_secondsfield - The assistant finishes speaking (
assistant_speech_endedevent fires) - The specified timeout period elapses without any user speech detected
Example:
typescript
onUserInputTimeout: async (event) => {
console.log(`No user input received for session ${event.session.id}`);
// Retry the question
return {
type: "speak",
session_id: event.session.id,
text: "Are you still there? Please say yes or no.",
user_input_timeout_seconds: 5
};
};Configuring Timeout:
Set user_input_timeout_seconds in the speak action:
typescript
onSessionStart: async (event) => {
return {
type: "speak",
session_id: event.session.id,
text: "What is your account number?",
user_input_timeout_seconds: 5 // Wait 5 seconds for response
};
};Common Use Cases:
typescript
// Hangup after multiple timeouts
const timeoutCounts = new Map<string, number>();
onUserInputTimeout: async (event) => {
const sessionId = event.session.id;
const count = (timeoutCounts.get(sessionId) || 0) + 1;
timeoutCounts.set(sessionId, count);
if (count >= 3) {
return {
type: "hangup",
session_id: sessionId
};
}
return {
type: "speak",
session_id: sessionId,
text: `I didn't hear anything. Please respond. Attempt ${count} of 3.`,
user_input_timeout_seconds: 5
};
};
// Transfer to agent after timeout
onUserInputTimeout: async (event) => {
return {
type: "speak",
session_id: event.session.id,
text: "Let me connect you with a live agent who can help you."
// Follow with transfer action
};
};DtmfReceived Event
Triggered when the user presses a key on their phone keypad.
typescript
interface AiFlowEventDtmfReceived {
type: "dtmf_received";
digit: string; // The key pressed: "0"–"9", "*", or "#"
session: SessionInfo;
}Example:
typescript
onDtmfReceived: async (event) => {
console.log(`User pressed: ${event.digit}`);
if (event.digit === '1') {
return {
type: 'transfer',
session_id: event.session.id,
transfer_to: '+49211100200'
};
}
return {
type: 'speak',
session_id: event.session.id,
text: `You pressed ${event.digit}.`
};
},Notes:
- All standard DTMF tones are supported:
0–9,*,# - Each key press triggers a separate event
- DTMF events can occur at any point during the call
SessionEnd Event
Triggered when the call session ends.
typescript
interface AiFlowEventSessionEnd {
type: "session_end";
session: SessionInfo;
}Example:
typescript
onSessionEnd: async (event) => {
// Save conversation history
await saveConversation(event.session.id);
// Send analytics
await trackSessionEnd(event.session);
};Barge-In Detection
User interruptions are detected via the barged_in flag in user_speak events:
typescript
interface AiFlowEventUserSpeak {
type: "user_speak";
text: string;
barged_in?: boolean; // true if user interrupted
session: SessionInfo;
}Example:
typescript
onUserBargeIn: async (event) => {
// Called automatically when event.barged_in === true
console.log(`User interrupted with: ${event.text}`);
return "I'm listening, please continue.";
};Event Flow
┌─────────────────┐
│ session_start │──> Respond with speak/audio or do nothing
└─────────────────┘
┌─────────────────┐
│ user_speak │──> Respond with speak/audio/transfer/hangup
│ (barged_in?) │ Check barged_in flag for interruptions
└─────────────────┘
┌─────────────────┐
│ assistant_speak │──> Optional: track metrics, trigger next action
└─────────────────┘
┌─────────────────┐
│ session_end │──> Cleanup only, no actions accepted
└─────────────────┘Event Summary Table
| Event Type | Transport | Description | When Triggered | Can Return Action? |
|---|---|---|---|---|
session_start | HTTP + WebSocket | Call session begins | When a new call is initiated | ✅ Yes |
user_speech_started | WebSocket only | Speech onset detected | When VAD detects the user starting to speak | ❌ No |
user_speak | HTTP + WebSocket | User speech detected | After speech-to-text completes (includes barged_in flag) | ✅ Yes |
dtmf_received | HTTP + WebSocket | DTMF digit pressed | When the user presses a phone key | ✅ Yes |
assistant_speak | HTTP + WebSocket | Assistant finished speaking | After TTS playback completes | ✅ Yes |
assistant_speech_ended | HTTP + WebSocket | Assistant finished speaking | After speech playback ends | ✅ Yes |
user_input_timeout | HTTP + WebSocket | User input timeout reached | When no speech detected after timeout | ✅ Yes |
session_end | HTTP + WebSocket | Call session ends | When the call terminates | ❌ No |
Type Safety
All events are fully typed. Import types from the SDK:
typescript
import type {
AiFlowEventSessionStart,
AiFlowEventUserSpeechStarted,
AiFlowEventUserSpeak,
AiFlowEventDtmfReceived,
AiFlowEventAssistantSpeak,
AiFlowEventAssistantSpeechEnded,
AiFlowEventUserInputTimeout,
AiFlowEventSessionEnd,
AiFlowEventUserBargeIn,
} from "@sipgate/ai-flow-sdk";
onSessionStart: async (event: AiFlowEventSessionStart) => {
// event is fully typed
const sessionId: string = event.session.id;
// ...
};Next Steps
- Action Types - Learn how to respond to events
- API Reference - Complete API documentation