Change: Anthropic joins the agent fleet. Claude Opus 5 launched 2026-07-24 and Sonnet 5 is on introductory pricing, which moved the seat economics enough to crown Anthropic into four seats and re-point one shared alias. Chasing the eval evidence for those seats then uncovered Bug-2926: Indigo has been silently running a two-model panel while paying for a three-model one. Both land here.
| Agent · seat | Was | Now | Proven? |
|---|---|---|---|
| Indigo judge — fallback leg | moonshot-judge | anthropic-sonnet | ✅ forced probe: salvaged 28, dropped 0 |
Indigo eval_candidates.judge | [moonshot-judge, gpt-5.6-sol] | [anthropic-opus, gpt-5.6-sol] | ⚪ config only |
| Mira synthesizer | minimax-mid | CHAIN [kimi-coding:k3 → minimax-mid] | ⚪ not live-sampled |
Vega judges.second_lens | x-ai/grok-4.3 | anthropic/claude-sonnet-5 | ⚪ eval path only |
| context_judge judge — fallback | openai-frontier | anthropic-sonnet | ⚪ needs a forced probe |
google-flash alias (3 seats) | gemini-3.5-flash | gemini-3.6-flash | ✅ survived every pass of 4 live runs |
Every other vendor is provider-DIRECT. Anthropic cannot be, today: build_model's
direct branch constructs an OpenAIChatModel, and Anthropic's API is not OpenAI-wire.
A bare OpenRouter slug gets the gateway plus ZDR pinning with zero code change,
so that is the path taken. Anthropic is now the second gateway vendor after the Google
exception — for a different reason, and the registry says so.
Anthropic's pricing page states Claude 4.7+ use a newer tokenizer emitting ~30% more tokens for the same text. Token price is therefore not comparable across that line, and our documents are the input:
| Model | list $in | effective $ per 1M tokens of text |
|---|---|---|
| claude-sonnet-5 (today) | 2.00 | ≈ 2.60 — still under kimi-k3 ($3.00) |
| claude-sonnet-5 (from 2026-09-01) | 3.00 | ≈ 3.90 — now OVER kimi-k3 |
| claude-opus-5 | 5.00 | ≈ 6.50 |
This is why Sonnet, not Opus, took the Indigo judge fallback: Indigo runs uncached
(founder call, "only a 1-time job"), so on a 100k-token document Sonnet costs ~$0.26 and fits the
max_run_cost_usd: 0.45 cap, while Opus costs ~$0.65 and would breach it mid-run.
Mira's synthesizer could not take kimi-coding:k3 as pure config: that route is
production_allowed=False and _build_agent called build_model()
without allow_nonproduction, so the seat failed closed at build time. The factory is
now chain-aware — the same FallbackModel shape _converse_agent already
used, lifted into the shared factory so every panel role inherits it.
llm.yaml a LIST means two different things: for proposer it is a
parallel roster of diverse drafters; for every other role it is an
ordered chain. The first version wrapped the roster in a FallbackModel too,
turning 3 independent drafters into 1 primary + 2 never-used fallbacks. Nothing errors. The panel
still returns answers. It just quietly stops being a panel. Pinned by
test_proposer_roster_is_never_collapsed_into_a_fallback_chain.Indigo lost ~1 of its 3 deep_read proposers to TimeoutError on essentially
every run, and the victim rotated by run rather than by model — sonnet-5,
deepseek-v4-flash, grok-4.20 and grok-4.5 were all observed dying. That is the signature of a
broken stopwatch, not a slow model.
Why nobody noticed: the pass only REQUIRES 2 survivors. Losing one is not an
error anyone sees — the run reports success. status=partial was the only hint.
ROOT CAUSE — one clock, measuring the wrong thing
await asyncio.wait_for(_run_seat_streamed(agent, prompt), timeout=remaining)
THE FIX — chunks reset the clock; only silence kills
chunks = stream.stream_responses(debounce_by=None).__aiter__()
while True:
chunk = await asyncio.wait_for(anext(chunks, _STREAM_DONE), timeout=silence_s)
if chunk is _STREAM_DONE: break
Indigo had already adopted the hard half of the streaming doctrine
(run_stream) but kept a wall-clock box — contradicting
docs/notes/streamed-provider-calls-2026-07-24.md: "a route read-cap measures
inter-chunk silence, never total call duration. Slow is not dead."
stream_responses and not stream_output: it yields raw
provider chunks, so a model emitting reasoning tokens counts as alive.
stream_output validates partial output per chunk and can stay quiet through exactly
the long thinking phase we must not kill.
invoke_budget_s cannot be raised from this repo — all four passes share one invoke
and the budget is bounded by the broker timeout, which is pramaan-functions-owned
(RFD-DOC-007 §4.5). That constraint made the fix better. A wedged seat used to consume its
ENTIRE box, so remaining <= 0 made the bounded retry unreachable
and the seat was simply lost:
before: wedged seat burns all 180s → remaining <= 0 → retry unreachable → seat lost after: wedged seat dies at 45s → 135s left → retry runs → seat kept
45s vs the 8.4s worst healthy inter-chunk gap measured at 132k input tokens — a ~5× margin.
Live runs on the same document and roster went 2-of-3 → 3-of-3 → 2-of-3 again.
The recurrence reports error_kind=TimeoutError, not
indigo_seat_went_silent — the seat streamed continuously and still exceeded the 180s
box. So deep_read has at least two causes:
| Cause | Signature | Status |
|---|---|---|
| Wedged stream | indigo_seat_went_silent | ✅ fixed — caught at 45s, retry recovers it |
| Genuinely slow seat | TimeoutError at 180s | ❌ not fixed — needs a bigger box (broker-owned) |
TimeoutError and the two causes were indistinguishable even in hindsight. The
new error_kind separated them on the very first repeat run — and disproved the
author's own "these were all stalls" conclusion.| Check | Result |
|---|---|
| Offline suites (indigo · mira · framer · context_judge · registrar · governance) | 1,513 passed |
ruff check | clean |
| Indigo offline gates | proposed=80 rejected=0 |
| Live: gemini-3.6-flash | survived every pass, 4 runs |
| Live: sonnet-5 judge (forced probe) | salvaged 28, dropped 0 |
Live: deep_read 3-of-3 | 1 of 3 post-fix runs — intermittent, see above |
grok-lite → grok-4.5 was tried and reverted the same day. It was
reverted on evidence that Bug-2926 later dissolved — the timeout was not model-specific. It is
unproven, not disproven; retrying it is reasonable once the box is fixed.Refs, not Closes.