Changelog
Release history of ratel-ai.
ratel-ai release history · PyPI · source
Synced verbatim from the package's
CHANGELOG.mdatratel-ai/ratel@d8635d5— do not edit by hand. Regenerate withpnpm sync:apiinapps/docs.
All notable changes to ratel-ai (the Python SDK) are documented here.
The format follows Keep a Changelog and this package adheres to Semantic Versioning.
[0.7.0] - 2026-08-07
Added
- Whole-catalog skill reload:
SkillCatalog.replace_all/SkillRegistry.replace_all(ADR-0015). For a source that fetches the full skill catalog rather than individual changes — the batch is the catalog, so ids missing from it are removed, including ones registered in-process. Two-phase likeregister: the corpus swap lands synchronously (a forgottenawaitnever leaves a half-applied reload) and only the embedding pass is awaited, so a reload whose embedding pass fails still reports what the swap changed. Returns aPendingReplacecarrying the finaladded/removed/updated/unchangedcounts; awaiting it drives the embedding pass and resolves to a plainReplaceOutcome. Alwaysawaitthe result so an embedding failure raises rather than being swallowed. On failure the new corpus is live and BM25 ranks it while semantic search reports not-built until a later pass succeeds; a reload started while a dense operation owns the registry is rejected rather than blended, and reloading an unchanged catalog costs zero embeddings.PendingReplaceandReplaceOutcomeare exported fromratel_ai. register_mcp_serverfollows everytools/listpage. Ingestion previously read only the first page, silently dropping every tool past it on a paginated server. It now walksnextCursorto exhaustion (treating""as a valid cursor, per MCP — only an absentnextCursorends pagination) acrossmcpclient versions before and after 1.18, capped at 64 pages.McpToolsListError(with a stablecodeof"RepeatedCursor"or"PaginationExceeded") is exported fromratel_ai, so a cursor loop or a runaway server is a typed failure rather than a hang.McpServerHandle.tool_idsnow spans all pages in upstream list order.
Fixed
- Telemetry tool-result capture records only the stable
CallToolResultfields (content,structuredContent,isError). It previously dumped the whole model, so fields themcppackage adds or renames between versions leaked into captured content and made the recorded payload depend on the installed client version.
[0.6.0] - 2026-07-28
Coming from
0.6.0rc0? That RC was tagged off a branch that predated 0.5.2, so it shipped neither theEventRecordcontent-capture fixes nor the baseratel-ai-telemetryruntime dependency. Read the 0.5.2 entry below as part of this upgrade. Upgrades from 0.5.2 are unaffected: for them this release is purely additive.
Added
- Experimental adaptive usage ranking (ADR-0014).
IntentGraphplusexperimental_enable_adaptive_ranking,experimental_rebuild_intent_graph,experimental_disable_adaptive_ranking, andexperimental_adaptive_ranking_statusonToolCatalog/SkillCatalog. The catalog learns from each search-then-invoke and boosts future rankings; persist and reload viaIntentGraph.to_json/from_json, and track writes viagraph.rev. Shipped behind anexperimental_prefix — the API may change until it graduates. rankandfusedon search hits: order onrank, and branch onfusedto know whether the usage arm changed the ranking.- Opt-in recovery after an embedding-model change:
experimental_enable_adaptive_ranking(graph, rebuild_on_model_change=True)re-embeds a paused graph on the next dense search. Default off; explicitexperimental_rebuild_intent_graph()otherwise.experimental_adaptive_ranking_statusreturns anAdaptiveRankingStatusthat carries the paused/active state and the mismatched-model detail.
[0.5.2] - 2026-07-26
Changed
configure_telemetry(endpoint=...)now defaults toRATEL_OTLP_ENDPOINT, falling back to the supersededRATEL_URLwith aDeprecationWarning.RATEL_URLalso selects the catalog source (ADR-0003), so it no longer doubles as the OTLP destination. Resolution lives inratel-ai-telemetry>=0.1.3; nothing breaks here, aRATEL_URL-only install keeps exporting to the same endpoint.
Fixed
- Emit content capture as structured OpenTelemetry Logs
EventRecords, keep tool results out of inference-output messages, and export those records throughconfigure_telemetry(). - Serialize real MCP
CallToolResultvalues into telemetry instead of recording an empty string. - Preserve heterogeneous JSON arrays losslessly despite OpenTelemetry Python 1.41's homogeneous-array limitation.
- Ship and require the OTel-free telemetry vocabulary version that defines the EventRecord contract, so base installs emit into host-owned OpenTelemetry providers.
[0.5.1] - 2026-07-24
Changed
- Ship the native extension built with symbol stripping and thin LTO (
[profile.release]), materially shrinking the wheel's compiled binary. No API or behavior change.
[0.5.0] - 2026-07-20
Added
register()accepts a single item or an iterable across tool/skill registries and catalogs.- Configurable default, HuggingFace, local Candle, Ollama, and OpenAI-compatible
endpoint embedding sources, with public
EmbeddingSpec,EmbeddingModelConfig, and source-specificTypedDictvariants.
Changed
- BREAKING:
register()now accepts a single tool/skill or an iterable of them and folds embedding in, returning an awaitable (Awaitable[None]): on a"semantic"/"hybrid"catalog it embeds the batch off the asyncio loop (GIL released), so embedding errors (model load / endpoint / auth / dimension) surface fromawait register(...). A"bm25"catalog registers metadata only and never loads a model.search()stays synchronous BM25-only;search_async()covers BM25/semantic/hybrid. There is noregister_many(),build_embeddings(), orrebuild_embeddings()—register()embeds, and recovery from a model/dimension change is to construct a new catalog and re-register. - Capability tools await async retrieval; MCP ingestion embeds ingested tools during
register. - Embedding configuration is validated and retained on BM25-default catalogs for later async semantic/hybrid overrides; typed config variants are mutually exclusive.
Fixed
- A forgotten
awaitonregister()no longer silently drops the corpus: an un-awaited call still registers the tools/skills (BM25 keeps working), and a"semantic"/"hybrid"search_asyncafter an un-awaitedregister()raises an actionable "not awaited" error instead of ranking an empty corpus.
[0.4.2] - 2026-07-11
Changed
configure_telemetry()returns a per-call shutdown handle (handle.shutdown()/handle.force_flush()) on every path — the no-override path no longer leaksinit()'s shared provider directly. Because that provider is shared across callers, shutting one handle down stops export for all of them.
Fixed
configure_telemetry()no longer mutates a shared provider'sshutdownmethod. When idempotent telemetry initialization reuses one provider, a stale handle can no longer clear a newer caller's generation-scoped content-capture override.
[0.4.1] - 2026-07-10
Added
configure_telemetryopts into message/tool content capture programmatically:capture_contentsets the exactContentCapturemode (validated like the env var — case-insensitive, legacy boolean forms accepted — raising aValueErroron garbage before any exporter is wired), andinclude_span_and_eventsis boolean sugar (True→SPAN_AND_EVENT,False→NO_CONTENT).capture_contentwins overinclude_span_and_events; when neither is provided,OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENTkeeps ruling (a provided option beats the env var, as in OTel code-over-env precedence). The returned provider'sshutdown()restores env-driven behavior via a generation-scoped clear (clear_content_capture), so a stale handle shutting down late never clobbers an override a newerconfigure_telemetryinstalled. Theset_content_capture/clear_content_capture/ContentCaptureprimitives live inratel_ai_telemetry.
[0.4.0] - 2026-07-07
Added
- OpenTelemetry emission. The SDK now opens an OTel span at each funnel boundary —
execute_tool(gen_ai.operation.name,gen_ai.tool.name,ratel.tool.args_size_bytes),ratel.search(target,top_k, origin,hit_count),ratel.skill.load,ratel.upstream.register, andratel.auth.flow— alongside the existing localrecord_eventstream, which is unchanged. Emission is transparent and free by default: theopentelemetryAPI and the vocabulary are imported lazily, so the base (dependency-free) install is a pure pass-through no-op, and when OpenTelemetry is present the spans flow to whatever provider is registered. Built on the OTel-freeratel_ai_telemetryvocabulary, so the base install stays dependency-free. configure_telemetry(api_key=..., endpoint=..., headers=..., service_name=...)convenience wiring, exported fromratel_ai: installs a Ratel-owned OTLP exporter (via the new[otlp]extra,pip install 'ratel-ai[otlp]') that ships the SDK's spans to Ratel Cloud (or any OTLP endpoint) and returns the provider as a shutdown handle. Hosts already running OpenTelemetry skip it and addratel_span_processorfromratel_ai_telemetryinstead.- Message/tool content (
ratel.search.query,gen_ai.tool.call.arguments/.result) rides span attributes only whenOTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENTselects a span mode (SPAN_ONLY/SPAN_AND_EVENT); default off.
[0.3.0] - 2026-07-06
Added
ToolCatalog/SkillCatalogaccept a defaultmethod("bm25"|"semantic"|"hybrid") andsearch(query, top_k, origin=..., method=...)takes a per-call override."bm25"(default) is unchanged and model-free;"semantic"/"hybrid"load a local embedding model and raiseRuntimeErrorif it fails to load. Exposed via the nativesearch_with_methodbinding and theSearchMethodtype.- A
"semantic"/"hybrid"catalog embeds each tool/skill eagerly atregister(incrementally), so searches never pay the corpus-embedding cost. Newcatalog.build_embeddings()pre-computes embeddings on demand (e.g. after a bulk register). BM25 catalogs do neither. A semantic/hybrid search on a catalog with no embeddings built raisesRuntimeError(embeddings not computed) rather than embedding during the search.
[0.2.1-rc.1] - 2026-07-04
Changed
- First release cut under the per-package release scheme (ADR-0008):
ratel-ainow versions and ships independently of the core crate and JS SDK, taggedsdk-py-v*. No API changes since 0.2.0.
[0.2.0] - 2026-06-16
Changed
- BREAKING:
search_tools_tool→search_capabilities_tool(SEARCH_TOOLS_ID→SEARCH_CAPABILITIES_ID). It now returns two independently-ranked buckets —{ tools, skills }. Brings the Python SDK to parity with the TypeScript SDK. The oldsearch_tools_tool/SEARCH_TOOLS_IDare kept as deprecated aliases (see Deprecated), so0.1.xcode keeps working after upgrading.
Added
- First-class skills:
SkillCatalog,Skill,get_skill_content_tool(get_skill_content), and the nativeSkillRegistry/SkillHit— the on-demand skill analogue of the tool catalog, ranked by a separate BM25 corpus. - Skill–tool coupling: a
Skillcan declare atoolslist, andsearch_capabilitiespulls a matched skill's declared tools into thetoolsbucket — additively (beyondtopKTools) and deduped against query hits — so the agent gets the playbook and the tools it needs in one turn.
Deprecated
search_tools_toolandSEARCH_TOOLS_ID. They retain their pre-0.2.0 behaviour — a tools-only{groups}result and thesearch_toolsid — so upgrading from0.1.xdoes not break existing callers. Migrate tosearch_capabilities_tool; the aliases will be removed in a future release.
Fixed
- Gateway error payloads carry
isError: True;invoke_toolrejects a non-objectargsinstead of forwarding stray top-level keys. search_capabilities_toolvalidatestopKTools/topKSkills(declaredinteger, positive):0, negative,bool, andfloatfall back to the default, matching the TypeScript SDK exactly.search_capabilities_tooladvertises theskillsbucket andget_skill_contentin its description only when a non-emptySkillCatalogis provided.
[0.1.6] - 2026-06-10
Added
- Initial release of the Python SDK. Binds the Rust core (
ratel-ai-core) via PyO3, distributed as prebuiltabi3wheels for darwin-arm64, darwin-x64, linux-x64-gnu, linux-arm64-gnu, and win32-x64-msvc — no Rust toolchain required to install. (v0.1.5shipped TS-only on 2026-05-10; the first release carrying Python is the next version bump.) Binding strategy locked in ADR-0006. - Full feature parity with the TypeScript SDK (
@ratel-ai/sdk):ToolRegistry/SearchHit— metadata-only BM25 index (native).ToolCatalogaccepts atraceconfig (noopdefault,memory, orjsonl); captured events flow through the Rust core sink (ADR-0007). Exposesrecord_event,drain_trace_events, and anoriginargument onsearch.invokeemitsinvoke_start/invoke_end/invoke_errorwithargs_size_bytesandtook_ms, and awaits coroutine executors.search_tools_tool/invoke_tool_toolgateway factories with verbatim descriptions and JSON schemas from the TS SDK.search_tools_toolemitsgateway_searchwithorigin: "agent";invoke_tool_toolemitsgateway_invoke/gateway_errorand handles theneeds_auth/on_unauthorizedpath.register_mcp_serveringests an upstream MCPClientSession(optionalmcpextra,pip install 'ratel-ai[mcp]'), namespacing tool ids as<server>__<tool>and emittingupstream_register/upstream_invoke/upstream_error.
- Ships type stubs (
_native.pyi,py.typed) for a fully typed install.