Repository navigation
Conversation
Add zoom_ai.realtime.RealtimeModel, a speech-to-speech model on the Zoom Voice Agent live-session WebSocket API (voice-agent.zoom.v2). - one complete session.update as the first event, sent once the agent has supplied its instructions and tools - 16 kHz PCM16 audio in and out; server-side turn detection and barge-in - function calls, function_call_output, and the follow-up reply - reply requests queued while a response is active - interrupt/truncate via response.cancel and conversation.item.truncate - pre-session history (handoffs, reconnects after the 60-minute limit) carried over in the instructions - bring-your-own OpenAI/Anthropic key via provider_headers Includes hermetic tests against a fake Voice Agent server, a three-agent handoff example, and README docs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- examples/voice_agents/zoom_voice_agent.py: a single speech-to-speech agent with a function tool; needs only ZOOM_AI_API_KEY. Tested live in console mode. - the three-agent handoff example moves to zoom_multi_agent.py - README: link both examples and document the zoom_server_event_received debugging event Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Send users to zoom.ai to sign up, create an API key and see pricing, keeping Platform Studio as the alternative for existing accounts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review fixes:
- A session.update only changes the fields it carries, so clearing
tool_choice, instructions, vocabulary or response_token_limit after it
was sent left Zoom on the old value. AgentActivity hits this when it
restores tool_choice to None after a forced-tool turn. Once a setting
has been sent on a connection, clearing it now sends its reset value
("auto", "", [], "inf"). The first update still leaves unset options
out so Zoom's defaults apply.
- Before the conversation starts, update_chat_ctx now replaces the
history as a whole, so removed or edited items no longer linger in the
instructions. An unchanged history sends nothing.
- Examples no longer log caller order numbers.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
zoom_ai.realtime.RealtimeModeltolivekit-plugins-zoom-ai. It's a speech-to-speech model on the Zoom Voice Agent API: one WebSocket (voice-agent.zoom.v2) carries the caller's audio in and the agent's speech, transcripts and function calls out.It works as the model of a whole session or of one agent in a multi-agent handoff.
How it maps onto the framework
session.update(listen/think/speak). The plugin connects only once the agent has supplied its instructions and tools, then sends one update instead of the framework's incremental three.turn_detection=True,can_disable_turn_detection=False).response.function_call_arguments.done, the result goes back as afunction_call_outputitem, andresponse.createasks for the follow-up reply (auto_tool_reply_generation=False).generate_reply()requests are queued untilresponse.done. The "active response" error is handled, including the race where a server-started response answers the request.interrupt()sendsresponse.cancelwith the response ID, andtruncate()sendsconversation.item.truncate.mutable_chat_context=False). History that exists before the session starts, from a handoff or a reconnect after the 60-minute session limit, is added to the instructions.session.update(for example an unknown voice) ends the session with an unrecoverable error instead of leaving the agent silent. Handshake errors don't include the request headers, so the API key never appears in them.provider_headers.Instructions and tools can change mid-session through
session.update. Per-reply instructions aren't supported by the API; they're ignored with a one-time warning.Changes
livekit-plugins/livekit-plugins-zoom-ai/livekit/plugins/zoom_ai/realtime/: new realtime modeltests/test_plugin_zoom_ai_realtime.py: 22 hermetic unit tests against a fake Voice Agent server, including oneAgentSessiontool turn end to endexamples/voice_agents/zoom_voice_agent.py: a Zoom-only agent with a function toolexamples/voice_agents/zoom_multi_agent.py: three agents handing off (pipeline, OpenAI Realtime, Zoom)Testing
uv run pytest tests/test_plugin_zoom_ai_realtime.py tests/test_plugin_zoom_ai_stt.py --unit: 110 passeduv run pytest --unit --audio_eot: no new failures. The failures seen locally also happen onmainor come from the local environment: the Azure Voice Live SDK isn't installed, a Google credentials test fails onmaintoo, and one worker-status test is flaky under parallel load.make checkstyle: ruff format/lint clean, and strict mypy clean forlivekit.plugins.zoom_aiThe Voice Agent docs don't list the fields of
conversation.item.input_audio_transcription.completedor ofresponse.doneusage. The plugin readsitem_id/transcriptandusage.input_tokens/output_tokens, with fallbacks.🤖 Generated with Claude Code