@dialt/sdk
Budget selects voice sessions; text sessions use Fast or Smart.
Public tiers are Budget, Fast (default) and Smart. Set mode: { kind: 'dialt', instructions: 'Help callers.', brain: 'budget' } in browser or Node for Budget at 3.33 cents/minute ($2/hour) with Fast reasoning. Its only tier restriction is six eligible stock voices, enforced by the server. See Budget. Legacy capacity: 'spot' and spot_fallback are deprecated compatibility fields; new calls never use paid fallback.
Version 0.50.0 adds first-class TypeScript declarations, a headless Node.js realtime entry point and a generated HTTP client. Version 0.49.0 makes mode.instructions required: the agent's role comes only from your instructions. Read the migration guide before upgrading.
The TypeScript and JavaScript SDK for Dialt. One package provides browser realtime, headless Node.js realtime and the generated HTTP API client.
Install
npm install @dialt/sdk
Use the installed package through your application build. Do not expose a persistent API key in browser JavaScript.
The canonical TypeScript SDK guide covers the backend credential route, AudioWorklet assets, microphone lifecycle, input selection, events, tools, reconnection, text mode, Node.js and HTTP operations. The WebSocket guide documents the wire protocol.
Browser realtime
The root export and @dialt/sdk/browser are equivalent. They own browser microphone capture, echo cancellation and playback.
Experimental assistant interruptions use mode.assistant_interruptions: 'off' | 'pauses' | 'speech', defaulting to 'off'. Enable a mode on a fresh single-speaker voice session and provide instructions describing when the assistant should interrupt. See assistant interruptions for same-utterance follow-up limits, acoustic barge protection and resume behavior. Node.js uses the same mode field.
Every session sets mode.instructions: customer-authored developer instructions for the application role, goals, knowledge, policy and task behavior. Dialt's platform prompt combines platform rules, selected voice guidance, and call facts. new DialtClient() throws when the instructions are missing or blank, and the server refuses such a start with missing_instructions.
mode.voice selects a synthesis identity with default pronunciation/accent and coupled voice guidance; mode.multilingual selects experimental multilingual guidance. Neither selects the application role. There are no independent customer style, accent, delivery or fine-tuning controls today. Prompting guides wording and delivery through generated text; synthesis receives that text and voice/settings, not the assembled system prompt. Developer instructions share the assembled system message with platform content, so intended ownership does not guarantee model obedience. See prompt ownership and control limits.
const client = new DialtClient({
apiKey: credential.api_key,
sessionId: credential.session_id,
mode: {
kind: 'dialt',
instructions: 'You are a helpful voice assistant on a phone call. If a request is missing a key detail, ask one concise clarifying question.',
},
});
Node.js realtime
The Node.js session is headless: your application sends 16 kHz mono audio and consumes assistant PCM from audio events. Set outputSampleRate to 8000, 16000 (the default) or 24000; each audio event reports that rate in detail.sr. It supports WebSocket realtime only and does not claim a microphone, speaker, echo canceller or WebRTC implementation.
import { DialtSession } from '@dialt/sdk/node';
const session = new DialtSession({
apiKey: credential.api_key,
sessionId: credential.session_id,
outputSampleRate: 24000,
mode: { kind: 'dialt', instructions: 'Help callers with their orders.' },
});
session.addEventListener('audio', ({ detail }) => {
if (detail.samples) play(detail.samples);
});
await session.connect();
await session.streamAudio(inputPcm, { chunkMs: 20 });
session.nowMs() returns the session's monotonic clock. For client-owned turn boundaries, set mode.turn_detection to client, send that turn's audio, then call session.finishInputTurn(). session.sendClientEvent() sends other documented client_event controls.
HTTP API
@dialt/sdk/http is generated from Dialt's OpenAPI contract. Use persistent API keys only on trusted backends.
import { createClient, listSessions } from '@dialt/sdk/http';
const http = createClient({ auth: process.env.DIALT_API_KEY });
const { data, error } = await listSessions({ client: http, query: { limit: 50 } });
For an acknowledged same-session agent swap, call
await client.handoffAgent({instructions, tools, voice?, context?, operationId?}). The SDK
generates operationId when omitted; it correlates this live request only and is not a retry
token. It resolves on the final applied or rejected acknowledgement (an optional queued one keeps
it pending), and updates reconnect replay state only after application. Await it before another
mode setter. On timeout or disconnect the outcome is uncertain and the SDK does not retry.
For host updates, await client.injectContext(text, { role: 'context', reply: true })
appends context immediately even while busy. An acknowledgement with accepted: true,
reply_started: false, and queued: true means a reply waits for the next idle boundary.
Waiting updates coalesce into one reply. Keep the same messageId and payload when retrying
a lost acknowledgement; a replayed receipt describes the original acceptance. Reset, transfer
teardown and session end cancel pending replies. User-role input retains its busy rejection.
client.setMicEnabled(false) gates current and future SDK-owned microphone tracks without reopening the device. The setting defaults to enabled and persists across startMic() and stopMic(), input-device fallback, capture acquisition already in progress and transport reconnection until setMicEnabled(true) is called.
Licensed under Apache-2.0.
Policy guidance
Define each rule once in mode.policy with id, when, and do:
{"include_instructions": true, "background_guidance": true,
"rules": [{"id": "supervisor", "when": "The caller requests a supervisor.",
"do": "Call request_supervisor and explain the tool result to the caller."}]}
Both switches default true and work independently. Declare and handle the tool normally; existing permission checks still apply. Background checks quietly inject guidance about the reviewed caller or assistant turn without requesting another reply or executing tools. Source revisions, flag updates/retractions, errors and completion events are reported through the ordinary event interface. Delivery is not proof the agent complied.
Policy rules use id, when and do; legacy action configurations are rejected. See the
policy contract.
Voice selection is optional and uses the server roster from GET /v1/voices. An explicit voice takes precedence over a saved preference, then US Female (us_female) is the shared default. The voice route is independent of Dialt Fast or Dialt Smart. Irish Male keeps the stable key classic, and Circuit (circuit) remains selectable.
The regional keys are us_female, us_male, british_male, british_female, mexican_female and brazilian_female. British Female and Mexican Spanish Female retain their keys with new speaking identities. southern_us_female is an accepted alias of us_female, changing the accent from Southern US to general US English. brazilian_male is an accepted alias of brazilian_female, changing the speaker from male to female, including feminine self-reference. Aliases are absent as duplicate picker options; use canonical keys in new integrations.
Customer voice conditioning and voice creation/deletion are removed. Replace saved conditioned-voice keys with a stock key from GET /v1/voices, available through listVoices in @dialt/sdk/http. Resumed sessions retain their confirmed stock voice identity unless explicitly changed. Irish Male, Chime, Servo, Circuit, Arabic voices and provisional Hinglish Male retain their identities. See the catalogue and migration guide.
Empty keys are rejected locally; unknown, retired or unavailable keys return the server's
nonretryable invalid_voice error. A rejected mid-session switch leaves the confirmed
voice unchanged, including on reconnect. Retired keys must be replaced explicitly.