Skip to content

Move default, Auto and test-agent model calls onto the Anthropic BYOK key, with a no-fallback guard - #220

Merged
Programcode merged 4 commits into
mainfrom
chore/ai-costs-haiku-byok
Oct 23, 2026
Merged

Programcode merged 4 commits into
mainfrom
chore/ai-costs-haiku-byok

Conversation

@Programcode

@Programcode Programcode commented Oct 23, 2026 •

Copy link
Copy Markdown
Owner

Moves DebateLab's own model spend onto the Anthropic key (BYOK in OpenRouter, covered by Adam's Claude plan) and adds a guard so non-Anthropic models and provider fallbacks can't creep back in. Do not merge or deploy without Adam's OK.

What #185 already did (confirmed on main)

  • DEFAULT_MODEL = anthropic/claude-haiku-5.5 (Basic), DEFAULT_PRO_MODEL = anthropic/claude-sonnet-5.5 (Pro), BACKGROUND_MODEL (research sub-steps) = Haiku 5.5.
  • openRouterProviderOptions() sends { only: ["anthropic"], allow_fallbacks: false, require_parameters: true } for every anthropic/ model, in both ai and ai-stream. No call site sends an OpenRouter models fallback array.
  • anthropic/claude-haiku-5.5 is the newest Haiku on GET /api/v1/models (Anthropic is one of its providers; tools, tool_choice, structured outputs and image input are supported there).

So the app's default traffic was already on BYOK. The non-Anthropic spend came from the test harness and from Auto routing. This PR fixes those.

Call sites

Call site Before After Why
App default, Basic (DEFAULT_MODEL, ai + ai-stream) Haiku 5.5, Anthropic-pinned unchanged already BYOK
App default, Pro (DEFAULT_PRO_MODEL) Sonnet 5.5, Anthropic-pinned unchanged kept on Sonnet, see below
Research sub-steps (BACKGROUND_MODEL) Haiku 5.5 unchanged already BYOK
Auto Fast (auto-model-router.ts) Jev picks among Haiku 5.5 / GPT-6 Luna / Muse Spark 1.3 Contributor always Haiku 5.5, no Jev call GPT and Muse bill OpenRouter credits; the Jev call itself also billed credits
Auto Pro Jev picks among Sonnet 5.5 / GPT-6.1 Sol always Sonnet 5.5, no Jev call same; still never Opus
Agentic e2e actor (e2e.config.ts) inclusionai/ling-3.0-flash-vl (Novita/DeepInfra, with fallback) anthropic/claude-haiku-5.5, only: ["anthropic"], allow_fallbacks: false OpenRouter credits → BYOK
Agentic e2e judge (e2e.config.ts) meta/muse-spark-1.3-contributor anthropic/claude-haiku-5.5, pinned the same way most of the ~4K Muse Spark requests
Live verify pin (verify.sh up --live, VERIFY_LIVE_MODEL) meta/muse-spark-1.3-contributor anthropic/claude-haiku-5.5; non-anthropic/ refused OpenRouter credits → BYOK
Live gate pin (db-gate.sh, live-e2e.yml via LIVE_MODEL) meta/muse-spark-1.3-contributor anthropic/claude-haiku-5.5; only anthropic/* or as-requested same
Live proxy (fake-openrouter.mjs) stripped only/allow_fallbacks when rewriting the model re-applies the Anthropic pin to every Claude call, drops any models list, refuses a non-Claude LIVE_MODEL at startup a rewrite could otherwise run Claude on Bedrock/Vertex or credits
scripts/prompt-examples.ts default openai/gpt-6-luna anthropic/claude-haiku-5.5 manual script; default now BYOK
Crossfire signal + source ranking (callJev, typesafe/jev-1.13) Jev unchanged Jev is OpenRouter's decisions model, not a chat model; there's no Anthropic equivalent. Small; flagged below
Model matrix (model-matrix.yml, LIVE_MODEL=as-requested) every catalog model unchanged (the one allowed exception) its job is to check each user-pickable model; Actions minutes are out anyway
Student picks GPT / Gemini / DeepSeek / GLM / Muse by hand that model unchanged a deliberate choice, not a fallback. Product call, see below

Kept on Sonnet or Opus

  • Pro default = Sonnet 5.5. Pro users pay for better debate writing (cases, rebuttals, adjudication). Sonnet already runs on BYOK, so there's no OpenRouter-credit cost to keeping it.
  • Auto Pro = Sonnet 5.5. Same reason.
  • Opus 5.5: only when a Pro user picks it by hand (unchanged; Auto never routes or falls back to it). Also BYOK.
  • Everything else (Basic default, Auto Fast, research sub-steps, the whole e2e/live harness) is on Haiku 5.5.

Anti-fallback guarantees

  • Every anthropic/ request carries provider: { only: ["anthropic"], allow_fallbacks: false }, both from the app and from the test agent and live proxy. No models fallback arrays anywhere.
  • Auto pools contain only anthropic/ models. With one model per pool the Jev router isn't called.
  • e2e.config.ts, verify.sh, db-gate.sh and the live proxy fail loudly if a non-anthropic/ model is configured (env var or repo variable), instead of quietly billing credits. The only exception is LIVE_MODEL=as-requested (model matrix).
  • New guard src/test/ai/anthropic-only-guard.test.ts (runs in npm test) fails if: a default/background model isn't Claude; Claude isn't pinned to only: ["anthropic"] + allow_fallbacks: false; an Auto candidate isn't anthropic/; the e2e actor/judge default or pin changes; the verify/gate/proxy defaults or refusals change; or any non-test source under supabase/functions, scripts, agentic, e2e, the verify skill, src/lib or e2e.config.ts has allow_fallbacks: true or a models: [...] list with a non-Claude entry. I mutation-checked it: adding GPT-6 Luna to Auto Fast and an allow_fallbacks: true + mixed models list both failed it.
  • auto-model-router.test.ts rewritten: the Auto pools are Claude-only and skip Jev; the Jev routing logic is still covered through routeAmongCandidates with a two-Claude test pool.

Verify (VPS, fresh clone of main at 3aa123a + this commit)

  • npm run verify: pass. docs:check, lint, typecheck, vitest 592/592 (82 files), collaboration 30/30, Deno edge 457/457, build, service-worker test, Playwright smoke 47/47.
  • Agentic e2e on the new models (verify.sh up in fake mode, then e2e run agentic/ai-tools.e2e.ts:8 :47 --target desktop): 2/2 pass, judge openrouter/anthropic/claude-haiku-5.5, 2 model calls, 6.3k tokens, reported $0.0000 (BYOK). Both agent.act steps replayed from cache, so the actor wasn't exercised live.
  • Not run: e2e/live, the full agentic suite, and the model matrix (they need Actions or a full live run).

Config / secrets

  • No Supabase secret or Edge Function env change is needed. No Edge Function reads a model from env; the change is code-only. It takes effect for the app when the ai and ai-stream functions are next deployed. Note: this PR doesn't deploy anything.
  • GitHub repo variables E2E_AGENT_MODEL, E2E_JUDGE_MODEL and LIVE_MODEL are unset (checked), so the new defaults apply. If someone sets one to a non-Claude model, the run now fails instead of spending credits.
  • OpenRouter dashboard (recommended, not changed): on the Anthropic BYOK key, turn on "Always use this key" / "Never use shared capacity". allow_fallbacks: false stops other providers, but only that setting stops OpenRouter from serving Anthropic on its own credits if the BYOK key errors. The app already logs claude_not_byok when that happens.
  • The lab key needs no change.

Risks

  • Haiku quality for the test judge: the judge decides every agent.assert/waitFor/extract. Haiku passed the two journeys above, but the full suite (about 250 judgments) hasn't run on it. Expect a few judgments to flake until they're tuned. The actor (only used on cache misses and in explorations) is untested live on Haiku.
  • Live-mode pin check: recipes/fixtures.ts requires OpenRouter's reply model to start with LIVE_MODEL. If OpenRouter answers Haiku 5.5 with a dated id, live recipes would flag it. Not testable without a live run.
  • Auto quality and latency: Auto Fast no longer sends long-context or multilingual work to Muse Spark (943K context). Haiku 5.5's 128K window is the cap for Auto Fast now. Auto also skips one Jev round trip, so it's a bit faster.
  • Anthropic is a single provider: with fallbacks off, an Anthropic outage or an exhausted Max/API allowance fails Claude calls (existing provider_unavailable handling) instead of failing over. That now also applies to the e2e judge and live verification.
  • Debate-content quality: the Basic default was already Haiku, so student-facing quality only changes for Auto users (above).

Expected effect

Based on the last-30-day OpenRouter numbers (~$39 total): the e2e and live-verify traffic, including Muse Spark 1.3 Contributor (~4K requests, $2.04), the Ling actor, and the Auto-routed GPT/Muse calls, moves onto the Anthropic BYOK key. Opus 5.5 ($15.90) and Sonnet 5 ($11.10) were already BYOK. Non-Anthropic OpenRouter spend from DebateLab's own defaults, Auto routing and test tooling should go to about $0.

What stays on OpenRouter credits:

  • Jev decisions for crossfire signals and source ranking.
  • Students who pick a non-Claude model by hand.
  • The weekly model matrix, if Actions runs.
  • OpenRouter's BYOK fee, if the monthly BYOK allowance is passed.

Overlap with in-flight work

Follow-up for Adam (not in this PR)

Should Basic users still be offered GPT-6 Luna and Muse Spark 1.3, and Pro users GPT/Gemini/DeepSeek/GLM, in the model picker? Those are the only way app traffic can still bill OpenRouter credits. Removing them is a UI/product change.

Summary by CodeRabbit

  • New Features

    • Auto Fast now uses Claude Haiku 5.5, while Auto Pro uses Claude Sonnet 5.5.
    • Automatic model selection is limited to Claude models; Auto Pro remains available to Pro accounts.
  • Improvements

    • Model selection now skips extra routing when only one model is available.

…opic BYOK key

- Auto Fast and Auto Pro route only to Claude (Haiku 5.5, Sonnet 5.5) and skip the Jev routing call
- agentic e2e actor and judge move to anthropic/claude-haiku-5.5 pinned to the Anthropic provider
- live verification and the live gate default to Claude Haiku and refuse non-Anthropic models
- the live proxy pins rewritten Claude calls to Anthropic with allow_fallbacks false
- new guard test fails on a non-Anthropic default, Auto candidate, test model, allow_fallbacks true, or a non-Claude models list
Copilot AI balanced review requested due to automatic review settings October 23, 2026 08:30

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

ℹ️ Recent review info
⚙️ Run configuration
📥 Commits

Reviewing files that changed from the base of the PR and between 79cb1f8 and 3c44cea.

📒 Files selected for processing: 17
  • .claude/skills/verify-debatelab/SKILL.md
  • .claude/skills/verify-debatelab/bin/verify.sh
  • .claude/skills/verify-debatelab/features/README.md
  • .claude/skills/verify-debatelab/features/model-defaults.md
  • .superset/db-gate.sh
  • AGENTS.md
  • agentic/support/anthropic-cache.ts
  • docs/architecture.md
  • docs/testing.md
  • e2e.config.ts
  • e2e/full-stack/fake-openrouter.mjs
  • scripts/prompt-examples.ts
  • src/test/ai/anthropic-cache-breakpoints.test.ts
  • src/test/ai/anthropic-only-guard.test.ts
  • supabase/functions/_shared/auto-model-router.test.ts
  • supabase/functions/_shared/auto-model-router.ts
  • supabase/functions/ai/handler-research.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

📝 Walkthrough

The change updates automatic model selection and verification defaults to Anthropic Claude models. It adds Anthropic routing restrictions for live and agentic calls, adjusts cache-breakpoint handling for tool messages, and updates related tests and documentation.

Changes: Anthropic model routing and verification

Layer / File(s) Summary
Automatic model pools and routing
supabase/functions/_shared/auto-model-router.ts, supabase/functions/_shared/auto-model-router.test.ts, supabase/functions/ai/handler-research.test.ts, docs/architecture.md
Auto Fast uses Claude Haiku 5.5 and Auto Pro uses Claude Sonnet 5.5. Single-candidate pools skip Jev; multi-candidate routing uses the shared routing path and fallback handling.
Agentic test models and cache handling
agentic/support/anthropic-cache.ts, e2e.config.ts, src/test/ai/anthropic-cache-breakpoints.test.ts, src/test/ai/anthropic-only-guard.test.ts, docs/testing.md, .claude/skills/verify-debatelab/...
The actor and judge use Anthropic Haiku 5.5 and Sonnet 5.5 with fallbacks disabled. The cache wrapper moves eligible tool-message breakpoints to the final content part. Tests and guidance cover these configurations and behaviors.
Live verification model restrictions
.claude/skills/verify-debatelab/..., .superset/db-gate.sh, e2e/full-stack/fake-openrouter.mjs, scripts/prompt-examples.ts, AGENTS.md, src/test/ai/anthropic-only-guard.test.ts, docs/testing.md
Live verification defaults to Claude Haiku 5.5. The scripts and proxy restrict model overrides, and the proxy removes fallback model lists and applies Anthropic-only routing to Anthropic requests. Documentation and guard tests describe or check the restrictions.

Estimated code review effort: 3 (Moderate) | ~25 minutes

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Essentials by visiting https://app.coderabbit.ai/settings/billing.

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

The OpenRouter provider copies a tool message's cache breakpoint onto every tool result, so an actor turn with parallel tool calls sent Anthropic 5-6 breakpoints and failed. Move it onto the last result.
A Haiku judge failed 23 of 180 checks on a fake-mode run; Sonnet passed 21 of those 23 with the same Haiku actor. Both stay pinned to Anthropic (BYOK) with fallbacks off.
@Programcode
Programcode merged commit 073dd08 into main Oct 23, 2026
3 of 14 checks passed
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