Nuance LabsDocs

Events you get

The user's words and the AI persona's, the end of each reply, hand-offs, quiet holds and the session's end.

The session sends these as JSON on the nuance_live topic. Every event has a type and an event_id. Times (start_ms, end_ms, offset_ms, cut_ms) are milliseconds on the session's timeline, where 0 is when it started.

EventWhen
session.startedThe session is live and hears the user's microphone.
session.input_transcript.deltaThe user's words, as they're recognized.
session.input_transcript.doneThe user's turn, as the AI persona's reply to it read it.
session.output_transcript.deltaThe persona's words, as it says them.
session.output_audio.doneThe audio of the persona's reply has ended.
session.delegation.createdThe persona handed work off.
response.eventOne event of the backend's work on a task.
session.quiet.started, session.quiet.endedA quiet hold, the persona's or yours, started or ended.
session.thinking.appended, session.instructions.appended, session.commentary.appendedYour append went in.
session.input_audio.muted, session.input_audio.unmutedYour mute or unmute went in.
session.updatedYour session.update went in.
session.usage.updatedSeconds used so far, every 15 seconds.
errorSomething you sent was refused, or the session hit a problem.
infoA notice, such as a task the session withdrew.
session.closedThe session is over, and why (reason, with message for a policy or age-check end). Nothing follows.

Ignore event types and fields you don't know: new ones are added.

The session

session.started comes once the persona can hear the user. Its session describes what runs:

  • session.id is live_ and the conversation's id.
  • session.expires_at is when the session will end, in Unix seconds.
  • session.delegation is the delegation as the session runs it.
  • session.runtime_tools is the persona's own tools as the session runs them: always stay_quiet, and end_call and call_time when you named them.

A room never echoes your prompts or tool schemas: instructions is null, and each tool is named without its schema. Keep the definitions you minted.

Words

session.input_transcript.delta and session.output_transcript.delta carry delta, start_ms and end_ms. Deltas carry their own spaces, so join them as they come.

{ "type": "session.output_transcript.delta", "event_id": "evt_88", "delta": " It's light rain", "start_ms": 41230, "end_ms": 41890 }
  • The user's words include words they cut off. A card number, a card's security code, a one-time code or a Social Security number the user reads aloud comes as [redacted].
  • The persona's words come as it says them; its audio is on the room's audio track.
  • session.input_transcript.done is the user's turn as the persona's reply to it understood it, once that reply opens: transcript is the turn's settled words, which may differ from the live ones (the deltas joined), with start_ms and end_ms. Use it as the turn's record. A turn can get a later one, when the persona's reply ended before it said a word and the next reply opens on the whole turn: the later one's replaces_event_id names the event_id of the one it replaces, so show it in that one's place. Typed words are in neither event.

The end of a reply

session.output_audio.done says the audio of the persona's reply has ended, at the time its last audio plays on the track: wait for it before acting on what the persona is saying, such as hanging up after a goodbye.

reasonWhy
completedThe persona finished.
interruptedThe reply was cut short: the user spoke over the persona, you sent session.output_audio.interrupt, the runtime let it go before its end, or the session closed while the persona spoke.
revisedAn append with while_speaking: "revise" cut it, and the persona's next reply carries on from the cut.

Treat a reason you don't know as an end too. It also carries start_ms and end_ms, and delegation_id and response_id when the reply was opened to say a backend's answer. A reply that said nothing gets none. The persona's replies come without response.created or response.done events: wait for session.output_audio.done, never for the persona's next words, since it may stay quiet until the user speaks.

Hand-offs

session.delegation.created says the persona handed work off: delegation.id (del_1, …), delegation.target (client or responses) and offset_ms, where on the timeline it did. Under a responses delegation, response.event then carries the backend's work, with the task's delegation_id and the backend's own event nested as event. See Delegation and tools.

Quiet holds

session.quiet.started and session.quiet.ended report a quiet hold: the persona's (by: "agent", it chose to stay quiet) or yours (by: "client", session.floor.hold).

  • started carries seconds until it runs out (null: until it's released or the user speaks), ends_on_speech, your reason and offset_ms.
  • ended carries cause: expired, speech (the user's words), released, replaced (by a newer hold) or session_ended.
  • offset_ms is null when the time isn't known.

Errors and notices

{ "type": "error", "event_id": "evt_90", "error": { "type": "invalid_request_error", "code": "command_refused", "message": "the agent is not talking", "client_event_id": "stop_1" } }

error.type is invalid_request_error, or server_error for a failure of ours. error.code says what happened, error.param names the field when one is at fault, and error.client_event_id names the event of yours it answers. Most errors aren't fatal: the session goes on. An error instead of session.started means the session was refused at the start; error.message names the setting. Limits and errors lists the codes you'll meet.

info is a notice, with code and message, such as delegation_cancelled for a task the session withdrew.

The session's end

session.closed is the last event, with reason, and, for a policy or age-check end, message: the words to show your user, the same for every end of its kind.

reasonWhy
close_requestedYou sent session.close.
expiredThe time limit ran out (session.expires_at).
contentA safety check ended it for a policy violation, including when the user says a Social Security number. message is "This conversation ended because something in it broke our Acceptable Use Policy." See Safety.
age_checkThe age check ended it: the camera showed only people who look under 18. message is "This conversation ended because it looks like someone under 18 is using it without an adult." See Safety.
end_callThe persona ended the call after its goodbye (the end_call tool).
errorThe session failed: start a new conversation with a new session token. A conversation your server ended with the end route can also close with error for now; it did not fail.
connection_lostThe connection ended without a session.close.

The events route's ended comes after it. If the room's connection is stuck, only ended comes. Either way, leave the room.

On this page