Patch releases v2.1.305 through v2.1.307 (2026-10-20/21) fix four classes of defects that all cluster around MCP integration and model selection: duplicated tool calls on mid-call connection loss, wrong model attribution after a subagent fallback, an API error masked as "prompt is too long" (triggering an unnecessary compaction), and two MCP configuration/status blind spots. The same source records a dependency fact about yoagent 0.25.10+, whose ModelConfig preset API supersedes the hand-maintained model tables still used by yoyo on Day 236.
Key Points
Retry safety is now keyed on tool idempotence. HTTP MCP tool calls were being sent twice when the connection closed mid-call; only read-only or idempotent tools are now retried.
Fallback attribution fixed. Claude previously named the wrong model for a subagent's work after that subagent switched to a fallback model.
Error masking fixed. In sessions with many MCP tools, an API error was replaced by "prompt is too long" plus an unneeded compaction — a classifier overwriting the real cause.
Headless MCP status. Servers reported as timed out stayed in a failed state in headless runs after sleep; failure reasons are now surfaced.
allowedMcpServers env-only blind spot. The filter stopped filtering managed stdio servers that use ${VAR} only inside env.
Dependency:yoagent 0.25.10+ provides ModelConfig::preset, ModelConfig::generic, and ModelConfig::presets(); yoyo still keeps three hand tables in agent_builder.rs, so glm-5.3 and gpt-5.5 run on a guessed (measured) 4096 max_tokens cap.
Idempotence / retry safety — retry eligibility determined by whether a tool is read-only or idempotent.
Fallback model attribution — which model is credited for a subagent's output after a fallback occurs.
Error masking — a downstream classifier replacing an upstream API error with a plausible but wrong message.
Headless runs — non-interactive execution where MCP server state persists across sleep.
allowedMcpServers — allowlist filter for managed MCP servers.
${VAR} expansion in env — environment-variable substitution scoped to a server's env block.
ModelConfig::preset(provider, id) — exact-match lookup of a named model preset.
ModelConfig::generic(provider, id) — returns None for gateways/custom providers.
ModelConfig::presets() — enumeration of 22 named presets (incl. gpt-5.5, glm-5.3, glm-5.3-flash, qwen3.8-max/flash).
Details
MCP tool-call retry safety
When an HTTP MCP connection closed mid-call, the client could not tell whether the server had executed the request, and re-sent it — producing duplicate side effects. The fix narrows retry to calls that are safe to repeat: read-only or otherwise idempotent tools. Non-idempotent tools now fail rather than risk double execution.
Rendering diagram…
Model attribution after fallback
After a subagent switched to a fallback model, the parent reported the wrong model as having done the work. yoyo has an analogous signal in sub_agent_model_label, which records which of the two models is in use; per the source, the which-of-two distinction is not observable on the error path only.
Error masking by the "prompt is too long" classifier
In sessions carrying many MCP tool definitions, a genuine API error was surfaced as "prompt is too long" and followed by an unnecessary compaction. The compaction was a symptom of the misclassification, not of real context pressure — the underlying API error is now preserved.
Headless MCP server status
A server reported as timed out remained marked failed in headless runs even after a sleep interval, and no reason was given. The releases surface the failure reason so the stale-failed state is diagnosable.
allowedMcpServers env-only filtering gap
Allowlist filtering skipped managed stdio servers whose configuration referenced ${VAR} only inside their env block. Env-only configuration was therefore a filtering blind spot; such servers are now subject to allowedMcpServers.
Dependency: yoagent 0.25.10+ model presets
yoagent 0.25.10+ exposes:
ModelConfig::preset(provider, id) — exact match against named presets.
ModelConfig::generic(provider, id) — returns None for gateways and custom providers.
ModelConfig::presets() — 22 named presets including gpt-5.5, glm-5.3, glm-5.3-flash, qwen3.8-max, qwen3.8-flash.
and inform the user when the fallback path was taken, so a generic-config resolution is never silently mistaken for an exact preset hit.
Implications for yoyo
yoyo (Day 236) still maintains three hand-written model tables in agent_builder.rs instead of consuming preset/generic. As a measured consequence, glm-5.3 and gpt-5.5 execute with a guessed 4096-token max_tokens cap rather than each preset's real limit. Adopting the preset(...).or_else(generic(...)) pattern would both remove the three tables and give correct per-model caps, at the cost of needing a user-visible notice when the generic fallback runs.