Skip to main content

Text chat

Open a text session when your app needs a typed conversation with no microphone or WebRTC setup. The SDK requests POST /api/v1/sessions/token with mode: 'text', connects the channel WebSocket, and routes your app's web_chat flow entry on the platform.

For the TelAPI wire format and REST upgrade/downgrade endpoints, see Browser SDK → Text chat.

Prerequisites

  • An endpoint whose flow includes a web_chat entry point (visible in TelWeb under the endpoint's entry-point configuration).
  • DelphiClient configured with apiDomain + apiKey, or a same-origin sessionTokenUrl proxy.
  • Platform webrtc flag on (gates all SDK session routes, including text-only).

Check support before opening UI:

const caps = await delphi.getCapabilities(endpointId);

if (!caps.interactionModes.text) {
throw new Error('This endpoint does not support text chat.');
}

const canHandoff =
caps.runtime.migration.includes('text_to_voice') &&
caps.runtime.migration.includes('voice_to_text');

Minimal example

const session = await delphi.openSession({
endpointId: '24599c70-1e79-4e52-9819-e2d97acf45a5',
mode: 'text',
});

session.onChat((chat) => {
if (chat.role === 'assistant') {
console.log('AI:', chat.content);
}
});

session.sendTextChat('Hello — what can you help me with?');

sendTextChat sends a chat message with intent: 'conversation' and expects a text reply. For full control (context-only updates, read-aloud intents, preferred response mode), use sendChat() — see the API reference.

React — useDelphiSession

import {useDelphiSession} from '@ki-kombinat/delphi-client-js-sdk/react';

function ChatPanel({endpointId}: {endpointId: string}) {
const {connected, messages, sendTextChat} = useDelphiSession({
endpointId,
mode: 'text',
});

const [input, setInput] = useState('');

const visible = messages.filter(
(m) => m.type === 'chat' && m.chat?.content && m.chat.intent !== 'browser_context',
);

return (
<div>
{!connected && <p>Connecting…</p>}
<ul>
{visible.map((m) => (
<li key={m.messageId}>{m.chat!.content}</li>
))}
</ul>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={(e) => {
if (e.key === 'Enter' && input.trim()) {
sendTextChat(input.trim());
setInput('');
}
}}
/>
</div>
);
}

Attach <DelphiProvider> at the app root with the same DelphiClient instance — same pattern as the voice quick start.

Page context without a reply

Keep the AI aware of what the user sees:

session.setBrowserContext({
text: document.body.innerText.slice(0, 4000),
identifier: window.location.pathname,
source: 'page',
});

This sends intent: 'browser_context' with responseExpected: false — no assistant turn is triggered.

Upgrade to voice

When the flow supports both web_chat and web_voice, migrate the live text session to a WebRTC call on the same sessionId:

delphi.setRemoteAudioElement(document.querySelector('#remote-audio')!);

await delphi.upgradeToVoice({
endpointId,
autoDial: true, // dial as soon as the SIP plugin registers
browserContext: {identifier: 'browser-user-1'}, // optional, sent before dial
});

What the SDK does internally:

  1. Confirms an open text session for endpointId.
  2. POST /api/v1/sessions/upgrade with the current sessionId.
  3. Closes the text WebSocket and opens voice_conversation with the upgraded token.
  4. Re-imports prior chat messages into the new session for UI continuity.
  5. Connects WebRTC using telproDomain / webrtcGatewayUrl from the upgrade response.

Attach the remote <audio> element before calling upgradeToVoice (same rule as Voice call).

Downgrade to text

Switch back to typed chat after a call:

const session = await delphi.downgradeToText({
endpointId,
endCallFirst: true, // default — hang up WebRTC before reopening text
});

session.sendTextChat('Thanks — can you summarise what we discussed?');

The SDK sends prepare_voice_to_text_handoff on the channel, calls POST /api/v1/sessions/downgrade, tears down WebRTC, and reopens mode: 'text' with the same sessionId.

Text overlay on a voice call (no migration)

If the user is already in a voice_conversation and you only want a typing panel alongside the call — without changing session mode:

const session = await delphi.startCall({endpointId, autoDial: true});

session.enableTextChat('text'); // AI replies in text; user can still speak
session.sendTextChat('Please email me the confirmation number.');

// later
session.disableTextChat();

Use upgradeToVoice / downgradeToText when the primary transport should switch between text-only and full voice. Use enableTextChat when voice remains the main session and text is auxiliary input.

Cleanup

await delphi.endSession(endpointId, 'text');
// or, if upgraded: await delphi.endCall()

Non-voice sessions also auto-close after sessionIdleTimeoutMs (default 5 minutes) when idle.

Common gotchas

  • openSession({ mode: 'text' }) fails with 409 — endpoint flow lacks a web_chat entry or the endpoint is archived.
  • Upgrade returns 503FEATURE_WEBRTC=false or TelPro is not configured on the deployment.
  • No assistant reply to typed text on a voice call — call enableTextChat() first; by default voice sessions ignore chat unless text-chat mode is enabled.
  • Stale getSession(endpointId) after handoff — pass the mode: getSession(endpointId, 'text') vs 'voice_conversation'.

Next step

Voice call — start directly in voice_conversation when you do not need a text-first UX.