Agent-readable docs index: /docs/llms.txt. Full docs in one file: /docs/llms-full.txt. Download /docs/docs.zip to grep all markdown files locally.

Server media

Use the server SDK when audio comes from a telephone or calling provider instead of a browser microphone. Your provider adapter owns codecs and transient playback. Inkibra remains the only owner of the conversation, floor, phases, tools, and generated speech.

Install and authorize

Run this once from the server application:
bash
npx @inkibra/voice-cli init
The command installs @inkibra/voice-sdk and writes INKIBRA_API_KEY to .env.local. Keep that file and every provider credential server-side.

Implement the audio transport

Every provider adapter implements one small interface:
ts
import { liveVoicePcmFormat, type LiveVoiceAudioTransport, type LiveVoiceAudioTransportHandlers, type LiveVoiceAudioOutputCommand, } from "@inkibra/voice-sdk/server"; class ProviderAudioTransport implements LiveVoiceAudioTransport { readonly format = liveVoicePcmFormat; private handlers?: LiveVoiceAudioTransportHandlers; constructor(private provider: WebSocket) {} start(handlers: LiveVoiceAudioTransportHandlers) { this.handlers = handlers; // Parse provider input, decode its codec, resample it, then call: // handlers.input(pcm16le24k); } output(command: LiveVoiceAudioOutputCommand) { // Map enqueue, block-foreground, release, cancel, and done // onto the provider's playback queue, marks, and clear command. } stop() { this.provider.close(1000, "Inkibra session ended"); } }
The SDK-facing format is always signed PCM16 little-endian, mono, at 24 kHz. A 20 ms frame contains 480 samples or 960 bytes. Preserve codec and resampler state across provider packets.

Connect the call

Create one session after the provider's media start event and after validating its one-time call nonce:
ts
import LiveVoice from "@inkibra/voice-sdk/server"; const session = await LiveVoice.connect({ apiKey: process.env.INKIBRA_API_KEY!, audio: new ProviderAudioTransport(providerSocket), prompt: "Help callers schedule an appointment.", conversation: { starts: "assistant", prompt: "Be concise and confirm dates before booking.", }, tools: { bookAppointment: { description: "Book a confirmed appointment", parameters: { type: "object", properties: { startsAt: { type: "string" }, }, required: ["startsAt"], }, execute: async ({ startsAt }) => calendar.book(startsAt), }, }, }); await session.closed;
With apiKey, the SDK creates the short-lived session, opens and prepares the realtime connection, sends the developer configuration, executes server-side tools, and tears down both sides together. You can supply a short-lived token instead when your application creates sessions separately.

Input audio

Decode provider audio and call the handler with PCM16LE 24 kHz:
ts
const pcm8k = decodeMulaw(providerPayload); const pcm24k = inputResampler.push(pcm8k); for (const frame of frames(pcm24k, 480)) { handlers.input(new Uint8Array(frame.buffer)); }
Frame boundaries are transport boundaries, not conversational turns. Inkibra performs turn taking and canonicalization.

Output commands

The SDK calls audio.output(command) in order:
CommandProvider-adapter behavior
enqueue with mode: "play"Convert and enqueue the PCM for provider playback.
enqueue with mode: "buffer"Keep it private until the matching release.
block-foregroundKeep foreground audio from overtaking a reaction.
releaseRelease the named generation at the supplied gain.
cancelDiscard unsent audio and clear provider playback.
donePlace a provider playback mark after the generation's final audio.
A buffered generation is speculative. Sending it before release breaks interruption handling. Ignoring cancel can make the caller hear speech that Inkibra has already rejected.

Playback receipts

Report playback through the handlers passed to start:
ts
handlers.receipt({ event: "completed", // started | completed | cancelled lane: "FOREGROUND", // FOREGROUND | REACTION generationId, playedSamples, });
  • Send started when provider playout begins.
  • Send completed after the provider echoes the generation's mark.
  • Send cancelled after clearing provider playback.
  • Express playedSamples on Inkibra's 24 kHz sample clock.
Accurate receipts let Inkibra truncate interrupted assistant speech and keep the canonical transcript clean.

Close together

When the provider call ends, call handlers.close(reason). When the provider socket fails, call handlers.error(error). The server SDK stops the Inkibra session and the provider transport exactly once.
If Inkibra emits limit, a provider error, or closes the realtime socket, clear provider playback and end the call. Protocol version 1 treats a media disconnect as terminal; do not reconnect a new provider socket into the old session.

Production checklist

  • Validate the provider's signed HTTP callbacks.
  • Authenticate its media WebSocket with a one-time nonce bound to the provider call ID.
  • Keep Inkibra tokens out of provider XML, URLs, and logs.
  • Use a stateful codec and resampler.
  • Honor every output command and playback receipt.
  • Make hangup and status callbacks idempotent.
  • Test caller barge-in, quick reactions, tool calls, session limits, and teardown.