clientis an open Rime client.microphoneyields the PCM16 frames from your capture.playeris your audio output.
Open one session per call
Open a session when the call starts, and close it when the caller hangs up. This code holds one call. It sends the caller’s audio on a separate task and reads Prism’s events inplay_replies, which Live conversations builds. When the caller hangs up, the capture loop closes the session, and the events loop ends.
- Python
- Node.js
stream_caller_audio closes the session when the capture stops for any reason, so a failed microphone ends the call. In Node.js, background runs work beside the events loop, and it closes the session if that work fails. The snippets in Live conversations and Tools also use it.
Configure a session
Set the voice, instructions, tools, and turn settings when the session opens. The SDK sends them when you connect, and over the WebSocket API, the firstsession.update sets them. During the call, update in the SDK, or a later session.update, can change most of them:
Node.js uses the same names in camelCase:
interruptOnSpeech, turnDetection, endOfTurnTimeoutMs, responseMetadata, and setResponseMetadata. In Go and Rust, Update and update take the same settings. These SDK calls need Python 0.1.0a22, Node.js 0.1.0-alpha.22, Go v0.1.0-alpha.13, Rust 0.1.0-alpha.11, or later, as the Prism SDK reference lists. The two turn settings work like this:
- Eagerness: how readily Prism decides that the caller has finished.
lowcuts in less and replies later, andhighreplies sooner and cuts in more.mediumandauto, the default, use Prism’s standard setting. - End-of-turn timeout: the silence that ends the turn, even when Prism is not sure that the caller has finished. It runs from 1 to 10 seconds, and the default is 5 seconds.
session_setting_fixed, and that update changes nothing, not even its other fields. Session configuration in the WebSocket reference lists every field, its default, and its values.
Choose a voice
Prism has four voices. Pick the one that suits your callers, and set it when you connect. Without a voice, Prism usesastra.
Write instructions for a phone call
Prism speaks every word that it writes, so the caller hears whatever format the reply takes. Start the instructions with rules for speech, and put your agent’s role, task, and policy after them. Write them in plain sentences, because replies follow their style. Write instructions that Prism follows gives a starter prompt with these rules, and shows how to improve it with test calls.Update instructions or history during a call
You can update Prism while a call runs.add_message (addMessage in Node.js) adds a line to the history. With create_item (createItem in Node.js) or over the WebSocket API, you can also add a system message, which is a note for the model, and delete_item (deleteItem) removes an item. Read and edit the history in the SDK reference shows both. update in the SDK, or a later session.update, can change the instructions, the voice, and the tools. Prism caches the start of the conversation between turns. After you change the instructions, the next reply builds that cache again, so its first audio comes a little later.
A change never interrupts the reply that is playing. That reply keeps the settings that it started with, and the next reply uses the change. To make a change count at once, follow these steps:
- Make the change.
- Cancel the reply that is playing, with
cancelin the SDK orresponse.cancelover the WebSocket API. - Report what the caller heard, and report that playback stopped. Stop playback when the caller talks over a reply and Report when a reply finishes playing show how.
- Ask for a nudge, such as “Tell the caller about the change.”
Start from an earlier conversation
A new session is a new conversation with no memory of the old one. A session also ends when its connection drops, and the SDK does not reconnect. So to go on with an earlier call, give the new session what the agent must remember. Add that history right after connect, before you stream the caller’s audio, so that the first reply already sees it. With the SDK, add each line withadd_message (addMessage in Node.js), as Typed turns and nudges shows. A "user" line is something that the caller said, and an "assistant" line is a reply that the caller heard:
- Python
- Node.js
create_item (createItem in Node.js), as Start from an earlier call shows. Over the WebSocket API, send one conversation.item.create for each item, after session.updated. Both take three kinds of items:
- Past messages:
userandassistantmessages, as with the SDK. - Notes: a
systemmessage, such as “The caller called back after the line dropped.” The model sees the note at its place in the conversation. - Past tool calls: a
function_callitem, and then afunction_call_outputitem with the samecall_id. A past call never starts a tool round.
get_history (getHistory in Node.js) in the SDK, or prism.conversation.get over the WebSocket API, lists every item in the order the next reply sees them, including turns that a long call leaves out of the prompt, and a new session accepts the listed items as they are. Keep each message within the text limit.
What each reply sees
Each reply sees your instructions and tools, and the conversation so far, unless a long call outgrows the context:- the caller’s turns. Prism keeps each earlier turn as its transcript.
- Prism’s earlier replies. After an interruption, your playback report keeps only what the caller heard.
- every tool call and its result
- every message that you added
get_history (getHistory in Node.js) in the SDK, or prism.conversation.get over the WebSocket API, lists the conversation.
Handle long calls
A call has no time limit. When a long call outgrows the context, Prism leaves the oldest turns out of each reply’s prompt by default, and the call goes on. So put what the agent must always know in the instructions, because asystem message that you add leaves the prompt with its turn. Over the WebSocket API, truncation sets this. usage in each response.done shows how many tokens the prompt uses, and prism_truncation says how many earlier items Prism left out.
Label replies for your logs
You can label every reply with your own values, such as your call ID, to match Prism’s events to your records. With the SDK, passresponse_metadata (responseMetadata in Node.js) when you connect, or call set_response_metadata (setResponseMetadata) during the call. Over the WebSocket API, set the labels in prism_response_metadata, and Prism copies them into the metadata of each reply’s response.created and response.done:
metadata of a response.create replaces the session label with the same name, for that reply only. This metadata came from the reply to a typed turn that set agent to after-hours. Prism adds its own fields, whose names start with prism_. prism_drain_token is the token for the reply’s playback receipt:
session.update with prism_response_metadata replaces all the labels, and {} clears them. Leave the field out to keep the current labels. Labels have limits on their number and length.
End a session
Close the session when the caller hangs up. With the SDK, leave theasync with block, or call await session.close(). Over the WebSocket API, close the connection. A closed connection ends the conversation, and a new connection starts a new conversation.
Prism also closes a quiet conversation after 5 minutes, even while you send audio. It sends session.idle_timeout first, and then it closes the connection with code 1000 and reason idle. The time starts again with any other client event, with speech that Prism detects, or with a reply. So a nudge that checks on a quiet caller keeps the conversation open.
Most errors do not end the session. Errors and limits explains each error code and close code, and what to do about it.
