Skip to content

Event types ​

The typed events a call emits, and what each one carries. This is the internal call vocabulary, used in two places: the call event stream (GET /calls/{call}/events) and the NATS subjects the two planes exchange. Defined as CallEventType in @callagent/contracts and mirrored in App\Enums\CallEventType, with a test that reads the PHP source and fails on drift.

These are not webhook event names

Outbound webhooks use a separate, deliberately versioned vocabulary of 28 names, and the two overlap enough to catch you out:

Here (call events)There (webhooks)
call.createdcall.started
call.connectedcall.answered
tool.startedtool.called
user.speech.startedspeech.started

Subscribe a webhook endpoint to a name from this page and it is rejected as unknown.

Every event shares the envelope; only data differs, and only that is described below.

Lifecycle ​

Eventdata
call.createddirection, from, to, phoneNumberId, assistantId, squadId, campaignId, telephonyProvider, idempotencyKey
call.ringingringingAt, destination
call.connectedansweredAt, setupMs, sipCallId
call.endedendedReason, durationMs, billableSeconds, endedBy (customer · assistant · operator · system · provider)
call.failedendedReason, error
call.state.changedfrom, to, reason
transport.connectedtransport, remoteAddress, connectMs, codec, sampleRate
transport.disconnectedcode, reason

Speech in stt ​

Eventdata
user.speech.startedenergyDb, duringAssistantSpeech
user.speech.endedspeechMs, silenceMs
transcript.partialtext, isFinal: false, confidence, speaker, language, words[]
transcript.finalas above with isFinal: true
endpoint.detectedstrategy (provider · vad_timeout · punctuation · semantic · hybrid), silenceMs, minSpeechMs, maxWaitMs, confidence, transcript

words[] carries per-word startMs, endMs, confidence and speaker when the transcriber provides them.

Model llm ​

Eventdata
llm.startedprovider, model, temperature, maxTokens, messageCount
llm.first_tokenas above plus ttftMs
llm.completedplus tokens (prompt, completion, total, cachedPrompt, reasoning), durationMs, finishReason, toolCallCount, fallbackIndex
llm.failederror (code, message, statusCode, retryable)
llm.abortedabortReason: barge_in · timeout · handoff · call_ended · operator

finishReason is stop, length, tool_calls, content_filter, aborted or error.

Synthesis tts ​

Eventdata
tts.startedvoice (provider, voiceId, model), text, chunkIndex
tts.first_audioplus ttfaMs
tts.completedplus characters, durationMs, audioMs, fallbackIndex
tts.failederror
tts.abortedabortReason

Playback playback ​

Eventdata
assistant.speech.startedtext, messageId
assistant.speech.interruptedspokenText, remainingText, spokenMs, detectionMs, stopAudioMs
assistant.speech.completedtext, audioMs, messageId

spokenText versus remainingText is the pair that matters: the transcript keeps only what the caller actually heard.

Speech to speech ​

s2s.started · s2s.first_audio (ttfaMs) · s2s.completed (durationMs, inputAudioMs, outputAudioMs, tokens) · s2s.failed.

Tools tool ​

Eventdata
tool.startedtoolId, toolCallId, name, toolType, args
tool.completedplus result, durationMs, async
tool.failedplus error
tool.rejectedplus rejectionReason, rejectionMessage

rejectionReason is one of the eleven on error codes.

MCP ​

mcp.started · mcp.completed · mcp.failed, each carrying serverId, serverName, transport (streamable_http · sse · stdio), toolName, args, and on completion result and durationMs.

Knowledge ​

Eventdata
knowledge.queriedknowledgeBaseId, query, provider, matchCount, topScore, durationMs, documentIds
knowledge.insufficientknowledgeBaseId, query, threshold, topScore, safetyMode

knowledge.insufficient is the honest-answer signal: retrieval came back below the threshold and the assistant said so rather than inventing one. See knowledge-only mode.

Routing ​

Eventdata
handoff.startedfromAssistantId, toAssistantId, squadId, trigger (tool · intent · variable · dynamic · explicit · silent), contextMode, reason
handoff.completedtoAssistantId, durationMs, messagesCarried
transfer.startedmode (blind · warm · queue · sip_uri · assistant · dynamic), destination, destinationType
transfer.completedplus legId, durationMs
transfer.failedplus error

Contact centre ​

operator.queued · operator.ringing · operator.connected · operator.rejected · operator.missed · operator.wrap_up · queue.abandoned · queue.overflowed.

All carry operatorId, operatorName, queueId, queueName, extension, waitMs, ringMs, position and reason where they apply. operator.wrap_up adds dispositionId, disposition, notes and wrapUpMs; queue.abandoned adds abandonedAfterMs; queue.overflowed adds overflowTo and overflowType (queue · ring_group · voicemail · assistant · number).

DTMF, SIP and voicemail ​

Eventdata
dtmf.receiveddigits, method (rfc2833 · rfc4733 · sip_info · inband · provider), buffer
dtmf.sentdigits, method, interDigitMs
sip.request.sentmethod (INFO · MESSAGE · NOTIFY · REFER · OPTIONS · UPDATE), destination, headers, body
sip.response.receivedstatusCode, reason, method, headers
voicemail.detecteddetector (provider_amd · classifier · beep · tool), confidence, beepDetected, policy (hangup · leave_message · continue · custom), detectionMs

Artifacts ​

Eventdata
recording.consent_announcedmode, spokenText, audioUrl, region
recording.consent_recordedplus acknowledged
recording.startedrecordingId, channels (mono · stereo · dual), track (mixed · caller · assistant · operator), format
recording.pausedplus reason
recording.resumedas recording.started
recording.readyplus url, storagePath, bytes, durationMs
analysis.completedsummary, sentiment, success, successReason, topics, structuredOutputs, scorecardIds, durationMs

analysis.completed

The event type and its payload are defined, and the control plane stores the results if they arrive. The post-call analysis pipeline that would produce them is not currently dispatched by the control plane — see Implementation status and Analytics & cost.

Provider health ​

Eventdata
provider.fallbackcomponent, from, to, reason (timeout · error · rate_limit · auth · circuit_open · health_check), attempt
provider.errorcomponent, provider, model, error, circuitOpened

component is model, transcriber, voice, speech_to_speech, telephony, and for provider.error also storage and observability.

Categorising them ​

The prefix before the first dot is the category, which is how a consumer can subscribe broadly without enumerating 60 names:

ts
const category = (type: string) => type.split('.')[0];
// 'endpoint.detected' → 'endpoint'

const isError = (type: string) =>
  type.includes('failed') || type.includes('error') || type === 'tool.rejected';

Both helpers ship as eventCategory() and isErrorEvent() in @callagent/contracts.

Documented against the code. Anything not yet implemented is labelled, never described as working.