Skip to content

chore: release v0.41.0 - #2220

Closed
github-actions[bot] wants to merge 1 commit into
mainfrom
release-plz-2026-07-28T10-20-36Z
Closed

chore: release v0.41.0#2220
github-actions[bot] wants to merge 1 commit into
mainfrom
release-plz-2026-07-28T10-20-36Z

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

🤖 New release

  • rig-derive: 0.40.0 -> 0.41.0
  • rig-core: 0.40.0 -> 0.41.0
  • rig-agent: 0.0.0 -> 0.41.0
  • rig-bedrock: 0.40.0 -> 0.41.0
  • rig-candle: 0.1.0 -> 0.41.0
  • rig-fastembed: 0.40.0 -> 0.41.0
  • rig-gemini-grpc: 0.40.0 -> 0.41.0
  • rig-helixdb: 0.40.0 -> 0.41.0
  • rig-lancedb: 0.40.0 -> 0.41.0
  • rig-memory: 0.40.0 -> 0.41.0
  • rig-milvus: 0.40.0 -> 0.41.0
  • rig-mongodb: 0.40.0 -> 0.41.0
  • rig-neo4j: 0.40.0 -> 0.41.0
  • rig-postgres: 0.40.0 -> 0.41.0
  • rig-qdrant: 0.40.0 -> 0.41.0
  • rig-s3vectors: 0.40.0 -> 0.41.0
  • rig-scylladb: 0.40.0 -> 0.41.0
  • rig-sqlite: 0.40.0 -> 0.41.0
  • rig-surrealdb: 0.40.0 -> 0.41.0
  • rig-vectorize: 0.40.0 -> 0.41.0
  • rig-vertexai: 0.40.0 -> 0.41.0
  • rig: 0.40.0 -> 0.41.0
Changelog

rig-derive

0.41.0 - 2026-07-28

Added

Other

Contributors

Changed

  • (rig-derive) [breaking] #[rig_tool] required-ness is derived from the
    parameter types so the advertised schema and the deserializer always agree:
    without required(...), Option<T> parameters are optional (previously
    advertised as required); with required(...), omitted parameters get
    #[serde(default)] (their types must be Option<T> or Default). Names in
    params(...)/required(...) must match actual parameters, and malformed or
    duplicate attribute entries are compile errors instead of silently ignored.
    Listing an Option<T> parameter in required(...) is a compile error
    (schemars and serde would both silently ignore the directive), and a
    wildcard context binding (#[rig(context)] _: &mut ToolContext) is now
    rejected — name it _context instead.

  • (rig-derive) Crate-name resolution and context classification share one
    authority: fully qualified &mut ToolContext paths are recognized under
    renamed rig/rig-agent dependencies without #[rig(context)], and a
    contextual tool without a reachable runtime crate gets a targeted
    diagnostic. Generated code resolves serde/serde_json/schemars through
    rig-core's re-exports (no direct downstream dependency needed), the
    Embed derive emits fully qualified impls (no Embed import needed at the
    call site), and parameters() builds its schema once via LazyLock with no
    generated expect. A field carrying both #[embed] and
    #[embed(embed_with = "...")] is now a compile error instead of being
    embedded twice, and a field carrying more than one
    #[embed(embed_with = "...")] attribute is a compile error instead of the
    first silently winning.

  • (rig-derive) [breaking] generated #[rig_tool] implementations preserve the function's Result<T, E> error as Tool::Error until erased dispatch normalizes it. Context-free functions implement the portable Tool::call API; functions with one &mut ToolContext parameter implement the contextual classic API. The context parameter may appear in any position; fully qualified rig::agent::tool::ToolContext / rig_agent::tool::ToolContext paths are recognized directly, while imported names and aliases use #[rig(context)]. The macro forwards runtime context and excludes that parameter from the generated arguments and JSON Schema without confusing unrelated application types also named ToolContext.

rig-core

0.41.0 - 2026-07-28

Added

Fixed

Other

Contributors

Added

  • (core) rig_core::telemetry::Empty re-exports tracing::field::Empty, so a
    runtime can declare a completion-parent field as not-yet-valued without taking
    a direct tracing dependency.

Changed

  • (core) The telemetry completion-parent contract has one declarative
    source: the new rig_core::telemetry::completion_parent_span! macro
    declares the adoption marker and every required gen_ai.* field. tracing
    bakes a span's field set into static metadata and Span::record silently
    no-ops on undeclared fields, so a hand-mirrored field list that drops one
    field loses that telemetry with no error. Exact-set tests now pin the macro
    against COMPLETION_PARENT_REQUIRED_FIELDS and against the span the
    completion builder itself creates, so the two can no longer drift. A
    completion parent that carries the marker but omits a required field
    triggers a warn! naming the missing fields — once per offending span
    callsite, so two broken runtimes are both reported — before it degrades to
    a fresh rig::completions child span. The macro accepts an optional
    parent: argument (default: the current span), and its expansion resolves
    tracing through rig-core, so downstream crates do not need a direct
    tracing dependency merely to invoke it (see the Empty re-export above).
    Nothing is breaking: the marker field and the required field set are
    unchanged.

  • (agent) [breaking] Remove the completion-model parameter from
    AgentHook, HookStack, and the erased hook interface. Managed response
    hooks now receive canonical Rig lifecycle fields (prompt, content,
    usage, and message_id) through non-generic CompletionResponse and
    StreamResponseFinish events. This lets one concrete hook attach to agents
    backed by different providers. Typed raw provider responses remain available
    from direct CompletionModel completion and streaming APIs.

    // Before
    impl<M: CompletionModel> AgentHook<M> for TelemetryHook { /* ... */ }
    
    // After
    impl AgentHook for TelemetryHook { /* ... */ }
  • (agent) [breaking] Make AgentRunner the only execution path for configured agents: remove the raw Completion and StreamingCompletion traits and their Agent implementations, make agent execution state private, add runner-backed per-request overrides, and route Extractor through the full hook lifecycle. Raw hook-free requests remain available explicitly through CompletionModel.

    Migration examples:

    // Before: built a one-shot request from configured Agent state, but bypassed
    // the AgentRunner lifecycle.
    agent.completion(prompt, history).await?.send().await?;
    
    // After, for managed Agent execution: hooks, tools, retrieval, memory, and
    // turn accounting all run. Budget enough calls for tool follow-ups.
    agent
        .runner(prompt)
        .history(history)
        .max_turns(3)
        .run()
        .await?;

    Streaming follows the same boundary:

    // Before
    agent.stream_completion(prompt, history).await?.stream().await?;
    
    // After
    let stream = agent
        .runner(prompt)
        .history(history)
        .max_turns(3)
        .stream()
        .await;

    The runner consumes tool calls instead of returning the first raw model
    response. If the old caller handled that response itself, or for any other
    intentionally hook-free provider transport, start from the model rather than
    an Agent:

    model
        .completion_request(prompt)
        .messages(history)
        .send()
        .await?;
    
    let stream = model
        .completion_request(prompt)
        .messages(history)
        .stream()
        .await?;

    AgentRun::new(prompt).with_history(history) remains the public sans-I/O
    state machine for custom drivers. It contains no model, tools, memory, or hook
    stack: callers must handle every AgentRunStep, perform provider/tool IO, and
    feed results back explicitly. It is not a way to execute a configured
    Agent; use AgentRunner for that.

    An Agent also keeps its configured model private and fixed. Applications
    that previously called .model(...) or .model_opt(...) on the returned raw
    request builder should retain the provider CompletionModel and use its raw
    request API, or construct a separate Agent for that model selection.

  • (providers) [breaking] Move Together, OpenRouter, and Mistral embeddings onto the shared GenericEmbeddingModel, with provider-specific endpoint and typed request-shaping hooks. Together now forwards configured embedding dimensions, Mistral maps Codestral Embed dimensions to output_dimension while rejecting dimensions for fixed-size models, compatible providers may omit usage without weakening OpenAI's public response type, and Base64 response encoding is rejected before sending because the shared parser accepts numeric vectors. Remove the superseded provider-specific embedding response/data types, Together's API envelope module, and OpenRouter's duplicate EncodingFormat.

  • (tool) [breaking] Replace the parallel tool-execution APIs with one structured path. Typed tools now implement only Tool::call(&mut ToolContext, Args) -> Result<Output, Error>; author-facing errors remain typed until private runtime erasure normalizes them into ToolExecutionError, ToolContext carries inbound values and host-only result metadata, ToolResult is the single runtime observation, and ToolSet::execute / ToolServerHandle::execute are the dispatch surfaces. Event-specific hook action types make invalid event/action combinations unrepresentable.

    • Tool implementations: retain one typed type Error for ordinary ? propagation and direct-call tests; remove classify_error, call_with_extensions, and call_structured. The optional map_error method classifies domain failures at the erased boundary, while its default preserves the source as Other. Return refusals through map_error with ToolExecutionError::refused, and attach host-only result metadata with ToolContext::insert_result.
    • Context: replace ToolCallExtensions and ToolResultExtensions with ToolContext; replace request/runner .tool_extensions(...) with .tool_context(...). Each dispatch snapshots inbound context exactly once, isolates tool-local mutations, and publishes only result metadata back to the caller and hooks.
    • Dynamic tools: ToolDyn is removed from the public API; use DynamicTool for runtime-defined tools. Rig's erased dispatch trait is private. Typed tools use Tool::NAME as their sole identity; runtime-named agents convert explicitly with Agent::into_tool().
    • Registration vocabulary: AgentBuilder::tools(Vec<Box<dyn ToolDyn>>) is removed; use repeated .tool(...) calls for typed tools or dynamic_tools(Vec<DynamicTool>) for runtime-defined callbacks. Retrieval-backed dynamic_tools(sample, index, toolset) becomes retrieved_tools. On ToolSetBuilder, static_tool remains the typed-tool path, the former embedding-backed dynamic_tool(ToolEmbedding) becomes retrieved_tool, and runtime-defined callbacks use dynamic_tool(DynamicTool).
    • Results and errors: replace ToolError, ToolFailure, ToolFailureKind, ToolReturn, ToolReturnOutcome, ToolExecutionResult, and ToolOutcome with ToolExecutionError, ToolErrorKind, and the read-only ToolResult observed by hooks.
    • Model presentation: serializable outputs convert once into canonical ToolOutput content blocks; strings remain literal text, explicit serde_json::Value values remain JSON, and multimodal tools use ToolOutput::content / ToolOutput::one or return typed ToolResultContent directly. Result hooks now rewrite ToolOutput, provider adapters preserve native JSON where supported or render it only at their terminal wire boundary, mixed user/tool-result blocks retain order, and Rig never reparses strings to infer rich content. Consumers can inspect ToolResultContent with as_text / as_json and explicitly decode either structured JSON or legacy JSON-bearing text with deserialize_json.
    • Error presentation: explicit ToolExecutionError constructors keep actionable diagnostics model-visible, while the generic ToolExecutionError::from_error path preserves operator diagnostics and the concrete source but defaults to safe kind-level model feedback. Use with_model_feedback for deliberate replacement text or with_model_output for JSON/multimodal feedback. MCP responses preserve ordered supported text/image content, retain unsupported and future blocks as typed JSON, and attach raw CallToolResult, structuredContent, and response metadata to ToolContext. MCP list installation and refresh are atomic and ownership-aware, so stale handlers cannot replace or remove newer registrations, while disconnected owners are retired during refresh, provider exposure, or direct dispatch.
    • Dispatch: replace ToolSet::{call, call_with_extensions, call_structured} with ToolSet::execute; replace ToolServerHandle::{call_tool, call_tool_with_extensions, call_tool_structured} with ToolServerHandle::execute.
    • Registration and definitions: ToolSet is the single ordered registry and records whether each tool is always advertised or retrieval-only. ToolSet::{get_tool_definitions, documents} are now synchronous and infallible, ToolServerHandle registration/removal methods no longer return an artificial Result, and the obsolete ToolSetError is removed.
    • Hooks: replace AgentHook::on_event, StepEvent, and Flow with the event-specific AgentHook methods and their corresponding action types (CompletionCallAction, ToolCallAction, ToolResultAction, InvalidToolCallAction, and ObservationAction). Result rewrites replace the effective model and result-content telemetry presentation while preserving the raw ToolResult and ToolContext for policy; result stops omit result-content telemetry. Invalid-tool hooks return None to defer; every explicit action, including Fail, is terminal for that hook stack.
    • Streaming execution observation: the atomically surfaced post-batch event is named ToolExecutionCommitted, reflecting that it is not a real-time start notification. Applications that need live host lifecycle events should observe on_tool_call / on_tool_result; typed result metadata remains available through ToolResultEvent::tool_context without entering model-facing messages.
  • (core) [breaking] Mark PromptError, StructuredOutputError, and VectorStoreError as non-exhaustive, requiring downstream match expressions to include a wildcard arm. Conversation memory load failures now surface as the typed PromptError::MemoryError variant instead of CompletionError::RequestError.

Fixed

  • (openai) Treat empty encrypted_content in non-streaming Responses API
    reasoning items as absent, matching streaming behavior and avoiding empty
    encrypted reasoning blocks.

rig-agent

0.41.0 - 2026-07-28

Added

Other

Contributors

rig-bedrock

0.41.0 - 2026-07-28

Added

Fixed

Other

Contributors

rig-candle

0.41.0 - 2026-07-28

Added

Other

Contributors

rig-fastembed

0.41.0 - 2026-07-28

Other

Contributors

rig-gemini-grpc

0.41.0 - 2026-07-28

Added

Other

Contributors

rig-helixdb

0.41.0 - 2026-07-28

Other

Contributors

rig-lancedb

0.41.0 - 2026-07-28

Added

Other

Contributors

rig-memory

0.41.0 - 2026-07-28

Added

Other

Contributors

rig-milvus

0.41.0 - 2026-07-28

Other

Contributors

rig-mongodb

0.41.0 - 2026-07-28

Other

Contributors

rig-neo4j

0.41.0 - 2026-07-28

Other

Contributors

rig-postgres

0.41.0 - 2026-07-28

Other

Contributors

rig-qdrant

0.41.0 - 2026-07-28

Other

Contributors

rig-s3vectors

0.41.0 - 2026-07-28

Fixed

Contributors

rig-scylladb

0.41.0 - 2026-07-28

Other

Contributors

rig-sqlite

0.41.0 - 2026-07-28

Other

Contributors

rig-surrealdb

0.41.0 - 2026-07-28

Other

Contributors

rig-vectorize

0.41.0 - 2026-07-28

Other

Contributors

rig-vertexai

0.41.0 - 2026-07-28

Added

Other

Contributors

rig

0.41.0 - 2026-07-28

Added

Fixed

Other

Contributors

Added

  • (agent) Restore AgentBuilder::dynamic_context and
    ExtractorBuilder::dynamic_context as convenience wrappers around the
    existing completion-call hook lifecycle. The helper retains the former query
    selection and document formatting behavior without restoring a separate
    retrieval path in agent request construction. As an ordinary hook, retrieval
    and injected documents follow registration order relative to application
    hooks; register stop policies before it when they should prevent retrieval.

  • (core) rig_core::telemetry::Empty re-exports tracing::field::Empty, so a
    runtime can declare a completion-parent field as not-yet-valued without taking
    a direct tracing dependency.

Changed

  • (core, agent) [breaking] Remove every wasm feature flag in the workspace
    rig-core's wasm, rig-agent's wasm, and the rig facade's wasm.
    Browser wasm needs no feature flags at all: cargo build --target wasm32-unknown-unknown is the entire opt-in. The feature was a pure cfg
    switch that every consumer already flipped from a target table, and its one
    optional dependency was never referenced. Relaxing the bounds cannot break
    implementors — the relaxed markers are blanket-implemented
    (impl<T> WasmCompatSend for T {}), so every type that satisfied the strict
    form satisfies the relaxed one. (Generic consumers on browser wasm that
    wrote T: WasmCompatSend and then relied on T: Send internally are the one
    exception, and only if they were previously building with the feature off.)
    Dependents passing features = ["wasm"] should drop it; nothing replaces it.

  • (core) if_wasm!/if_not_wasm! now key on the target rather than a feature.
    These are #[macro_export]ed, and a cfg inside a macro expansion is
    evaluated in the calling crate — so the old expansion tested whether the
    caller had a feature named wasm, not rig-core. Any caller without one
    took the if_not_wasm! branch on every target, browser wasm included. Called
    out separately because unlike the feature removal, which Cargo rejects at
    resolution, this one changes behavior with nothing to fail on: a downstream
    crate that did define a wasm feature and expected it to drive these macros
    gets the target's answer now, silently. Gate on the target directly if you
    need the old association.

  • (agent) [breaking] The rmcp feature is native-only. It never compiled
    for wasm — rmcp's ClientHandler requires Send + Sync unconditionally,
    which rig's wasm tool registry cannot satisfy — but it failed with a wall of
    dyn ErasedTool trait errors. It now fails with one sentence naming the cause,
    and CI asserts that stays true.

  • (agent) Document the supported target matrix: native is fully supported,
    wasm32-unknown-unknown (browser) is supported, and WASI is not — its
    dependency graph has never built. Browser-only dependencies and Send-relaxed
    aliases are scoped accordingly, and wasm-bindgen-futures is no longer a
    rig-agent dependency, its only user having been the now-native-only MCP
    cancellation dispatch.

  • (core) Fix rig-core's SSE ResponseFuture/EventStream aliases, whose
    cfg arms did not partition and left some targets matching neither, so the
    types were undefined there. Both arms now share one predicate.

  • (core) The telemetry completion-parent contract has one declarative
    source: the new rig_core::telemetry::completion_parent_span! macro
    declares the adoption marker and every required gen_ai.* field. tracing
    bakes a span's field set into static metadata and Span::record silently
    no-ops on undeclared fields, so a hand-mirrored field list that drops one
    field loses that telemetry with no error — the contract was previously
    duplicated in six places. Exact-set tests now pin the macro against
    COMPLETION_PARENT_REQUIRED_FIELDS and against the span the completion
    builder itself creates, so those lists (including rig-agent's chat span,
    which now delegates to the macro) can no longer drift. A completion parent
    that carries the marker but omits a required field triggers a warn! naming
    the missing fields — once per offending span callsite, so two broken runtimes
    are both reported — before it degrades to a fresh rig::completions child
    span, so the degradation is visible in logs rather than only as a duplicated
    span layer in dashboards. The macro accepts an
    optional parent: argument (default: the current span), and its expansion
    resolves tracing through rig-core, so downstream crates do not need a
    direct tracing dependency merely to invoke it (see the Empty re-export
    above). Nothing is breaking: the marker field and the required field set are
    unchanged.

  • (derive) [breaking] #[rig_tool] required-ness is now derived from the
    parameter types, and the advertised schema always agrees with the
    deserializer. Without an explicit required(...), non-Option parameters
    are required and Option<T> parameters are optional (previously Option
    parameters were advertised as required even though absence deserialized to
    None). With an explicit required(...), parameters omitted from the list
    are deserialized with #[serde(default)], so omitting a non-Option,
    non-Default parameter is now a compile error instead of a runtime
    deserialization failure when the model leaves it out. Names in params(...)
    and required(...) must match actual parameters, and malformed or duplicate
    attribute entries are compile errors instead of being silently ignored.
    Listing an Option<T> parameter in required(...) is a compile error
    (schemars and serde would both silently ignore the directive), and a
    wildcard context binding (#[rig(context)] _: &mut ToolContext) is now
    rejected — name it _context instead.

  • (derive) #[rig_tool] recognizes fully qualified &mut ToolContext
    parameters under renamed rig/rig-agent dependencies without the
    #[rig(context)] marker; crate-name resolution and context classification
    now share one authority. A contextual tool in a crate with neither rig nor
    rig-agent reachable gets a targeted diagnostic instead of an unresolved
    ::rig_agent path error. Generated parameters() builds the schema once
    (LazyLock) and no longer contains an expect, so downstream crates
    denying clippy::expect_used are unaffected.

  • (derive, core) Macro-generated code resolves serde, serde_json, and
    schemars through rig-core's re-exports (rig_core::{serde, serde_json, schemars} are now public), so crates using #[rig_tool] or
    #[derive(Embed)] no longer need direct serde/serde_json dependencies.
    The Embed derive emits fully qualified trait impls and no longer requires
    the Embed trait to be imported at the call site. A field carrying both
    #[embed] and #[embed(embed_with = "...")] is now a compile error instead
    of being embedded twice, and a field carrying more than one
    #[embed(embed_with = "...")] attribute is a compile error instead of the
    first silently winning.

Removed

  • (agent) Remove the experimental rig-runtime-conformance crate and its
    classic-runtime adapter. With a single runtime it was a premature cross-runtime
    abstraction, and its scenarios were ~90% redundant with rig-agent's own test
    suite. The genuinely-unique invariants (multi-step memory append-once, append
    of only newly-committed messages, no-append on hook stop, committed-transcript
    role validity, and a two-sided concurrency bound) are now covered by direct
    tests in rig-agent. A real conformance contract can be re-extracted once a
    second runtime exists.

Fixed

  • (examples) candle_wasm_chat now declares the agent feature it actually
    imports (rig::agent::{Agent, AgentBuilder}, rig::completion::Chat), so it
    builds standalone rather than only inside a workspace-wide --all-features
    build that happened to unify the feature onto the shared rig. The wasm CI
    matrix now checks the example on its own, so a manifest that under-declares its
    features fails instead of being masked by feature unification.

  • (openai) Treat empty encrypted_content in non-streaming Responses API
    reasoning items as absent, matching streaming behavior and avoiding empty
    encrypted reasoning blocks.

  • (aws) Stop enabling the AWS SDK's legacy Rustls connector in the Bedrock and S3 Vectors integrations, removing vulnerable rustls-webpki 0.101 from their active dependency graphs while retaining the modern default HTTPS client.

Changed

  • (core, agent) [breaking] Split the monolithic core into a portable
    contracts crate (rig-core) and the classic agent runtime crate (rig-agent),
    presented behind the rig facade. Code using the rig facade needs
    essentially no source changes — rig::… paths, rig::prelude::*, and
    rig::tool::{Tool, ToolContext} all keep working. Direct rig-core dependents
    that constructed agents must now depend on rig-agent. See the migration
    guide (MIGRATING.md).

  • (tool) [breaking] The portable, context-free tool contract is now named
    PortableTool (with PortableToolEmbedding, PortableDynamicTool,
    portable_tool_definition); the rig_core::tool::Tool alias is removed. On
    the rig facade, rig::tool::Tool remains the classic contextual trait, so
    existing facade code is unchanged; portable contracts are always available as
    rig::tool::PortableTool (and in full under rig::tool::portable).

  • (client) [breaking] Provider clients no longer carry inherent
    agent() / extractor() methods. There is a single canonical
    CompletionClient trait (in rig-core, providing completion_model); the
    classic agent() / extractor() constructors live on the new AgentClientExt
    extension trait. use rig::prelude::*; brings both into scope for the full
    pre-split client surface (or import rig::client::{CompletionClient, AgentClientExt} explicitly).

  • (agent) [breaking] rig-agent no longer re-exports all of rig-core
    at its crate root. The previous pub use rig_core::*; made rig-agent an
    implicit second facade; the root now exports only runtime-owned items (plus
    the runtime-facing rig_tool / tool_macro macros). Code that depends on
    rig-agent directly and reached a portable rig-core item through the
    rig-agent root must import it from rig_agent::core (e.g.
    rig_agent::core::OneOrMany) or depend on rig-core directly. The root
    rig facade is unaffected: rig::… and rig::prelude::* are unchanged.

    // Before
    use rig_agent::{OneOrMany, message::Message};
    
    // After
    use rig_agent::core::{OneOrMany, message::Message};
  • (agent) [breaking] Managed agent hooks are now provider-independent.
    AgentHook, HookStack, and the internal erased-hook interface no longer
    carry a completion-model type parameter. CompletionResponseEvent and
    StreamResponseFinish now expose canonical Rig content, usage, prompt, and
    message ID fields instead of typed provider responses. Direct
    CompletionModel completion and streaming APIs continue to return their
    typed raw provider responses.

    // Before
    impl<M: CompletionModel> AgentHook<M> for TelemetryHook { /* ... */ }
    
    // After
    impl AgentHook for TelemetryHook { /* ... */ }
  • (agent) [breaking] Make AgentRunner the only execution path for configured agents: remove the raw Completion and StreamingCompletion traits and their Agent implementations, make agent execution state private, add runner-backed per-request overrides, and route Extractor through the full hook lifecycle. Raw hook-free requests remain available explicitly through CompletionModel.

    • For managed agent execution, replace agent.completion(prompt, history).await?.send().await? with agent.runner(prompt).history(history).max_turns(3).run().await?, choosing a turn budget large enough for tool follow-ups.
    • For managed streaming execution, replace agent.stream_completion(prompt, history).await?.stream().await? with agent.runner(prompt).history(history).max_turns(3).stream().await.
    • The runner consumes tool calls rather than returning the first raw model response. Callers that handled that response manually, and other intentionally hook-free transport, should start from model.completion_request(prompt).messages(history) and then call .send().await? or .stream().await?.
    • AgentRun::new(prompt).with_history(history) remains a sans-I/O state machine for custom drivers; it contains no configured agent model, tools, memory, or hooks and is not an alternate configured-agent execution path.
    • An Agent's model is fixed and private. Former per-call .model(...) / .model_opt(...) users should retain the provider CompletionModel and use its raw request API, or construct a separate Agent for the selected model.
  • (tool) [breaking] Replace the parallel tool-execution APIs with one structured path. Typed tools now implement only Tool::call(&mut ToolContext, Args) -> Result<Output, Error>; author-facing errors remain typed until private runtime erasure normalizes them into ToolExecutionError, ToolContext carries inbound values and host-only result metadata, ToolResult is the single runtime observation, and ToolSet::execute / ToolServerHandle::execute are the dispatch surfaces. Event-specific hook action types make invalid event/action combinations unrepresentable.

    • Tool implementations: retain one typed type Error for ordinary ? propagation and direct-call tests; remove classify_error, call_with_extensions, and call_structured. The optional map_error method classifies domain failures at the erased boundary, while its default preserves the source as Other. Return refusals through map_error with ToolExecutionError::refused, and attach host-only result metadata with ToolContext::insert_result.
    • Context: replace ToolCallExtensions and ToolResultExtensions with ToolContext; replace request/runner .tool_extensions(...) with .tool_context(...). Each dispatch snapshots inbound context exactly once, isolates tool-local mutations, and publishes only result metadata back to the caller and hooks.
    • Dynamic tools: ToolDyn is removed from the public API; use DynamicTool for runtime-defined tools. Rig's erased dispatch trait is private. Typed tools use Tool::NAME as their sole identity; runtime-named agents convert explicitly with Agent::into_tool().
    • Registration vocabulary: AgentBuilder::tools(Vec<Box<dyn ToolDyn>>) is removed; use repeated .tool(...) calls for typed tools or dynamic_tools(Vec<DynamicTool>) for runtime-defined callbacks. Retrieval-backed dynamic_tools(sample, index, toolset) becomes retrieved_tools. On ToolSetBuilder, static_tool remains the typed-tool path, the former embedding-backed dynamic_tool(ToolEmbedding) becomes retrieved_tool, and runtime-defined callbacks use dynamic_tool(DynamicTool).
    • Results and errors: replace ToolError, ToolFailure, ToolFailureKind, ToolReturn, ToolReturnOutcome, ToolExecutionResult, and ToolOutcome with ToolExecutionError, ToolErrorKind, and the read-only ToolResult observed by hooks.
    • Model presentation: serializable outputs convert once into canonical ToolOutput content blocks; strings remain literal text, explicit serde_json::Value values remain JSON, and multimodal tools use ToolOutput::content / ToolOutput::one or return typed ToolResultContent directly. Result hooks now rewrite ToolOutput, provider adapters preserve native JSON where supported or render it only at their terminal wire boundary, mixed user/tool-result blocks retain order, and Rig never reparses strings to infer rich content. Consumers can inspect ToolResultContent with as_text / as_json and explicitly decode either structured JSON or legacy JSON-bearing text with deserialize_json.
    • Error presentation: explicit ToolExecutionError constructors keep actionable diagnostics model-visible, while the generic ToolExecutionError::from_error path preserves operator diagnostics and the concrete source but defaults to safe kind-level model feedback. Use with_model_feedback for deliberate replacement text or with_model_output for JSON/multimodal feedback. MCP responses preserve ordered supported text/image content, retain unsupported and future blocks as typed JSON, and attach raw CallToolResult, structuredContent, and response metadata to ToolContext. MCP list installation and refresh are atomic and ownership-aware, so stale handlers cannot replace or remove newer registrations, while disconnected owners are retired during refresh, provider exposure, or direct dispatch.
    • Dispatch: replace ToolSet::{call, call_with_extensions, call_structured} with ToolSet::execute; replace ToolServerHandle::{call_tool, call_tool_with_extensions, call_tool_structured} with ToolServerHandle::execute.
    • Registration and definitions: ToolSet is the single ordered registry and records whether each tool is always advertised or retrieval-only. ToolSet::{get_tool_definitions, documents} are now synchronous and infallible, ToolServerHandle registration/removal methods no longer return an artificial Result, and the obsolete ToolSetError is removed.
    • Hooks: replace AgentHook::on_event, StepEvent, and Flow with the event-specific AgentHook methods and their corresponding action types (CompletionCallAction, ToolCallAction, ToolResultAction, InvalidToolCallAction, and ObservationAction). Result rewrites replace the effective model and result-content telemetry presentation while preserving the raw ToolResult and ToolContext for policy; result stops omit result-content telemetry. Invalid-tool hooks return None to defer; every explicit action, including Fail, is terminal for that hook stack.
    • Streaming execution observation: the atomically surfaced post-batch event is named ToolExecutionCommitted, reflecting that it is not a real-time start notification. Applications that need live host lifecycle events should observe on_tool_call / on_tool_result; typed result metadata remains available through ToolResultEvent::tool_context without entering model-facing messages.
  • (core) [breaking] Mark PromptError, StructuredOutputError, and VectorStoreError as non-exhaustive, requiring downstream match expressions to include a wildcard arm. Conversation memory load failures now surface as the typed PromptError::MemoryError variant instead of CompletionError::RequestError.


This PR was generated with release-plz.

@github-actions github-actions Bot closed this Jul 28, 2026
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.

0 participants