Ratel Docs
ReferencePython packages

ratel-ai

Raw API of ratel-ai — every exported class, function, and constant of the Python SDK.

v0.5.0 · Python · PyPI · source

Generated from the doc comments at ratel-ai/ratel@5b6e154 — do not edit by hand. Regenerate with pnpm sync:api in apps/docs.

Classes

DimensionMismatchError

A query/corpus embedding dimension mismatch.

EmbedderError

Embedding model load / inference failure (subclass of RuntimeError).

EndpointEmbeddingConfig

OpenAI-compatible embedding endpoint configuration.

Attributes:

  • model: str
  • url: str

ExecutableTool

ExecutableTool(id: str, name: str, description: str, input_schema: dict[str, Any] = dict(), output_schema: dict[str, Any] = dict(), execute: Executor = None)

A Tool plus the handler that runs it. Registered into a ToolCatalog.

Attributes:

  • execute: Executor = field(default=None)

HuggingFaceEmbeddingConfig

In-process HuggingFace embedding model configuration.

Attributes:

  • huggingface: str

LocalEmbeddingConfig

In-process local-directory embedding model configuration.

Attributes:

  • local: str

McpServerHandle

McpServerHandle(tool_ids: list[str], server_instructions: str | None, close: Callable[[], Awaitable[None]])

What register_mcp_server returns: the registration's outcome.

Attributes:

  • tool_ids (list[str]) — the namespaced <server>__<tool> ids registered into the catalog, in upstream listing order.
  • server_instructions (str | None) — the instructions value passed to register_mcp_server (the caller reads it from its own initialize result), or None.
  • close (Callable[[], Awaitable[None]]) — async teardown — the on_close passed to register_mcp_server, or a no-op. The session itself stays caller-owned either way.

OllamaEmbeddingConfig

Local Ollama embedding endpoint configuration.

Attributes:

  • ollama: str

SearchHit

A single search result: the matched tool id and its relevance score.

Attributes:

  • score: float — Relevance score; higher ranks first. The scale depends on the search method: raw BM25 (unbounded) for "bm25", cosine similarity for "semantic", reciprocal-rank-fusion for "hybrid" — scores from different methods are not comparable.
  • tool_id: str — Id of the matched tool, as passed to register.

Skill

Skill(id: str, name: str, description: str, tags: list[str] = list(), tools: list[str] = list(), metadata: dict[str, list[str]] = dict(), body: str = '')

Skill metadata: what the index ranks and the capability tools surface.

Attributes:

  • body: str = ''
  • description: str
  • id: str
  • metadata: dict[str, list[str]] = field(default_factory=dict)
  • name: str
  • tags: list[str] = field(default_factory=list)
  • tools: list[str] = field(default_factory=list)

SkillCatalog

SkillCatalog(trace: TraceSinkConfig | None = None, method: SearchMethod = 'bm25', embedding: EmbeddingSpec | None = None)

Registry of skills. Register once, then search and load bodies by id.

Create an empty skill catalog.

Parameters:

  • trace (TraceSinkConfig | None) — where trace events go; None keeps the default no-op sink.
  • method (SearchMethod) — default retrieval method for search — see ToolCatalog.__init__; a "semantic"/"hybrid" catalog embeds inside register, and dense results come from search_async.
  • embedding (EmbeddingSpec | None) — model for semantic/hybrid retrieval — see ToolCatalog.__init__; retained and validated under "bm25" too.

drain_trace_events

drain_trace_events() -> list[dict[str, Any]]

Drain captured trace envelopes; [] unless the sink is "memory".

get

get(skill_id: str) -> Skill | None

Return the registered Skill for an id, or None if unknown.

has

has(skill_id: str) -> bool

Return whether a skill with this id is registered.

invoke

invoke(skill_id: str) -> str

Return a skill's body for dispatch, recording a skill_invoke event.

Synchronous, unlike ToolCatalog.invoke — the body is already in memory, there is no handler to run.

Parameters:

  • skill_id (str) — id of a registered skill.

Returns: str — The skill's body (Markdown), verbatim as registered.

Raises:

  • ValueError — on an unknown id — callers at the capability-tool boundary translate this into a structured error for the agent.

record_event

record_event(event: dict[str, Any]) -> None

Record a trace event into the catalog's sink.

See ToolCatalog.record_event for the event contract.

register

register(skills: Skill | Iterable[Skill]) -> Awaitable[None]

Register one skill or many — the single entry point for both.

Metadata is stored synchronously when register(...) is called (name/description/tags are indexed; tools, metadata, body are stored but not indexed), so a forgotten await never drops the corpus. The returned awaitable drives only the embedding pass: on a "semantic"/"hybrid" catalog it embeds the batch off-thread and surfaces errors when awaited; a BM25 catalog never loads a model. Always await the result. Re-registering an id replaces it in place.

A model or dimension change is not recovered in place — construct a new catalog and re-register.

Parameters:

  • skills (Skill | Iterable[Skill]) — a single Skill or an iterable of them. Pass the whole batch at once for a single embedding request.

Raises:

  • EmbedderError — on a semantic/hybrid catalog, if embedding fails (when awaited).
  • RuntimeError — if a dense operation already owns the registry.
search(query: str, top_k: int, origin: SearchOrigin = 'direct', method: SearchMethod | None = None) -> list[SkillHit]

Rank registered skills synchronously with BM25.

The skill twin of ToolCatalog.search: a dense resolved method raises immediately with guidance to use search_async.

Returns: list[SkillHit] — Up to top_k SkillHits, best first.

search_async

async search_async(query: str, top_k: int, origin: SearchOrigin = 'direct', method: SearchMethod | None = None) -> list[SkillHit]

Rank skills asynchronously with BM25, semantic, or hybrid retrieval.

Dense methods require a complete cache built explicitly beforehand.

size

size() -> int

Return the number of registered skills.

SkillHit

A single skill search result: the matched skill id and its relevance score.

The skill analogue of SearchHit (tool_idskill_id).

Attributes:

  • score: float — Relevance score; higher ranks first. Same method-dependent scale as SearchHit.score, computed against the skill corpus.
  • skill_id: str — Id of the matched skill, as passed to register.

SkillRegistry

SkillRegistry(embedding: EmbeddingSpec | None = None, *, method: SearchMethod = 'bm25', spec: str | None = None, huggingface: str | None = None, local: str | None = None, ollama: str | None = None, url: str | None = None, model: str | None = None, revision: str | None = None, api_key_env: str | None = None, query_prefix: str | None = None, doc_prefix: str | None = None, pooling: str | None = None, download: bool | None = None)

Typed Python facade over the private native skill registry.

Create a metadata registry with an optional embedding model.

A "semantic"/"hybrid" method makes register embed eagerly (inside the call, on a worker thread); "bm25" keeps registration model-free.

drain_trace_events

drain_trace_events() -> list[dict[str, Any]]

Drain captured native trace events.

record_event

record_event(event: dict[str, Any]) -> None

Record an SDK-layer trace event.

register

register(item: Skill | Iterable[Skill] | str, name: str | None = None, description: str | None = None, tags: list[str] | None = None, tools: list[str] | None = None, metadata: dict[str, list[str]] | None = None, body: str | None = None) -> Awaitable[None]

Register one Skill, many Skills, or a flat (id, name, …) tuple.

Metadata is indexed synchronously when register(...) is called (a forgotten await never drops the corpus); the returned awaitable drives only the embedding pass. On a "semantic"/"hybrid" registry it embeds in one batched, off-thread pass (errors surface when awaited); "bm25" has nothing to embed. Always await the result.

search

search(query: str, top_k: int) -> list[SkillHit]

Run synchronous, model-free BM25 retrieval.

search_async

async search_async(query: str, top_k: int, origin: SearchOrigin = 'direct', method: SearchMethod = 'bm25') -> list[SkillHit]

Search immediately with BM25 or run dense retrieval on a worker thread.

search_with_method

search_with_method(query: str, top_k: int, origin: SearchOrigin, method: SearchMethod) -> list[SkillHit]

Run BM25 synchronously; dense retrieval is async-only.

search_with_origin

search_with_origin(query: str, top_k: int, origin: SearchOrigin) -> list[SkillHit]

Run BM25 retrieval with an explicit trace origin.

set_trace_sink

set_trace_sink(kind: str, session_id: str | None = None, path: str | None = None) -> None

Replace the native trace sink.

Tool

Tool(id: str, name: str, description: str, input_schema: dict[str, Any] = dict(), output_schema: dict[str, Any] = dict())

Tool metadata: what the index ranks and the capability tools surface.

Attributes:

  • description: str
  • id: str
  • input_schema: dict[str, Any] = field(default_factory=dict)
  • name: str
  • output_schema: dict[str, Any] = field(default_factory=dict)

ToolCatalog

ToolCatalog(trace: TraceSinkConfig | None = None, method: SearchMethod = 'bm25', embedding: EmbeddingSpec | None = None)

Registry + executors. Register tools once, then search and invoke by id.

Create an empty catalog.

Parameters:

  • trace (TraceSinkConfig | None) — where trace events go; None keeps the default no-op sink.
  • method (SearchMethod) — default retrieval method for search — "bm25" (the historical, model-free behavior), "semantic" or "hybrid". A per-call method= overrides it. A "semantic"/"hybrid" catalog embeds inside register; dense results come from search_async.
  • embedding (EmbeddingSpec | None) — model for semantic/hybrid retrieval (a path string or a keyed dict — see EmbeddingSpec). Retained and validated even under "bm25" so a later async semantic override can use it.

drain_trace_events

drain_trace_events() -> list[dict[str, Any]]

Drain captured trace envelopes; [] unless the sink is "memory".

get

get(tool_id: str) -> Tool | None

Return the metadata-only Tool for an id, or None if unknown.

get_executable

get_executable(tool_id: str) -> ExecutableTool | None

Return the ExecutableTool (metadata plus handler) for an id, or None.

has

has(tool_id: str) -> bool

Return whether a tool with this id is registered.

invoke

async invoke(tool_id: str, args: dict[str, Any]) -> Any

Run a registered tool's handler and return its result.

This is the canonical place that absorbs the sync/async executor difference: the handler is called first and the result awaited only if it is awaitable, so plain functions and async def executors (e.g. MCP/HTTP tools) are both supported. Callers must route invocations here rather than re-deriving that logic. Emits invoke_start / invoke_end / invoke_error trace events and wraps the call in an execute_tool OTel span (ADR-0007).

Parameters:

  • tool_id (str) — id of a registered tool.
  • args (dict[str, Any]) — the arguments dict passed to the handler.

Returns: Any — Whatever the handler returns (awaited if it returned an awaitable).

Raises:

  • ValueError — if tool_id is not registered.
  • Exception — whatever the handler raises, re-raised after an invoke_error trace event is recorded.

record_event

record_event(event: dict[str, Any]) -> None

Record a trace event into the catalog's sink.

Parameters:

  • event (dict[str, Any]) — a dict matching one of the core-owned TraceEvent shapes (ADR-0007), e.g. {"type": "gateway_search", ...}.

Raises:

  • ValueError — if the dict doesn't match any known event shape.

register

register(tools: ExecutableTool | Iterable[ExecutableTool]) -> Awaitable[None]

Register one tool or many — the single entry point for both.

Metadata and the executor handler are stored synchronously, the instant register(...) is called, so a forgotten await can never silently drop the corpus. The returned awaitable drives only the embedding pass: on a "semantic"/"hybrid" catalog it embeds the batch in one pass on a worker thread (the event loop is never blocked), and embedding errors (model load / endpoint / auth / dimension) surface when it is awaited. A BM25 catalog never loads a model and the awaitable is a no-op. Always await the result — a semantic/hybrid search after an un-awaited register raises rather than ranking an empty corpus. Re-registering an id replaces it in place; the index never holds a duplicate.

A model or dimension change is not recovered in place — construct a new catalog and re-register.

Parameters:

  • tools (ExecutableTool | Iterable[ExecutableTool]) — a single ExecutableTool or an iterable of them; each execute must be set. Pass the whole batch at once for a single embedding request; separate register calls embed separately.

Raises:

  • ValueError — if any execute is None, or a schema isn't JSON-serializable.
  • EmbedderError — on a semantic/hybrid catalog, if embedding fails (when awaited).
  • RuntimeError — if a dense operation already owns the registry.

search

search(query: str, top_k: int, origin: SearchOrigin = 'direct', method: SearchMethod | None = None) -> list[SearchHit]

Rank registered tools synchronously with BM25.

Parameters:

  • query (str) — what the caller wants to do.
  • top_k (int) — max hits to return.
  • origin (SearchOrigin) — who initiated the search — labels the trace event only.
  • method (SearchMethod | None) — per-call override of the catalog's default retrieval method ("bm25" | "semantic" | "hybrid").

Returns: list[SearchHit] — Up to top_k SearchHits, best first.

Raises:

  • ValueError — if method is not "bm25", "semantic" or "hybrid".
  • RuntimeError — if the resolved method is semantic/hybrid; use search_async for dense retrieval.

search_async

async search_async(query: str, top_k: int, origin: SearchOrigin = 'direct', method: SearchMethod | None = None) -> list[SearchHit]

Rank tools asynchronously with BM25, semantic, or hybrid retrieval.

Dense methods require the corpus to have been embedded by register on a semantic/hybrid catalog; searching never embeds missing corpus vectors.

ToolRegistry

ToolRegistry(embedding: EmbeddingSpec | None = None, *, method: SearchMethod = 'bm25', spec: str | None = None, huggingface: str | None = None, local: str | None = None, ollama: str | None = None, url: str | None = None, model: str | None = None, revision: str | None = None, api_key_env: str | None = None, query_prefix: str | None = None, doc_prefix: str | None = None, pooling: str | None = None, download: bool | None = None)

Typed Python facade over the private native tool registry.

Create a metadata registry with an optional embedding model.

A "semantic"/"hybrid" method makes register embed eagerly (inside the call, on a worker thread); "bm25" keeps registration model-free.

drain_trace_events

drain_trace_events() -> list[dict[str, Any]]

Drain captured native trace events.

record_event

record_event(event: dict[str, Any]) -> None

Record an SDK-layer trace event.

register

register(item: Tool | Iterable[Tool] | str, name: str | None = None, description: str | None = None, input_schema: dict[str, Any] | None = None, output_schema: dict[str, Any] | None = None) -> Awaitable[None]

Register one Tool, many Tools, or a flat (id, name, …) tuple.

Metadata is indexed synchronously, the instant register(...) is called, so a forgotten await can never silently drop the corpus. The returned awaitable drives only the embedding pass — on a "semantic"/"hybrid" registry it embeds in one batched, off-thread pass (embedding errors surface when awaited); "bm25" has nothing to embed and the awaitable is a no-op. Always await the result.

search

search(query: str, top_k: int) -> list[SearchHit]

Run synchronous, model-free BM25 retrieval.

search_async

async search_async(query: str, top_k: int, origin: SearchOrigin = 'direct', method: SearchMethod = 'bm25') -> list[SearchHit]

Search immediately with BM25 or run dense retrieval on a worker thread.

search_with_method

search_with_method(query: str, top_k: int, origin: SearchOrigin, method: SearchMethod) -> list[SearchHit]

Run BM25 synchronously; dense retrieval is async-only.

search_with_origin

search_with_origin(query: str, top_k: int, origin: SearchOrigin) -> list[SearchHit]

Run BM25 retrieval with an explicit trace origin.

set_trace_sink

set_trace_sink(kind: str, session_id: str | None = None, path: str | None = None) -> None

Replace the native trace sink.

TraceSinkConfig

TraceSinkConfig(kind: str, session_id: str | None = None, path: str | None = None)

Where the catalog's trace events go. Mirrors the TS TraceSinkConfig union.

kind: "noop" | "memory" | "jsonl". session_id is required for memory/jsonl; path is required for jsonl.

Attributes:

  • kind: str
  • path: str | None = None
  • session_id: str | None = None

UpstreamServerInfo

UpstreamServerInfo(name: str, description: str | None = None, instructions: str | None = None, tool_count: int | None = None, needs_auth: bool = False)

An upstream MCP server, as advertised in the capability-tool descriptions.

Pass a list of these to search_capabilities_tool (or the deprecated search_tools_tool) to append a "this catalog aggregates…" listing to the tool description shown to the model, and to enrich each search result's server group with the upstream's description and instructions.

Attributes:

  • name (str) — the catalog namespace of the server — the <name> prefix of its <name>__<tool> tool ids.
  • description (str | None) — what the server offers; compacted to one line in listings.
  • instructions (str | None) — the server's usage instructions (from its MCP initialize result), surfaced on matching server groups.
  • tool_count (int | None) — number of tools the server contributed, shown in listings.
  • needs_auth (bool) — True when the upstream rejected its boot connection with a 401 / re-auth needed; listings append "(auth required)".

Functions

configure_telemetry

configure_telemetry(*, api_key: str | None = None, endpoint: str | None = None, headers: dict[str, str] | None = None, service_name: str | None = None, capture_content: ContentCapture | str | None = None, include_span_and_events: bool | None = None) -> Any

Register a Ratel-owned OTLP exporter (convenience wiring for the greenfield case).

Ships the spans this SDK emits to Ratel Cloud (or any OTLP endpoint) by delegating to ratel_ai_telemetry.init, which needs the OpenTelemetry SDK — install it with pip install 'ratel-ai[otlp]'. A host already running its own OpenTelemetry provider should skip this (the SDK's spans flow to that provider) and add ratel_span_processor from ratel_ai_telemetry.

capture_content / include_span_and_events opt into message/tool content capture in code via set_content_capture: capture_content sets an exact mode, include_span_and_events is bool sugar (True -> SPAN_AND_EVENT, False -> NO_CONTENT); capture_content wins when both are given. A provided option beats OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT (the env var is the fallback when neither is given, as in OTel). The returned handle's shutdown() clears the override, restoring env-driven behavior; the clear is generation-scoped, so a stale handle shutting down late never clobbers an override a newer configure_telemetry/set_content_capture call installed.

Parameters:

  • api_key (str | None) — Ratel Cloud API key override; defaults to RATEL_API_KEY.
  • endpoint (str | None) — OTLP endpoint override; defaults to RATEL_URL.
  • headers (dict[str, str] | None) — Extra headers sent with every export request.
  • service_name (str | None) — service.name resource attribute; defaults per init.
  • capture_content (ContentCapture | str | None) — Exact content-capture mode to set (see above).
  • include_span_and_events (bool | None) — Boolean sugar for capture_content (see above).

Returns: Any — A per-call shutdown handle (handle.shutdown() / handle.force_flush()), the same shape on every path. Attribute access delegates to the shared handle init returns; because that handle is shared across callers, shutting it down stops export for all of them.

Raises:

  • ModuleNotFoundError — if the OpenTelemetry exporter is not installed (pip install 'ratel-ai[otlp]').
  • ValueError — if capture_content is not a recognized mode — raised before any exporter is wired, so a bad option has no side effects.

format_upstream_line

format_upstream_line(s: UpstreamServerInfo) -> str

Render one upstream server as a listing bullet for a tool description.

Format: - <name> — <description> (<N> tools) (auth required), where the description is whitespace-collapsed and truncated to ~160 chars, and each trailing part appears only when the corresponding field is set.

Parameters:

  • s (UpstreamServerInfo) — the upstream server to render.

Returns: str — A single - -prefixed line, ready to join into the "this catalog aggregates…" listing.

get_skill_content_tool

get_skill_content_tool(catalog: SkillCatalog) -> ExecutableTool

Build the get_skill_content tool: load a skill's full body by id.

The returned tool resolves skillId and answers {"body": <markdown>} via SkillCatalog.invoke (which records a skill_invoke trace event). It never raises into the host: an unknown or non-string id comes back as a structured {"error": ..., "isError": True} payload the model can recover from, mirroring invoke_tool.

Parameters:

  • catalog (SkillCatalog) — the skill catalog to load bodies from.

Returns: ExecutableTool — An ExecutableTool to put in the agent's direct tool list alongside search_capabilities.

invoke_tool_tool

invoke_tool_tool(catalog: ToolCatalog, *, on_unauthorized: OnUnauthorized | None = None) -> ExecutableTool

Build the invoke_tool tool: run any catalog tool by id.

The returned tool resolves toolId, forwards the nested args object to ToolCatalog.invoke, and never raises into the host: an unknown id, malformed args, or a tool exception all come back as a structured {"error": ..., "isError": True} payload the model can recover from. A flattened call (arguments at the top level instead of nested under args) is tolerated. When the tool raises an UnauthorizedError, the payload is {"error": "needs_auth", ...} with a re-auth hint and, for namespaced <server>__<tool> ids, the upstream server name.

Parameters:

  • catalog (ToolCatalog) — the catalog to resolve and run tool ids against.
  • on_unauthorized (OnUnauthorized | None) — called with the upstream server name when a tool raises UnauthorizedError; may be sync or async. Skipped when the tool id has no <server>__ namespace prefix.

Returns: ExecutableTool — An ExecutableTool to put in the agent's direct tool list.

register_mcp_server

async register_mcp_server(catalog: ToolCatalog, *, name: str, session: Any, transport_label: str = 'unknown', instructions: str | None = None, on_close: Callable[[], Awaitable[None]] | None = None) -> McpServerHandle

Ingest an initialized MCP ClientSession into the catalog.

Parameters:

  • catalog (ToolCatalog) — the catalog to register the upstream tools into.
  • name (str) — namespace prefix for tool ids (<name>__<tool>).
  • session (Any) — an initialized mcp.ClientSession owned by the caller.
  • transport_label (str) — recorded on the upstream_register trace event.
  • instructions (str | None) — the upstream's server instructions (from initialize), if any.
  • on_close (Callable[[], Awaitable[None]] | None) — optional async teardown invoked by the handle's close().

Returns: McpServerHandle — An McpServerHandle with the registered tool ids.

Raises:

  • ImportError — if the optional mcp package is not installed (pip install 'ratel-ai[mcp]').

search_capabilities_tool

search_capabilities_tool(catalog: ToolCatalog, skill_catalog: SkillCatalog | None = None, *, upstream_servers: Sequence[UpstreamServerInfo] | None = None) -> ExecutableTool

Build the search_capabilities tool: unified discovery over tools AND skills.

The returned tool ranks two independent buckets, each with its own top-K budget — so a relevant skill is never starved out of the results by a large number of matching tools (and the two BM25 corpora are never score-compared). Tools land grouped by upstream server; a matched skill's declared tools are pulled into the tools bucket additively (score 0), so the agent gets the playbook and its toolkit in one turn. The skills bucket (and the mention of get_skill_content in the description) is only advertised when a non-empty skill_catalog is wired in.

Parameters:

  • catalog (ToolCatalog) — the tool catalog to search.
  • skill_catalog (SkillCatalog | None) — optional skill catalog, ranked against the same query in its own bucket.
  • upstream_servers (Sequence[UpstreamServerInfo] | None) — upstream MCP servers to advertise in the tool description and to enrich result server groups with.

Returns: ExecutableTool — An ExecutableTool to put in the agent's direct tool list.

search_tools_tool

search_tools_tool(catalog: ToolCatalog, *, upstream_servers: Sequence[UpstreamServerInfo] | None = None) -> ExecutableTool

Build the pre-0.2.0 tools-only discovery tool (id search_tools).

Keeps the original behaviour: a flat {groups} result and no skills bucket. New code should use ratel_ai.search_capabilities_tool instead. Registering both lets a host serve the old and new names during a migration window.

Parameters:

  • catalog (ToolCatalog) — the tool catalog to search.
  • upstream_servers (Sequence[UpstreamServerInfo] | None) — upstream MCP servers to advertise in the tool description and to enrich result server groups with.

Returns: ExecutableTool — An ExecutableTool to put in the agent's direct tool list.

Deprecated — Since 0.2.0: use ratel_ai.search_capabilities_tool. Tracked for removal in RAT-250.

Constants

  • GET_SKILL_CONTENT_ID = 'get_skill_content' — Id (and name) of the skill-loading tool built by get_skill_content_tool.
  • INVOKE_TOOL_ID = 'invoke_tool' — Id (and name) of the invocation tool built by invoke_tool_tool.
  • SEARCH_CAPABILITIES_ID = 'search_capabilities' — Id (and name) of the discovery tool built by search_capabilities_tool.
  • SEARCH_TOOLS_ID = 'search_tools' — Id (and name) of the deprecated pre-0.2.0 discovery tool built by search_tools_tool; superseded by ratel_ai.SEARCH_CAPABILITIES_ID.
  • EmbeddingModelConfig = Union[HuggingFaceEmbeddingConfig, LocalEmbeddingConfig, OllamaEmbeddingConfig, EndpointEmbeddingConfig] — Mutually exclusive keyed embedding-source configurations.
  • EmbeddingSpec = Union[str, EmbeddingModelConfig] — Embedding selection; a bare string is a local model directory path.
  • Executor = Callable[[dict[str, Any]], Union[Awaitable[Any], Any]] — A tool handler: takes the tool's arguments dict, returns the result. May be sync or async (tool inputs are heterogeneous across the catalog); ToolCatalog.invoke absorbs the difference.
  • OnUnauthorized = Callable[[str], Union[Awaitable[None], None]] — Notified when the underlying tool raises UnauthorizedError, with the upstream server name inferred from the toolId. May be sync or async.
  • SearchMethod = str — Retrieval engine: "bm25" (lexical, model-free, the default), "semantic" (dense embeddings) or "hybrid" (both, fused).
  • SearchOrigin = str — Who initiated a search: "direct" (host code, the default) or "agent" (a model calling a capability tool). Labels the emitted trace event only — ranking is unaffected.

On this page