RAG Tool Curator docs v0.1.0
Get Started

Quickstart

Build an index and select tools for a query — the entire public surface of tool_curator is one factory function and two methods.

Tool Curator

from tool_curator import get_curator, load_tool_context

curator = get_curator(
    mode       = "rag",
    top_k      = 15,
    model_name = "BAAI/bge-small-en-v1.5",
    index_dir  = "/path/to/cache",     # "" disables disk caching
)

# your_tools: list[tuple[str, str]] — (tool_name, tool_description) pairs.
# This should already reflect your own access-control filtering — the
# curator never widens a tool pool, it only narrows it.
your_tools = [
    ("get_account_balance", "Returns the current balance for a customer account."),
    ("initiate_wire_transfer", "Initiates an outbound wire transfer between accounts."),
    # ...
]

# Build once, e.g. at session start when the tool pool becomes known.
synonyms = load_tool_context("/path/to/domain_synonyms.json")   # optional, {} if omitted
curator.build_index(your_tools, extra_context=synonyms)

# Per query.
selected = curator.select("can I send money to Rahul?", your_tools)
# selected: same (name, description) format, trimmed to top_k entries

That’s the whole interface: build_index() once per session, select() once per message. See API Reference: tool_curator for every parameter, and Configuration & Domain Synonyms for how domain_synonyms.json actually moves the accuracy numbers.

Multilingual Normalizer

from multilingual_normalizer import get_normalizer

normalizer = get_normalizer(provider="gemini", api_key="...")

english_query, language = normalizer.normalize(user_query)
# english_query is safe to hand to curator.select() (or any English-only retriever)
# language is the detected source language, "English" for the fast-path case

Run this before curator.select() in your per-message flow — the curator’s BGE embeddings are English-only, so an untranslated non-English query will retrieve on noise. See Multilingual Normalizer for the fast-path heuristic and how to add your own translation backend.

Putting them together

from tool_curator import get_curator, load_tool_context
from multilingual_normalizer import get_normalizer

curator    = get_curator(mode="rag", top_k=15, index_dir=".tool_cache")
normalizer = get_normalizer(provider="gemini", api_key=GEMINI_API_KEY)

curator.build_index(your_tools, extra_context=load_tool_context("domain_synonyms.json"))

# Per message:
english_query, language = normalizer.normalize(user_message)
selected = curator.select(english_query, your_tools)
tool_declarations = build_llm_tool_declarations(selected)   # your own LLM-format conversion
# proceed with your existing LLM call using tool_declarations

Everything downstream — tool execution, streaming, persistence — is unaffected; neither plug-in has a role in actually invoking tools. For a worked example wiring this into a multi-server MCP orchestration layer, see the Integration Guide.