What's new in 3.5.0
Model pins fail loud instead of silently swapping
An explicit agent({ model }) pin, agent-type model, explicit tier, or phase-routed model that can't be resolved now throws a clear MODEL_NOT_FOUND error before the subagent starts — previously the run silently continued on the session default, so a mistyped pin looked successful while answering with different weights. Tier failures name their source (tier "big" from model-tiers.json resolves to "…", which is not available). Scripts can try/catch the error to degrade on their own terms. Untagged agents routed through the implicit default medium tier still degrade gracefully to the session default, now with a visible once-per-run log entry. The resolver also gained pi CLI's auth-aware handling of vendor/model ids whose vendor segment collides with a provider name — moonshotai/kimi-k3-style pins now resolve exactly as pi --model does. Thanks @johannrymill for the precise report (#131).
Upgrade note: if a workflow relied on an unresolvable pin quietly falling back, it now fails loudly — fix the pin, catch MODEL_NOT_FOUND, or drop the pin to use the session default. The onModelFallback callback narrows to the implicit-default-tier case with a new object signature.
Token budget contract, restored verbatim
The tokenBudget schema wording now matches the evaluated contract text exactly, pinned by a strict-equality test. Contributed by @Whamp (#129).
Docs: defensive parsing and empty-output recovery
agent() resolves to raw assistant text unless you pass schema (the built-in tool-forced structured-output path). New README guidance and a runnable defensive-json-parsing.js example show the parse-or-flag pattern; fleet guidance covers agentRetries: 1-2 for models with occasional empty first outputs, and documents that failed attempts are never journaled so resumeFromRunId re-runs only the failed call. Thanks @johannrymill (#134, #135).