Skip to content

Conversation

@longcw
Copy link
Contributor

@longcw longcw commented Jan 22, 2026

when there is a speech generated alongside a tool call, the interruption to the speech shouldn't cancel the tool execution if it's await for an AgentTask.

Summary by CodeRabbit

  • Bug Fixes

    • Enhanced tool execution reliability by preventing premature cancellation when speech generation is active.
    • Improved speech pause handling with better state tracking and proper recovery after cancellation.
    • Enhanced task logging for better debugging of cancellation events.
  • Chores

    • Updated email example to use OpenAI GPT-4.1 Mini as the default LLM model.

✏️ Tip: You can customize this high-level summary in your review settings.

@chenghao-mou chenghao-mou requested a review from a team January 22, 2026 09:40
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 22, 2026

📝 Walkthrough

Walkthrough

This PR adds a SpeechHandle tool_cancelable flag and uses it to prevent mid-execution cancellations, renames/refactors paused-speech interruption APIs to _cancel_speech_pause (with an interrupt parameter), assigns names to tool-execution tasks, changes SegmentSynchronizerImpl.resume to a no-op after close, and switches the email example LLM to openai/gpt-4.1-mini.

Changes

Cohort / File(s) Summary
Tool execution safety
livekit-agents/livekit/agents/voice/speech_handle.py, livekit-agents/livekit/agents/voice/agent.py
Add _tool_cancelable + public tool_cancelable property on SpeechHandle. Agent code temporarily sets speech_handle.tool_cancelable = False while awaiting tool execution and restores the previous value in finally blocks to avoid race-condition cancellations.
Speech pause handling refactor
livekit-agents/livekit/agents/voice/agent_activity.py
Rename _interrupt_paused_speech_task_cancel_speech_pause_task, replace _interrupt_paused_speech(...) calls with _cancel_speech_pause(..., interrupt=...), add interrupt parameter, and unify forwarded_text/speech scheduling and interruption-reset logic across flows.
Task naming for tooling
livekit-agents/livekit/agents/voice/generation.py
Give the asyncio task created for tool execution a name (function call name) so cancellations/logging can reference the task name.
Transcription resume behavior
livekit-agents/livekit/agents/voice/transcription/synchronizer.py
SegmentSynchronizerImpl.resume now silently returns when called after close (removed runtime warning).
Example LLM change
examples/voice_agents/email_example.py
Change default LLM backend from google/gemini-2.5-flash to openai/gpt-4.1-mini.

Sequence Diagram(s)

sequenceDiagram
    participant Agent as Agent
    participant Speech as SpeechHandle
    participant Tool as Tool Task
    participant Finally as Finally

    Agent->>Speech: read tool_cancelable (old_state)
    Agent->>Speech: set tool_cancelable = False
    Note over Speech: prevents mid-execution cancellation

    Agent->>Tool: create named asyncio task (tool execution)
    Tool->>Tool: run tool logic
    Note over Tool: task runs without being cancelled by speech pause

    Tool-->>Agent: tool completes / returns result
    Finally->>Speech: restore tool_cancelable = old_state
    Note over Speech: original cancelability restored
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 A rabbit hops where code flags gleam,
I tuck cancels away behind a seam,
Tasks run named, safe from sudden stops,
Pauses canceled with gentler plops,
I nibble bugs and dance on logs—hip, hop! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.70% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'prevent tool cancellation when AgentTask is called inside it' is specific and directly describes the main change, which involves preventing tool cancellation during AgentTask execution to fix a deadlock issue.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

@longcw longcw changed the title fix deadlock when interrupting a tool that awaiting for AgentTask prervent tool cancellation when a AgentTask is called Jan 22, 2026
@longcw longcw changed the title prervent tool cancellation when a AgentTask is called prevent tool cancellation when AgentTask is called inside it Jan 22, 2026
Copy link
Member

@chenghao-mou chenghao-mou left a comment

Choose a reason for hiding this comment

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

LGTM. I tested with the email example, and it worked.

def resume(self) -> None:
if self.closed:
logger.warning("_SegmentSynchronizerImpl.resume called after close")
# logger.warning("_SegmentSynchronizerImpl.resume called after close")
Copy link
Member

Choose a reason for hiding this comment

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

It's been bugging me for a while!

# there should be only one message
msg_gen, text_out, audio_out = message_outputs[0]
if msg_gen:
forwarded_text = text_out.text if text_out else ""
Copy link
Member

Choose a reason for hiding this comment

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

we can probably remove this line

self._allow_interruptions = value

@property
def tool_cancelable(self) -> bool:
Copy link
Member

Choose a reason for hiding this comment

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

Can we add a comment here? It wasn't immediately clear to me why a speech handle has anything to do with the tool execution.

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.

3 participants