Skip to content

fix(code-review): pin a same-vendor small model for BYOK reviews - #6033

Closed
maphew wants to merge 6 commits into
Kilo-Org:mainfrom
maphew:fix/code-review-byok-small-model
Closed

maphew wants to merge 6 commits into
Kilo-Org:mainfrom
maphew:fix/code-review-byok-small-model

Conversation

@maphew

@maphew maphew commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Refs #4268.

Problem

A user set a BYOK model for Code Reviewer. The review itself used that model.
But Kilo credits still went down. The Kilo CLI used a separate small model for
title and auxiliary calls. The CLI fell through to kilo-auto/small. That
resolves to google/gemma-4-26b-a4b-it. The Gemma call goes through Kilo, not
the user provider.

Change

The web dispatcher now picks a cheaper model from the same vendor as the
effective review model. It uses the OpenRouter catalog and prompt prices.

  • A managed vendor uses the cheapest strictly-cheaper sibling.
  • A direct-BYOK vendor uses the primary BYOK model. The primary is used when
    the catalog has no cheaper BYOK sibling. This keeps the call on the user key.
  • A managed vendor with no cheaper sibling leaves small_model unset. The CLI
    keeps its current default in that case.

The value travels as smallModel from apps/web to the sandbox session
config. It is stored in the v2 session metadata. It is part of the create
intent fingerprint. The sandbox KILO_CONFIG_CONTENT gets small_model and
agent.title.model. This applies to code-review sessions only. Bitbucket
sessions do not get agent.title.

Relation to other work

Adversarial review

An independent review agent examined the diff against main. It found one
critical defect in the first revision. The Durable Object rebuilt
metadata.agent from a fixed field list. It dropped smallModel, so the fix
was inert. The fix now writes smallModel in registerSession and in the
admitted-plan agent. A new Durable Object integration test asserts the
persisted value. A second review pass confirmed that all findings are closed.

Verification

Passed:

  • pnpm run typecheck in apps/web, services/cloud-agent-next,
    services/code-review-infra, and packages/worker-utils.
  • oxlint and oxfmt --list-different on all changed files.
  • vitest run in services/cloud-agent-next for session-service.test.ts,
    session/session-prepare.test.ts, persistence/session-metadata.test.ts,
    and router/handlers/session-worktree.test.ts: 453 tests pass.
  • vitest run --config vitest.workers.config.ts for
    test/integration/session/code-review-small-model.test.ts and
    test/integration/session/start-execution-v2.test.ts: 41 tests pass.

Not run locally:

  • apps/web jest tests (model-selection.test.ts,
    prepare-review-payload.test.ts). The jest global setup needs a live
    PostgreSQL test database. The sandbox has no Docker and no database. CI
    covers these tests.

Code Review sessions let the Kilo CLI choose title and auxiliary models.
The CLI fell through to `kilo-auto/small`, which resolves to Gemma on
Kilo credits. This happened even when the user set a BYOK review model.
See issue Kilo-Org#4268.

Resolve a cheap model from the same vendor as the effective review model.
Use the OpenRouter catalog prices for managed vendors. Use the BYOK primary
model for direct-BYOK vendors when the catalog has no cheaper sibling.
Leave `small_model` unset when no cheaper managed sibling exists.

Thread the value from apps/web dispatch to the sandbox session config.
Persist it in the v2 session metadata. Include it in the create-intent
fingerprint. Add `small_model` and `agent.title.model` to the sandbox
KILO_CONFIG for code-review sessions only. Do not inject `agent.title` for
Bitbucket sessions.

Tests cover the resolver, payload plumbing, session materialization, the
metadata round trip, and the Durable Object registration boundary.
@maphew
maphew marked this pull request as ready for review September 10, 2026 01:43
@kilo-code-bot

kilo-code-bot Bot commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (19 files)
  • apps/web/src/lib/cloud-agent-next/cloud-agent-client.ts
  • apps/web/src/lib/code-reviews/core/model-selection.test.ts
  • apps/web/src/lib/code-reviews/core/model-selection.ts
  • apps/web/src/lib/code-reviews/triggers/prepare-review-payload.test.ts
  • apps/web/src/lib/code-reviews/triggers/prepare-review-payload.ts
  • packages/worker-utils/src/cloud-agent-next-client.ts
  • services/cloud-agent-next/src/execution/types.ts
  • services/cloud-agent-next/src/persistence/CloudAgentSession.ts
  • services/cloud-agent-next/src/persistence/session-metadata.test.ts
  • services/cloud-agent-next/src/persistence/session-metadata.ts
  • services/cloud-agent-next/src/router/handlers/session-prepare.ts
  • services/cloud-agent-next/src/router/schemas.ts
  • services/cloud-agent-next/src/session-service.test.ts
  • services/cloud-agent-next/src/session-service.ts
  • services/cloud-agent-next/src/session/session-prepare.test.ts
  • services/cloud-agent-next/src/session/session-registration.ts
  • services/cloud-agent-next/test/helpers/session-setup.ts
  • services/cloud-agent-next/test/integration/session/code-review-small-model.test.ts
  • services/code-review-infra/src/types.ts

Reviewed by grok-4.6 · Input: 123K · Output: 14K · Cached: 573.2K

Review guidance: REVIEW.md from base branch main

…k-small-model

Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com>
…k-small-model

Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com>
@eshurakov

Copy link
Copy Markdown
Contributor

Hey @maphew

I think the small-model choice belongs in the CLI as it already resolves the small model per request in Provider.getSmallModel (provider.ts#L1989): explicit small_model config, a plugin hook, kilo-* providers, then a family match (gemini-flash/gpt-nano/claude-haiku, L2113). The last step is an unconditional fallback to kilo-auto/small for any non-Azure provider (L2065) with no check that the active provider is Kilo-billed. That fallback is what pulls the credits, and titles, prompt enhance, commit messages, branch names and project copy all hit it through getSmallModel(pid) ?? getModel(pid, modelId).

CLI should have access to the model list as well so that we can pick a cheaper same-vendor model by price, could you take a look if we can fix it there for everyone?

maphew commented Sep 16, 2026

Copy link
Copy Markdown
Contributor Author

Good question — I agree the unconditional kilo-auto/small fallback in getSmallModel is the real root cause, and fixing it in the CLI would cover titles, prompt-enhance, commit messages and branch names for everyone, not just code review. This PR stays web-side deliberately as the narrow fix for #4268: the web dispatcher already knows the effective review model and the vendor catalog at dispatch time, so it can pin small_model per review session today with no CLI release coordination and no behavior change to the other aux-call paths. A CLI-side fix (vendor-aware fallback, or at least a Kilo-billed check before falling through to kilo-auto/small) is the right follow-up and would subsume this — happy to open that issue against Kilo-Org/kilocode and link it here, or close this in favor of it if you prefer the CLI fix first. Which do you want?

@eshurakov

Copy link
Copy Markdown
Contributor

@maphew because something similar already exists in the CLI, I think it should be there to avoid spreading similar logic in different places. It may be useful in the end for more than just a code reviewer.
My preference is to open a PR against the CLI with the minimal fix.
Thanks!

maphew commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

@eshurakov Agreed — done: the CLI-side fix is up as Kilo-Org/kilocode#14263. Provider.getSmallModel now picks the cheapest chat-capable model from the active provider's own catalog (models.dev prices, ties broken by release date/id) after the family match, so titles, prompt enhance, commit messages, branch names and project copy stay on the user's key; the creds-gated kilo-auto/small fallback only remains for providers with no chat-capable model at all. Family matching and explicit small_model config behave as before. Happy to close this PR in favor of the CLI one once that approach looks good to you.

@maphew maphew closed this Sep 17, 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.

2 participants