Download Latest Version rig-v0.41.0 source code.zip (10.6 MB)
Email in envelope

Get an email when there's a new version of Rig

Home / v0.41.0
Name Modified Size InfoDownloads / Week
Parent folder
README.md 2026-07-28 24.6 kB
rig-v0.41.0 source code.tar.gz 2026-07-28 9.5 MB
rig-v0.41.0 source code.zip 2026-07-28 10.6 MB
Totals: 3 Items   20.1 MB 0

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.

```rust // 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.

```rust // Before impl<M: CompletionModel> AgentHook 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.
Source: README.md, updated 2026-07-28