Repository navigation
Rig v0.43.0 Released !!! #2641
gold-silver-copper
announced in
Announcements
Replies: 3 comments
|
Congratulations guys, great work 🚀 🚀 🚀 |
0 replies
|
Congratulations, amazing work 🔥🔥 |
0 replies
|
whooppp |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
117 PRs merged since 0.42. The tag-to-tag diff is +2.88M/−0.33M lines, mostly recorded fixtures; excluding them it is +379k/−192k. The provider cassette corpus grew from 1,793 to 2,995 recordings, plus 2,058 replayable effect-log goldens, and there are seven new crates. Big thank you to all our contributors 🫡
0.43 highlights:
New Crates
rig-reqwestreqwestfeature.rig-httprig-tungstenitewebsocket.rig-rmcprig-ecsWorld.rig-cassetterig-typesafeaitypesafeai.Effects
An effect is the result of an action. An action can be a model call, a tool call, an embedding, a memory operation, database retrieval, etc. Previously, most of these were neither directly observable nor serializable in Rig. The new effect system makes all actions observable, recordable and replayable. This allows us to augment our cassette system with an effect-log system, very useful for debugging provider contracts and the functioning of coding agents.
Two runtimes consume the same effect protocol: the classic
rig-agentloop, and the newrig-ecs.rig-ecs: Rig Inside a Bevy World
rig-ecsis a reimagining of the agent runtime on top of the Bevy runtime. It is very promising but is still experimental, and will likely go through many changes in the future, consider it a pre-alpha. If you want a more stable Rig experience, use the classic agent runtime.RigSet::Patch, judge a turn inRigSet::Judge, save inRigSet::Checkpoint.checkpoint::save_world/load_world), including your own registered components.hold_after_tool_turnpauses a run at a durable tool-turn boundary so you can resume it in a fresh world.rig-cassette: Record and Replay
The engine behind Rig's own test corpus is now a published crate, re-exported as
rig::cassette.Recording a classic agent is one builder call:
TypeSafe AI: typed judgments
rig-typesafeaiadds a different kind of provider. Instead of free text, Jev returns typed, calibrated judgments:Choicepicks one of your enum variants, with a probability distribution.Scoregrades on a rubric.Noulanswers yes/no as a probability.DynamicScoreand maps of questions cover rubrics defined at runtime.A query is one generic struct used for both questions and answers, so routing and triage decisions come back as ordinary Rust types.
examples/typesafeai_chatroutes between agents, andexamples/typesafeai_triageclassifies support tickets.Local Pose Estimation in rig-candle
rig_candle::pose::CandlePoseModelruns YOLOv8 pose estimation locally from a safetensors checkpoint you supply, in any size from n to x. It serves a customPoseEstimationoperation: RGB frames in, oneFramePosesper frame out (bounding box, confidence and the 17 COCO keypoints), folded into aPoseTrack. It is the first real model built on the out-of-tree operation path. Streaming, unary calls, erasure toDynModel<PoseEstimation>and custom transports all work as they do for any other Rig model:Caching
Caching got its own verification harness this cycle. It uses a three-turn probe that measures the cache hit ratio rather than just "cached > 0", plus 100-turn long-run recordings on Anthropic (
claude-opus-5-5), OpenAI (gpt-6-sol) and Gemini. The harness found bugs on its first run. Gemini tool schemas and Cohere documents were serialized from aHashMapin a different key order on every request, so the cacheable prefix changed every time and those requests could never hit.Gemini explicit context caching:
gemini::cached_contentcreates, gets, lists, updates and deletescachedContentsresources, andwith_cached_contentpoints a request at one.CacheExpirymakes a TTL and an absolute expiry mutually exclusive. The request rejects the combinations Gemini rejects (a cache owns the system instruction, tools and tool config), naming every conflict. An expired handle isProviderError::CacheExpired.Automatic caching for long Gemini runs: wrap a Gemini model with
.caching(&book)and a sharedCacheBookmanages explicit caches for you. It reads the longest live cache a request starts with, rolls a new cache when the input premium already paid would cover it, stays inline where implicit caching serves, shares prefixes across sub-agents, extends and deletes caches on schedule, and resumes from checkpointedleases().ThoughtReplay::CurrentTurnstops re-sending old thought signatures, which Gemini 3 would otherwise re-bill as input. In the recordings, a 100-turn support chat ongemini-3.8-flashwent from about 1% of input cached (implicit caching only) to 93% cached and a 78.6% input-cost saving with a book and current-turn replay. With the default thought replay, the same chat was 55% cached, a 46% saving.Providers Are Clients, and Models Are Values
In 0.42 a provider was a generic
Client<Ext, H>. Everything that could be built from it went through a family of capability traits (CompletionClient,EmbeddingsClient, …), and every model was its own type implementing one of eight model traits (CompletionModel,EmbeddingModel, …). Most of that is gone in 0.43. A provider is now two types:OpenAIConfig,AnthropicConfig,GeminiConfig, …): the settings. It is serializable, and its credential is never serialized.OpenAI,Anthropic,Gemini,Cohere,Ollama,Copilot,VoyageAi): the settings bound to a transport. This is what you normally hold.Every model, for every operation and every backend, is one type:
Model<W, T>, a wire (what to send and how to read the reply) on a transport (how the bytes travel). You call it withcall(..)orstream(..).erase()turns it into a cloneableDynModel<Op>when you want to store models of different providers side by side.AgentBuilder::new,ExtractorBuilder::newand every vector store accept anything that converts into the matchingDynModel.Models from a string. The new
rig::providers::registrymodule makes provider selection data.ProviderRef::parse("vendor/format:model")accepts the canonical form or thevendor:modelshorthand, andcompletion_model()builds aDynModel<Completion>with credentials from the environment.completion_model_with(key, http)takes explicit credentials and a transport. This is useful for config files, CLIs and routers:rig-core Without reqwest or tokio
rig-core is now transport-agnostic all the way down. Its hot paths no longer touch tokio primitives (streaming, the tool server, the Copilot and ChatGPT auth caches), and reqwest is gone from its dependencies and its public error types. The transports are separate crates:
rig-httpHttpClientExt,DynHttpClient,HttpMiddleware, framing and multipart;ws_client(WebSocketClientExt,WebSocketConnection);wasm_compat. rig-core re-exports all of them at the oldrig_core::http_clientandrig_core::ws_clientpaths.rig-reqwestReqwestClient, whoseDefaultis a process-wide shared client, plusReqwestMiddlewareClient(thereqwest-middleware*features),shared(),from_reqwestandmultipart_form.rig-tungsteniteTungsteniteClient), native targets only, withrustlsornative-tls.The
rigfacade turns the bundled transport on by default (featurereqwest), soOpenAI::from_env()just works. If you depend onrig-coredirectly, enable itsreqwestfeature; without it, bring your own transport withOpenAIConfig::from_env()?.connect(http)(every config hasconnect).Websockets. The OpenAI Responses websocket protocol moved into rig-core, and the socket lives in rig-tungstenite. With the facade's
websocketfeature, a Responses model opens a session directly. Without it, pass anyWebSocketClientExttoconnect_with(..):One Error Type
CompletionError,EmbeddingError,RerankError,TranscriptionError,ImageGenerationError,AudioGenerationError,VerifyErrorandModelListingErrorare now one enum:rig::ProviderError, also in both preludes. The variant is the classification (kind()).UsageMeans One Thing EverywhereAbsent is not zero. All seven
Usagecounters areOption<u64>:Nonemeans the provider didn't report that counter, andSome(0)is a reported zero.Usage::new()is gone (Usage::default()is all-None), andhas_values()is nowis_reported().One contract on every provider. This release decoded every one of the 7,178 recorded replies in the corpus and made the numbers agree:
Reasoning, Signatures and Tool-Call Ids That Survive the Round Trip
Providers hand Rig values that only they can interpret and expect back on the next turn: thinking signatures, encrypted reasoning, reasoning item ids, tool-call ids and cache handles. This cycle started recording those values verbatim. An oracle now checks all 1,655 continuation pairs in the corpus: every delivered value must come back, in its exact slot, on the next request.
Hooks: Run Lifecycle, Durable State and Effects
AgentHookgains the start and end of a run, durable state, and one pair of hooks for everything the run does:on_run_startfires once before the first model call. It can continue, rewrite the prompt, or stop the run.on_run_settledfires exactly once, on success or failure, with the messages the run actually committed.on_dispatch/on_outcomefire for every effect the run issues (model calls, tool calls, retrieval, memory) and replaceon_tool_call,on_tool_resultand the completion-response hooks.OutcomeEvent::completion()gives you the model reply when that's what landed.HookContext::append_entry(kind, &value)appends to aRunEntrylog carried inside the serializedAgentRun, andentries(kind)/last_entry(kind)read it back. A resumed run replays the log, so there is no manual export step. Entries never reach a provider request.on_invalid_tool_callwithInvalidToolCallReason::MalformedArgumentsand the raw text, so a hook canRetry,SkiporStop.Providers
New Models
CLAUDE_OPUS_5_5andCLAUDE_SONNET_5_5, plus the Claude 5 familyCLAUDE_FABLE_5_1,CLAUDE_FABLE_5,CLAUDE_OPUS_5andCLAUDE_SONNET_5(requested by @scadoshi). All have 128K output limits. Model ids are now also exported atrig::providers::anthropicdirectly.GPT_6_ASTRA,GPT_6_1_SOL,GPT_6_SOL,GPT_6_LUNA,GPT_5_4,GPT_5_4_MINI,GPT_5_4_NANOandGPT_5_2_PRO.LLAMA_3_3_70B_VERSATILE,GPT_OSS_120B,GPT_OSS_20B,GPT_OSS_SAFEGUARD_20B,QWEN3_8_27BandMINIMAX_M2_7. The retired constants are removed (reported by @Muhammad-Owais-Warsi).KIMI_K3,KIMI_K2_7_CODE,KIMI_K2_7_CODE_HIGHSPEEDandKIMI_K2_6. The discontinuedMOONSHOT_CHAT,KIMI_K2andKIMI_K2_5are removed (reported by @loony-lisa and @Parikalp-Bhardwaj).MXBAI_EMBED_LARGE,BGE_M3,EMBEDDINGGEMMA,QWEN3_EMBEDDING).llama.cpp Replaces llamafile
providers::llamafileis gone.providers::llamacpptargetsllama-server, the upstream everyone actually runs; a.llamafileserves the same API. It supports completion, embeddings and, new this release, rerank and model listing. It sends images in tool results, which llama.cpp honours and OpenAI does not; that capability was first attempted by @inqode-lars. A specific-functiontool_choice, which llama-server silently served asauto, is now refused before sending. Construct it withllamacpp::from_env()orllamacpp::new(key).Huge thank you to everyone who made 0.43 happen:
We build Rig, Rig builds us!
Full changelog: v0.42.0...v0.43.0
All reactions