跳到正文
FunCoding

搜索

搜索文档、文章、Skill 和 MCP

Talk and realtime voice migration

Migrating realtime voice, telephony, and meeting code to the unified Talk session API

The unified Talk session controller, its supported session combinations, and the method map from the removed Talk families. Part of the Plugin SDK migration guide.

Talk and realtime voice migration

Realtime voice, telephony, meeting, and browser Talk code shares one Talk session controller exported by openclaw/plugin-sdk/realtime-voice. The controller owns the common Talk event envelope, active turn state, capture state, output-audio state, recent event history, and stale-turn rejection. Provider plugins own vendor-specific realtime sessions. Browser-meeting plugins use openclaw/plugin-sdk/meeting-runtime for session, browser, audio, node-host, agent-consult, and voice-call mechanics, then implement MeetingPlatformAdapter for URL rules, DOM scripts, manual-action mapping, captions, creation, and dial-in plans. Platform REST APIs, OAuth, artifacts, selectors, and wire names remain in the plugin. Browser permission plans receive the requested meeting URL so each platform can grant only its exact supported origins. Session runtimes must also normalize platform-specific live health after confirmed browser departure; historical transcript fields may remain, but caption and audio readiness must not stay active after leave.

All bundled surfaces run on the shared controller: browser relay, managed-room handoff, voice-call realtime, voice-call streaming STT, Google Meet realtime, and native push-to-talk. Gateway advertises one live Talk event channel in hello-ok.features.events: talk.event.

New code should not call createTalkEventSequencer(...) directly unless implementing a low-level adapter or test fixture. Use the shared controller so turn-scoped events cannot be emitted without a turn id, stale turnEnd / turnCancel calls cannot clear a newer active turn, and output-audio lifecycle events stay consistent across telephony, meetings, browser relay, managed-room handoff, and native Talk clients.

The public API shape:

// Gateway-owned Talk session API.
await gateway.request("talk.session.create", {
  mode: "realtime",
  transport: "gateway-relay",
  brain: "agent-consult",
  sessionKey: "main",
});
await gateway.request("talk.session.appendAudio", { sessionId, audioBase64 });
// Capture this before stopping playback from the active output `talk.event`.
const turnId = activeOutputTalkEvent.talkEvent.turnId;
await gateway.request("talk.session.cancelOutput", { sessionId, turnId, reason: "barge-in" });
await gateway.request("talk.session.submitToolResult", {
  sessionId,
  callId,
  result: { status: "working" },
  options: { willContinue: true },
});
await gateway.request("talk.session.submitToolResult", {
  sessionId,
  callId,
  result: { status: "already_delivered" },
  options: { suppressResponse: true },
});
await gateway.request("talk.session.submitToolResult", { sessionId, callId, result });
await gateway.request("talk.session.close", { sessionId });

// Client-owned provider session API.
await gateway.request("talk.client.create", {
  mode: "realtime",
  transport: "webrtc",
  brain: "agent-consult",
  sessionKey: "main",
});
await gateway.request("talk.client.toolCall", { sessionKey, callId, name, args });
await gateway.request("talk.client.steer", { sessionKey, text, mode: "steer" });

Browser-owned WebRTC/provider-websocket sessions use talk.client.create, because the browser owns provider negotiation and media transport while the Gateway owns credentials, instructions, and tool policy. talk.session.* is the common Gateway-managed surface for gateway-relay realtime, gateway-relay transcription, and managed-room native STT/TTS sessions.

Legacy configs that place realtime selectors beside talk.provider / talk.providers should be repaired with openclaw doctor --fix; runtime Talk does not reinterpret speech/TTS provider config as realtime provider config.

The supported talk.session.create combinations are intentionally small:

ModeTransportBrainOwnerNotes
realtimegateway-relayagent-consultGatewayFull-duplex provider audio bridged through the Gateway; tool calls route through the agent-consult tool.
transcriptiongateway-relaynoneGatewayStreaming STT only; callers send input audio and receive transcript events.
stt-ttsmanaged-roomagent-consultNative/client roomPush-to-talk and walkie-talkie style rooms where the client owns capture/playback and the Gateway owns turn state.
stt-ttsmanaged-roomdirect-toolsNative/client roomAdmin-only room mode for trusted first-party surfaces that execute Gateway tool actions directly.

Method map for readers migrating from the older talk.realtime.* / talk.transcription.* / talk.handoff.* families (all removed):

OldNew
talk.realtime.sessiontalk.client.create
talk.realtime.toolCalltalk.client.toolCall
talk.realtime.relayAudiotalk.session.appendAudio
talk.realtime.relayCanceltalk.session.cancelOutput
talk.realtime.relayToolResulttalk.session.submitToolResult
talk.realtime.relayStoptalk.session.close
talk.transcription.sessiontalk.session.create({ mode: "transcription" })
talk.transcription.relayAudiotalk.session.appendAudio
talk.transcription.relayCanceltalk.session.close
talk.transcription.relayStoptalk.session.close
talk.handoff.createtalk.session.create({ transport: "managed-room" })
talk.handoff.revoketalk.session.close

The unified control vocabulary is also deliberately narrow:

MethodApplies toContract
talk.session.appendAudiorealtime/gateway-relay, transcription/gateway-relayAppend a base64 PCM audio chunk to the provider session owned by the same Gateway connection.
talk.session.cancelOutputrealtime/gateway-relayStop assistant audio output without necessarily ending the user turn.
talk.session.submitToolResultrealtime/gateway-relayComplete a provider tool call after any asynchronous completion exposed by its bridge; pass options.willContinue for interim output or, when supported, options.suppressResponse to avoid another assistant response.
talk.session.steeragent-backed Talk sessionsSend spoken status, steer, cancel, or followup control to the active embedded run resolved from the Talk session.
talk.session.closeall unified sessionsStop relay sessions or revoke managed-room state, then forget the unified session id.

Do not introduce provider or platform special cases in core to make this work. Core owns Talk session semantics. Provider plugins own vendor session setup. Voice-call and Google Meet own telephony/meeting adapters. Browser and native apps own device capture/playback UX.