Skip to content

voice: retry missing run outputs - #1978

Merged
toubatbrian merged 2 commits into
mainfrom
stifling-deletion-balk
Jul 7, 2026
Merged

voice: retry missing run outputs#1978
toubatbrian merged 2 commits into
mainfrom
stifling-deletion-balk

Conversation

@rosetta-livekit-bot

@rosetta-livekit-bot rosetta-livekit-bot Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Validation

  • pnpm build
  • pnpm vitest run agents/src/voice/testing/run_result.test.ts
  • pnpm eslint agents/src/_exceptions.ts agents/src/voice/agent_session.ts agents/src/voice/index.ts agents/src/voice/testing/index.ts agents/src/voice/testing/run_result.ts (passes with one pre-existing warning in agent_session.ts:343)
  • cue-cli text-mode smoke against a temporary JS worker: greeting and user turn resolved with assistant conversation_item_added framework events

Notes

  • Did not add tests because the source PR did not add tests.
  • pnpm api:check is blocked by existing repo issues: missing api-extractor.json in some plugin packages; focused pnpm --filter @livekit/agents api:check is blocked by the existing API Extractor limitation on export * as ___ in dist/index.d.ts.

Ported from livekit/agents#6080

Original PR description

A run with an output_type ends with final_output=None whenever the model finishes its turn in prose instead of calling the task's completion tool — common with chatty models, and currently surfaced as a generic RuntimeError that callers can't distinguish or recover from.

Following pydantic-ai's output-tool semantics:

  • New output_options on run() (an options TypedDict in the style of keyterm_options/expressiveness): when the run ends without its output_type, the session re-prompts in the same context as a per-turn system message (max_retries, default 2) before raising; retry_instructions overrides the built-in retry prompt.

    result = await sess.run(
        user_input=...,
        output_type=SummarizeOutput,
        output_options={"max_retries": 2, "retry_instructions": "Call submit_analysis, nothing else."},
    )
  • A distinct UnexpectedModelBehavior (exported from livekit.agents, same name as pydantic-ai's) replaces the generic RuntimeError once the budget is exhausted, so callers can catch the failure specifically.

Defaults convert the dominant failure (model summarizes in prose) into a recovered run. Unit tests cover recovery, the prompt override, and exhaustion via FakeLLM.

🤖 Generated with Claude Code

@rosetta-livekit-bot
rosetta-livekit-bot Bot requested a review from a team as a code owner July 7, 2026 06:21
@changeset-bot

changeset-bot Bot commented Jul 7, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 129a15c

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

This PR includes changesets to release 36 packages
Name Type
@livekit/agents Patch
@livekit/agents-plugin-anam Patch
@livekit/agents-plugin-anthropic 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 theomonnom July 7, 2026 06:22

@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 bugs or issues to report.

Open in Devin Review

- Surface a failed retry generateReply (e.g. session closing) as the
  UnexpectedModelBehavior rejection's cause instead of hiding it behind
  the schema-mismatch message
- Fall back to the zod schema class name in the retry warning; .description
  is undefined for schemas without .describe()
- Remove unreachable try/catch around the retry warning (a RunResult with a
  session always has an initialized logger)
- Document that outputOptions: null disables retries, and the deliberate
  divergence from Python: a task completed with null is not retryable
- Add tests covering retry-then-success, retry exhaustion, the null opt-out,
  and custom maxRetries/retryInstructions

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@toubatbrian
toubatbrian merged commit 92d7244 into main Jul 7, 2026
9 checks passed
@toubatbrian
toubatbrian deleted the stifling-deletion-balk branch July 7, 2026 08:45
@github-actions github-actions Bot mentioned this pull request Jul 7, 2026
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