Skip to content

fix(llm): select container union defaults by item schema - #8240

Draft
Ramcharan49 wants to merge 1 commit into
livekit:mainfrom
Ramcharan49:fix/container-union-tool-defaults-20261029
Draft

Ramcharan49 wants to merge 1 commit into
livekit:mainfrom
Ramcharan49:fix/container-union-tool-defaults-20261029

Conversation

@Ramcharan49

@Ramcharan49 Ramcharan49 commented Oct 29, 2026 •

Copy link
Copy Markdown

When a tool accepts requests: list[EmailRequest] | list[SMSRequest], the null-default resolver currently selects the first array schema without checking its elements. With defaults of 2 and 5 retries respectively, [{"kind":"sms","retries":null}] becomes an SMS request with 2 retries: Pydantic chooses the SMS model after the wrong default has already been inserted, so validation succeeds with silently changed behavior.

Check items and positional prefixItems recursively when selecting a default-injection variant. This selects the SMS default of 5 and also handles nested lists and tuple arguments. If no variant matches the item schemas strictly, retain the previous shape-only fallback so existing Pydantic-coercible input can still receive defaults.

This follows the null-sentinel contract from merged #6444.

Validation on base 18c07ba0482d90093b361cb566b573a27e389515 (Python 3.12.14, Linux; dependencies installed from uv.lock):

  • Final new regression suite against unchanged main: 4 failed, 6 passed. Each failure demonstrates the SMS tool receiving 2 instead of 5.
  • Patched regression and related tool/session/schema suites: 417 passed across 12 modules. The new tests execute the prepared tools, validate list-shaped examples against their advertised strict schema, preserve genuine nullable values and input payloads, and cover explicit/omitted defaults plus non-strict numeric coercion.
  • Repository-wide Ruff check and format check: pass (ruff 0.15.22, 1,207 files).
  • Focused strict mypy: python -m mypy --follow-imports=silent --platform linux -m livekit.agents.llm.utils passes (mypy 2.3.0). Python 3.10 syntax parsing and git diff --check pass.
  • The patch was reviewed in a separate pass and the checks above were rerun after the final edits.

CI on exact head 20974007bd6866e4090c36b3b6c69b18e346215b: Ruff, the release gate, and blockguard on Ubuntu/macOS/Windows pass. Unit-test collection and Python 3.13 all-plugin type checking fail on the pre-existing Thunderphone _shorten_call_id import after its upstream rename to _shorten_id; the Python 3.10 matrix job was cancelled. The relevant files are byte-identical to the tested base, and the import failure was reproduced in a clean worktree of that base. Existing upstream PR #8229 addresses it; this PR does not duplicate that fix.

Limits: the existing matcher remains a shape/literal heuristic, not a complete JSON Schema or Pydantic union validator. Ambiguous variants and variants requiring coercion retain the existing fallback behavior. No live providers or paid APIs were called. Full all-plugin type checking and the whole unit/audio suite were not run.

AI assistance: OpenAI Codex investigated, implemented and reviewed the patch, and executed the validation above. No personal human review is asserted. This PR is intentionally a draft; no CLA agreement has been accepted by this automated task.

Inspect array items before resolving union defaults, preserving the prior
shape-only fallback for Pydantic-coercible inputs.

AI-assisted investigation, implementation, review and local validation by
OpenAI Codex. New regression suite: 4 failures on main; related suites: 417 pass.

This branch has not been deployed

No deployments
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