Skip to content

fix(voice/realtime): add tool_reply_after_audio to prevent duplicate speech#6480

Open
Utkarshsteve wants to merge 2 commits into
livekit:mainfrom
Utkarshsteve:fix/realtime-duplicate-tool-reply
Open

fix(voice/realtime): add tool_reply_after_audio to prevent duplicate speech#6480
Utkarshsteve wants to merge 2 commits into
livekit:mainfrom
Utkarshsteve:fix/realtime-duplicate-tool-reply

Conversation

@Utkarshsteve

Copy link
Copy Markdown

Summary

  • Adds a configurable tool_reply_after_audio policy to ToolHandlingOptions that controls whether the framework generates a post-tool reply when the realtime response already produced audible audio
  • Default is "always" (backwards-compatible); setting "skip" suppresses the duplicate reply
  • Exposes response_had_audio on FunctionToolsExecutedEvent so user handlers can inspect the signal

Problem

When a realtime model (e.g. xAI Grok) bundles audio output and a function_call in one response, the framework fires a post-tool reply after executing the tool — causing the agent to audibly answer twice (#6411).

Solution

Detection: after tool execution, check whether the triggering response produced audio that was actually played (started_speaking_at is not None and at least one message output wasn't skipped).

Guard: when tool_reply_after_audio == "skip" and audio was produced, skip the post-tool reply generation.

AgentSession(
    tool_handling={"tool_reply_after_audio": "skip"},
)

Test plan

  • Unit tests for event property defaults and mutation
  • Unit tests for ToolHandlingOptions config dictionary
  • Unit tests for AgentSession config storage (default, skip, always, empty dict)
  • make check passes (format, lint, mypy strict)
  • uv run pytest --unit — all 1132 + 10 new tests pass
  • Manual verification with xAI Grok realtime model (requires API key)

Closes #6411

The `with_azure` factory set `model="gpt-4o"` by default, but Azure
OpenAI uses `azure_deployment` to select models — the `model` parameter
is not used by the API. This caused the `.model` property to return
"gpt-4o" regardless of the actual deployment.

Change `model` to default to `None` and fall back to `azure_deployment`
so that `.model` reflects the real deployment name.

Closes livekit#6209
…licate speech

When a realtime model bundles audio output and a function_call in one
response, the framework's post-tool reply fires and the agent answers
twice. This adds a configurable `tool_reply_after_audio` policy on
`ToolHandlingOptions`:
- "always" (default): backwards-compatible, always generate reply
- "skip": suppress post-tool reply when audio was already delivered

Closes livekit#6411
@Utkarshsteve
Utkarshsteve requested a review from a team as a code owner July 18, 2026 12:46

@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

1 participant