Skip to content

fix(voice): agent and user state while a tool runs - #2311

Open
rosetta-livekit-bot[bot] wants to merge 1 commit into
port-tool-call-status-eventsfrom
port-fix-agent-user-state-tool-runs
Open

fix(voice): agent and user state while a tool runs#2311
rosetta-livekit-bot[bot] wants to merge 1 commit into
port-tool-call-status-eventsfrom
port-fix-agent-user-state-tool-runs

Conversation

@rosetta-livekit-bot

@rosetta-livekit-bot rosetta-livekit-bot Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Ports livekit/agents#6937.

Summary

  • keep blocking tools in thinking after preamble and filler speech finishes
  • suppress and restart the user-away window around in-flight tools
  • restore pipeline and realtime state when no tool reply follows
  • route tool lifecycle updates through the session so state and event delivery stay synchronized

Validation

  • pnpm exec vitest run agents/src/voice/agent_tool_state.test.ts agents/src/voice/realtime_agent_state_during_tool.test.ts agents/src/voice/agent_activity.test.ts agents/src/voice/generation_tools.test.ts (29 passed)
  • pnpm exec vitest run agents (1,062 passed, 2 skipped; 11 pre-existing failures in agents/src/voice/amd.test.ts, reproduced unchanged when that file runs alone)
  • pnpm build
  • pnpm lint (passes with existing warnings)
  • pnpm format:check
  • pnpm --filter @livekit/agents build:types
  • cue-cli: slow tool with filler produced AS_SPEAKING -> AS_THINKING, remained thinking for the six-second tool, emitted no US_AWAY, then delivered the tool reply

Source diff coverage

Source diff coverage
  • Ported: livekit-agents/livekit/agents/voice/agent_activity.py -> agents/src/voice/agent_activity.ts. Preserves pipeline, filler/say, realtime, server-generated reply, and no-reply state transitions.
  • Adapted: livekit-agents/livekit/agents/voice/agent_session.py -> agents/src/voice/agent_session.ts. Uses a session-scoped call ID set instead of Python weak-keyed _RunningTasks, and centralizes lifecycle event handling and away-window restart.
  • Adapted: livekit-agents/livekit/agents/voice/events.py -> agents/src/voice/run_context.ts. JS owns RunContext.update() in this file; updates now use the centralized session lifecycle hook.
  • Adapted: livekit-agents/livekit/agents/voice/tool_executor.py -> agents/src/voice/generation.ts. JS executes tools in performToolExecutions; started and ended updates now flow through the session hook.
  • Adapted: tests/fake_realtime.py -> the fake realtime model/session in agents/src/voice/realtime_agent_state_during_tool.test.ts, including controllable generation resolvers.
  • Adapted: tests/test_agent_session.py -> agents/src/voice/agent_tool_state.test.ts. Ports all four blocking, silent, deferred-away, and no-reply scenarios with deterministic Vitest timers.
  • Ported: tests/test_realtime_agent_state_during_tool.py -> agents/src/voice/realtime_agent_state_during_tool.test.ts. Ports all three realtime state scenarios.
  • Adapted: tests/test_tools.py -> agents/src/voice/generation_tools.test.ts. Mock sessions now expose the centralized lifecycle hook used by tool execution.
  • Not applicable: none.

Ported from livekit/agents#6937

Original PR description

Problem

A long tool call marks the user away, so the app asks "are you still there?" over the agent's own reply. The away timer arms whenever the agent and the user are both listening, and a tool call does not stop it. Filler speech ends in "listening" (livekit/agents#6904), and an async tool leaves the agent listening for its whole run (livekit/agents#6883). After the user is away, nothing restarts the window, so no further user_state_changed event fires in that session.

Fix

The away timer no longer arms while a tool runs, and the last tool to land restarts the window in full. The user never enters "away" during a tool call, so the state cannot stick there and livekit/agents#6883 needs no new API. Agent state separates the two cases: a blocking tool holds "thinking", and an async tool stays "listening" because the user can still speak. The realtime path also gains the state resets the pipeline already had, so a tool that asks for no reply hands the state back.

Based on livekit/agents#6908 by @VihaanAgarwal, with the review comments folded in.

close #6904 and close #6883

@changeset-bot

changeset-bot Bot commented Aug 21, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 21d6012

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 35 packages
Name Type
@livekit/agents Patch
@livekit/agents-plugin-anam Patch
@livekit/agents-plugin-assemblyai Patch
@livekit/agents-plugin-baseten Patch
@livekit/agents-plugin-bey Patch
@livekit/agents-plugin-cartesia Patch
@livekit/agents-plugin-cerebras Patch
@livekit/agents-plugin-deepgram Patch
@livekit/agents-plugin-did Patch
@livekit/agents-plugin-elevenlabs Patch
@livekit/agents-plugin-fishaudio Patch
@livekit/agents-plugin-google Patch
@livekit/agents-plugin-hedra Patch
@livekit/agents-plugin-hume Patch
@livekit/agents-plugin-inworld Patch
@livekit/agents-plugin-lemonslice Patch
@livekit/agents-plugin-liveavatar Patch
@livekit/agents-plugin-livekit Patch
@livekit/agents-plugin-minimax Patch
@livekit/agents-plugin-mistral Patch
@livekit/agents-plugin-mistralai Patch
@livekit/agents-plugin-neuphonic Patch
@livekit/agents-plugin-openai Patch
@livekit/agents-plugin-perplexity Patch
@livekit/agents-plugin-phonic Patch
@livekit/agents-plugin-resemble Patch
@livekit/agents-plugin-rime Patch
@livekit/agents-plugin-runway Patch
@livekit/agents-plugin-sarvam Patch
@livekit/agents-plugin-silero Patch
@livekit/agents-plugin-soniox Patch
@livekit/agents-plugin-tavus Patch
@livekit/agents-plugins-test Patch
@livekit/agents-plugin-trugen Patch
@livekit/agents-plugin-xai Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@rosetta-livekit-bot
rosetta-livekit-bot Bot requested a review from longcw August 21, 2026 07:53

@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.

0 participants