yoagent is a Rust agent framework crate published on crates.io. The 0.25.x line (0.25.0 on 2026-10-08; 0.25.1 and 0.25.2 on 2026-10-09) contains breaking changes for host applications (such as yoyo) in 0.25.0 — pricing must now be opted into, and the extension message variant was renamed — plus a further breaking Unix behaviour change in 0.25.2 to how BashTool manages process groups. Beyond the breaks, the line carries a set of behavioural fixes that a host still pinned to 0.24.2 — as yoyo does (#1007) — silently lacks; several are safety- or correctness-relevant: cancelled runs no longer fire off pending tool calls, event streams are now balanced, sub-agent cancellation is reported as an error, and compaction spend is counted. 0.25.x also adds an extension contract, custom HTTP headers for MCP transports, and reasoning inference for OpenAI Responses. (Changelog read 2026-10-10.)
Key Points
Pricing is now opt-in.ModelConfig::cost is None from every constructor until the process explicitly enables pricing via yoagent::provider::prices::enable_bundled() (offline snapshot) or prices::enable_live(...). Without this, session/total cost is reported as unpriced. This is one of the two known breaking changes in 0.25.0.
Message variant renamed.AgentMessage::Extension → AgentMessage::Custom (and ExtensionMessage → CustomMessage with a deprecated alias). The serialized format is unchanged: untagged enum with role: extension. This is the second known breaking change in 0.25.0.
Unix BashTool process-group change (0.25.2). On Unix, bash now leads its own process group, and timeout/cancel/drop kills the entire group — including pipelines, && lists, and background jobs. Windows behaviour is unchanged.
Behavioural consequence: terminal Ctrl+C no longer reaches the running command; the host must cancel the call on Ctrl+C. Commands that prompt on /dev/tty (e.g. sudo, ssh) stall until timeout.
Cancellation safety (#243): a run cancelled while the model response was still arriving used to its not-yet-started tool calls anyway, because the cancel was only observed on the next turn. 0.25.0 stops this — relevant for Ctrl+C handling.
execute
Event pairing (#243): every TurnStart now has a matching TurnEnd, and final failure/cancel messages now emit MessageStart/MessageEnd. Consumers that count events must be re-checked.
Sub-agent cancellation: a sub-agent cancelled before answering now fails with ToolError::Cancelled; previously it reported success with "(sub-agent produced no text output)".
Cost accounting:LlmCompaction summarization spend now reaches SessionStats/total_cost_usd (it was under-counted). With an unpriced summarizer, the total is None.
Delegated-run extensions:with_tree_extension makes an Extension apply to delegated runs at every depth (previously a parent ToolMiddleware never reached sub-agents).
Filesystem accuracy:list_files now reports unreadable subdirectories (#260, originally found by yoyo).
Reasoning inference:openai_responses infers reasoning=false for gpt-3*, gpt-4*, chatgpt-*, and -chat model ids.
0.25.2 MCP:HttpTransport::with_header added for HTTP MCP servers (#275).
New APIs across 0.25.x: the Extension contract (with_extension, with_tree_extension, required vs advisory extensions, take_failure), HttpTransport::with_header for HTTP MCP servers, and reasoning inference from model id in openai_responses.
Rival context (same week): OpenAI Codex CLI rust-v0.161.0 (2026-10-07) made GPT-6.1 Sol the default model, but yoagent 0.25.2 ships no gpt-6.1 preset (per grep). Claude Code 2.1.295 (2026-10-08) added an onFailure: block hook (a hook that cannot start or times out blocks the run); yoyo's pre-hooks already fail closed on timeout/spawn error (hooks.rspre_executeErr → Blocked by hook).
Concepts
ModelConfig::cost — per-model cost configuration; now defaults to None until pricing is enabled.
prices::enable_bundled / prices::enable_live — opt-in pricing modes: an offline bundled snapshot vs. live pricing data; enable_bundled() is the switch hosts must call to get bundled pricing.
AgentMessage::Custom / CustomMessage — the renamed message variant (formerly Extension/ExtensionMessage); wire format is an untagged enum with role: extension.
Extension contract — mechanism for hosts to attach required or advisory extensions to agent runs, with take_failure to surface failures.
with_tree_extension — attaches an extension so it reaches delegated sub-agent runs at any depth.
ToolMiddleware — extension hook type that, before 0.25, never reached sub-agents.
TurnStart / TurnEnd, MessageStart / MessageEnd — lifecycle events that are now guaranteed to be paired.
ToolError::Cancelled — error returned for a sub-agent cancelled before it answers.
LlmCompaction, SessionStats, total_cost_usd — summarization path and the cost accounting it now feeds.
HttpTransport::with_header — supplies custom HTTP headers to HTTP MCP servers.
openai_responses — provider that now infers reasoning behaviour from the model id.
MCP (Model Context Protocol) — transport surface where HttpTransport lives.
tokio::process::Command — the async process API whose direct-child kill semantics motivated the process-group fix.
Details
Breaking changes for hosts
1. Opt-in pricing (0.25.0). Model cost is no longer populated by default. Every ModelConfig constructor leaves cost as None. A host process must call either:
yoagent::provider::prices::enable_bundled() — uses an offline pricing snapshot, or
prices::enable_live(...) — fetches live pricing.
Until one of these is called, session and total cost values read as unpriced rather than as a number.
2. Renamed extension message variant (0.25.0).AgentMessage::Extension is now AgentMessage::Custom, with ExtensionMessage renamed to CustomMessage and a deprecated alias retained for the old name. Serialized data is unchanged because the enum is untagged and the role remains extension — so persisted payloads stay compatible.
3. Unix process-group killing in BashTool (0.25.2, #277). On Unix, bash is launched as the leader of its own process group. On timeout, cancellation, or drop, the whole group is killed, which reliably terminates pipelines, && lists, and background jobs, so child processes are not orphaned. Two behaviour changes follow:
Terminal Ctrl+C no longer propagates to the command; the host must cancel the call itself when Ctrl+C is received.
Commands that prompt on /dev/tty (such as sudo or ssh) will stall until the call times out, since the interactive terminal is no longer connected.
Windows behaviour is unchanged.
Behavioural fixes a 0.24 host silently lacks
Cancellation is now honoured mid-response. In 0.24.2, if a run was cancelled while the model response was arriving, the cancel was not observed until the following turn — so tool calls that had not yet started still executed. 0.25.0 fixes this. This is the most safety-relevant change for hosts that map Ctrl+C to cancellation, since a user pressing Ctrl+C could previously still trigger side-effecting tool calls.
Rendering diagram…
Event stream is now balanced. Every TurnStart has a corresponding TurnEnd, and terminal failure/cancel messages emit MessageStart/MessageEnd. Any consumer that counts or pairs lifecycle events against assumptions from 0.24 needs to be re-verified.
Sub-agent cancellation is an error, not a success. A sub-agent cancelled before producing an answer now surfaces ToolError::Cancelled. Previously the caller saw a successful result whose text read "(sub-agent produced no text output)", masking the cancellation.
Compaction spend is counted.LlmCompaction summarization was under-counted; in 0.25 it flows into SessionStats/total_cost_usd. If the summarizer is unpriced, the reported total is None rather than a partial figure.
Extensions reach delegated runs.with_tree_extension applies an Extension to delegated runs at every depth. In 0.24, a parent's ToolMiddleware never reached sub-agents.
list_files reports unreadable subdirectories (#260) — an accuracy fix originally found by yoyo.
Reasoning inference for OpenAI.openai_responses infers reasoning=false for gpt-3*, gpt-4*, chatgpt-*, and -chat model ids.
New in 0.25.x
Extension contract:with_extension and with_tree_extension (the latter reaches delegated sub-agent runs at any depth), a distinction between required and advisory extensions, and take_failure for retrieving extension failures.
HttpTransport::with_header for attaching custom headers to HTTP MCP servers (#275).
openai_responses now infers reasoning settings from the model id.
Underlying Unix fact
Killing the direct child of a tokio::process::Command (e.g. a bash -c running a pipeline or list) leaves forked stages running. Verified 2026-10-09: with bash -o pipefail -c "sleep N | cat; echo", sending kill -9 to bash leaves the sleep process alive. The fix is to launch with Command::process_group(0) and, on timeout/cancel, call killpg(-pgid) to kill the whole group — the mechanism adopted by BashTool in 0.25.2.
Competitive context (week of 2026-10-07)
OpenAI Codex CLI rust-v0.161.0 (2026-10-07) set GPT-6.1 Sol as its default model; yoagent 0.25.2 has no gpt-6.1 preset.
Claude Code 2.1.295 (2026-10-08) introduced onFailure: block hooks, where a hook that fails to start or times out blocks execution — behaviour yoyo's pre-hooks already implement by mapping pre_executeErr to Blocked by hook.
Related note
Claude Code 2.1.29x also adjusted pricing, billing Sonnet 5.5 cache reads at 0.10 per Mtok (down from 0.20).