Skip to content

feat(agent): add update_models() to swap STT/VAD/LLM/TTS at runtime#6440

Open
longcw wants to merge 1 commit into
mainfrom
longc/agent-update-models
Open

feat(agent): add update_models() to swap STT/VAD/LLM/TTS at runtime#6440
longcw wants to merge 1 commit into
mainfrom
longc/agent-update-models

Conversation

@longcw

@longcw longcw commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Agent.update_models(*, stt, vad, llm, tts) swaps a model in place. Only the models passed are changed; strings resolve to inference models like the constructor, and None disables a model (overriding the session), matching Agent(stt=None).

When the agent isn't running it replaces the stored model, applied on the next start. When running, it applies to the live pipeline: the STT and VAD streams are rewired, the LLM and TTS take effect on the next generation and synthesis respectively, and each model's metrics_collected/error listeners follow the new instance. The call is synchronous and atomic.

The Agent is the source of truth — the activity resolves agent.<model> if given else session.<model> live — so update_models just writes to the agent. This is distinct from AgentSession.update_agent (full handoff, new instance) and from a model's own update_options (same instance, provider options).

Alternative to #6235

Realtime models

A RealtimeModel owns a live session created when the agent starts, so it can't be swapped in place. While running, passing a RealtimeModel as llm (or swapping away from one) raises RuntimeError pointing to AgentSession.update_agent. Validation happens before any mutation, so the call stays all-or-nothing.

Agent.update_models(*, stt, vad, llm, tts) swaps a pipeline model in place, for cases like changing the STT language or TTS voice mid-call without a full agent handoff.

When the agent isn't running it replaces the stored model; when running it applies to the live pipeline: STT/VAD streams are rewired, LLM/TTS take effect on the next generation/synthesis, and metrics/error listeners follow the new model. None disables a model, matching Agent(stt=None).

Swapping to or from a RealtimeModel while running raises (its session is created at start); use AgentSession.update_agent instead. Adds KeytermDetector.swap_stt to rebind the recognizer in place so the swap stays synchronous.
@longcw longcw requested a review from a team as a code owner July 15, 2026 12:58

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 2 additional findings.

Open in Devin Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant