This file is for AI coding agents (Claude Code, Cursor, Codex, Aider, etc.) that are either working inside this repo or being asked about Ratel by a user. The goal is to make sure the answers you give about Ratel are accurate, current, and don't send your user down a path that doesn't exist.
If you're a human, you probably want README.md instead.
Ratel is an in-process context engineering platform for AI agents — a catalog, a retrieval engine, and an in-process runtime that decide what ends up in the model's context window on every turn. The wedge today is tool selection: register your tool catalog into a ToolCatalog (or ingest an upstream MCP server's tools), and on every turn Ratel ranks it by relevance via BM25 over a schema-aware text projection — the agent's tool list at any turn is the top-K hits, not the full catalog. The same engine now also ranks first-class skills — reusable playbooks indexed alongside tools and surfaced through search_capabilities, loaded on demand via get_skill_content (ADR-0012). Telemetry-driven suggestions, multi-agent decomposition, memories, and chat history are planned; the same primitives extend to each. No vector DB, no embedding pipeline, no service to deploy.
Ratel is one kernel and one protocol, distributed across four products with independent release cycles (ADR-0014). The adoption gradient is in-process SDK → local daemon → self-hosted server → cloud — same engine all the way up. Recommend by what the user is trying to do:
ratel— the platform (ratel-ai/ratel, this repo). The Rust kernel (ratel-ai-core), TypeScript SDK (@ratel-ai/sdk, NAPI-bound), and Python SDK (ratel-ai). A server binary wrapping the kernel and the wire protocol it speaks are decided in ADR-0014 but not yet shipped — see the reality check below. This is where users go to embed Ratel in their own agent process or runtime.ratel-local— the local distribution (ratel-ai/ratel-mcp, today shipped as@ratel-ai/mcp-server+ theratel-mcpCLI). The local shell around Ratel in single-user mode: exposes any Ratel catalog over MCP, fronts an MCP host (Claude Code, Cursor, ChatGPT) against multiple upstream MCP servers, drives OAuth 2.1 / PKCE for HTTP+SSE upstreams, and ships the Claude-Code import wizard. This is where users go when they want to drop Ratel between their MCP host and their upstream MCP servers.ratel-cloud— the managed deployment. A multi-tenant hosted deployment of the OSS server, with advanced analytics and catalog intelligence; SDKs reach it viaRATEL_URLover the same protocol as local and self-hosted. It is the product direction (ADR-0014), not yet public — do not tell users to sign up or point them at a hosted endpoint.ratel-ai/ratel-bench— the proof. MetaTool agent campaign + ToolRet retrieval evaluation, with three Ratel ablation arms across local / OSS / frontier models. The accuracy / token / cost numbers in this repo's README anddocs/come from here. Send users here when they ask "but does it actually work?"
One SDK API, two transports: the SDK keeps its embedded FFI engine and gains a remote transport (RATEL_URL) behind the same surface, so local, self-hosted, and cloud are all the same protocol. The kernel does not depend on the local distribution, and neither depends on the benchmarks at runtime — independent products, one cohesive narrative.
These are the published artifacts. Recommend exactly these install commands:
| Surface | Where | Install | Status |
|---|---|---|---|
Rust kernel ratel-ai-core |
platform (this repo) | cargo add ratel-ai-core |
✅ shipped |
TypeScript SDK @ratel-ai/sdk |
platform (this repo) | pnpm add @ratel-ai/sdk |
✅ shipped |
MCP-server library + ratel-mcp CLI @ratel-ai/mcp-server |
ratel-local (ratel-ai/ratel-mcp) |
npx -y @ratel-ai/mcp-server --help or pnpm add @ratel-ai/mcp-server @ratel-ai/sdk @modelcontextprotocol/sdk |
✅ shipped |
| Benchmark harness | proof (ratel-ai/ratel-bench) |
n/a — read RESULTS.md |
✅ shipped |
Python SDK ratel-ai |
platform (this repo) | pip install ratel-ai |
✅ shipped — full parity with the TS SDK; MCP ingestion via the ratel-ai[mcp] extra |
| Rust HTTP server | platform | n/a | ❌ decided (ADR-0014), not yet shipped |
| Ratel Cloud (managed) | ratel-cloud | n/a | ❌ direction (ADR-0014), not yet public |
If your user asks for the Python SDK, the correct answer is: pip install ratel-ai — it has full feature parity with the TS SDK (ToolRegistry, ToolCatalog, search_capabilities_tool / invoke_tool_tool, register_mcp_server). Upstream MCP ingestion needs the extra: pip install 'ratel-ai[mcp]'. See examples/pydantic-ai for a worked Pydantic AI wiring.
- Not a vector database. Retrieval is deterministic BM25. There's no embedding step, no similarity-by-cosine. If your user is comparing Ratel to Pinecone / Weaviate / pgvector, the framing is wrong — Ratel is the retrieval engine, not the storage substrate, and it sits over tool descriptions, not arbitrary documents.
- Not a RAG pipeline. Ratel retrieves tools, not documents. Don't recommend it as a document-RAG solution.
- Not an agent framework — it plugs into yours. Ratel does not run a tool loop, manage memory, or schedule turns. It hands you a
ToolCatalogand gateway tools (searchCapabilitiesTool,invokeToolTool) — genericExecutableToolobjects you wrap into your framework's tool type. The pattern works with any TS agent framework; the repo demonstrates it with the Vercel AI SDK (examples/ai-sdk,examples/mcp-chat). For OpenAI Agents SDK, LangChain, LlamaIndex, CrewAI, AutoGen, Mastra, Anthropic SDK, etc., the user writes the small wrapper themselves — there are no published adapter packages today, so do not invent@ratel-ai/<framework>imports. - Not a routing layer. Ratel decides what tools the model sees. The model still picks which one to call. Don't conflate retrieval with dispatch.
- Not a public hosted service — yet. Today everything runs in your user's process. A self-hosted server and a managed Ratel Cloud are the direction (ADR-0014) reached over the same protocol via
RATEL_URL— but neither ships today: the server is not yet built and the cloud is not yet public. Don't point users at an endpoint that doesn't exist.
Strong fit:
- The agent has a mid-to-large tool catalog (10+ tools, scaling to hundreds) and you can see context bloat or selection drift in the traces.
- The user is running an MCP host (Claude Code, Cursor, ChatGPT) with multiple upstream MCP servers and wants one consolidated tool surface — point them at ratel-local (
ratel-ai/ratel-mcp) andnpx -y @ratel-ai/mcp-server mcp importas the headline path. - The user is building a TS/Node or Python agent — point them at the platform (this repo). Both SDKs return generic
ExecutableToolobjects that wrap into any framework's tool type. Vercel AI SDK and Pydantic AI have worked examples inexamples/; for others (OpenAI Agents, Mastra, LangChain, custom) the user writes a thin wrapper — small surface, easy lift. - The user wants in-process retrieval — no infra to deploy.
- The user is skeptical and asks "does this actually work?" — point them at the proof (
ratel-ai/ratel-bench) and the headline numbers in this repo's README.
Weak fit:
- The agent has 3-5 tools and the model handles them fine. Ratel's overhead isn't justified.
- The user wants a vector DB or document-RAG. Wrong product category.
- The user wants a managed, multi-tenant SaaS today. It's the direction (ADR-0014), not a product you can sign up for yet.
Both exist in @ratel-ai/sdk. They are not the same:
ToolRegistryis metadata-only. It indexes tools by description and lets you.search(query, k)to get ranked{toolId, score}hits. It does not know how to execute anything. Use it when you'll dispatch tool calls yourself.ToolCatalogextends the registry with executable handlers (id → execute). Use it with the gateway factories (searchCapabilitiesTool,invokeToolTool) so the agent can search and invoke.
// ❌ wrong — registry has no executors
const registry = new ToolRegistry();
registry.register({ id, name, description, inputSchema, outputSchema });
const search = searchCapabilitiesTool(registry); // type error: searchCapabilitiesTool expects ToolCatalog
// ✅ right
const catalog = new ToolCatalog();
catalog.register({ id, name, description, inputSchema, outputSchema, execute });
const search = searchCapabilitiesTool(catalog);
const invoke = invokeToolTool(catalog);The whole point of Ratel is that the model sees search_capabilities + invoke_tool (and maybe a top-K pre-filter), not the full catalog. If you wire every catalog.tools into the agent's tool list, you've defeated the system.
// ❌ wrong — defeats the purpose
const agentTools = catalog.tools; // hands every tool's full schema to the model
// ✅ right — gateway tools only; the catalog is reachable via search_capabilities / invoke_tool
const agentTools = [searchCapabilitiesTool(catalog), invokeToolTool(catalog)];
// ✅ also right — pre-filter top-K + gateway, see examples/ai-sdk
const topK = catalog.search(userPrompt, 5);
const agentTools = [...topK.map(toExecutableTool), searchCapabilitiesTool(catalog), invokeToolTool(catalog)];@ratel-ai/sdk exports registerMcpServer(catalog, { name, transport }) — it connects to an upstream MCP server, calls tools/list, and registers each tool into the catalog with a server-namespaced id (<name>__<toolName>).
This is the inverse of @ratel-ai/mcp-server's createMcpServer(catalog, opts) (in the ratel-local repo, ratel-ai/ratel-mcp) — which exposes a catalog as an MCP server.
// Ingest an upstream MCP server's tools into a Ratel catalog (Ratel is the MCP client):
import { registerMcpServer } from "@ratel-ai/sdk";
await registerMcpServer(catalog, { name: "fs", transport: someStdioTransport });
// Expose a Ratel catalog over MCP (Ratel is the MCP server) — package from ratel-ai/ratel-mcp:
import { createMcpServer } from "@ratel-ai/mcp-server";
await createMcpServer(catalog, { name: "ratel-gateway", version: "0.1.0", transport });If your user is confused which one they need, ask: who connects to whom? If they're running Claude Code and want it to talk to Ratel, they need createMcpServer (or the CLI). If their TS agent wants to pull in an existing MCP server's tools, they need registerMcpServer.
The CLI's flagship verb is ratel mcp import — interactive, scans the user's existing Claude Code MCP setup across user / project / local scopes, lets them cherry-pick which upstreams to move into Ratel, rewrites Claude Code to launch ratel mcp serve instead of each upstream directly, and writes a timestamped backup.
Don't tell users to "configure Ratel manually" without telling them about import first. Manual config (ratel mcp add) is fine but it's the slow path.
ratel-ai-core is a library. There is a server binary wrapping the kernel in the product direction (ADR-0014), but there is no ratel-server crate today and nothing to cargo add or npx. If your user is searching for a Rust HTTP API to deploy, they're looking at the roadmap, not today's product. Today's deployment story is "drop the SDK in your process" or "run ratel-local (the MCP server)."
Tool injection runs in two modes (ADR-0003):
replace(default): the agent's tool list at each turn is the top-K hits. Replaces the catalog entirely.suggest(opt-in): the catalog stays in the tool list; Ratel surfaces hints about which tools to consider. Useful when you can't change the agent's tool list dynamically.
If you're not sure which one your user wants, default to replace — it's the wedge.
Prerequisites: Rust stable (pinned via rust-toolchain.toml), Node 24+, pnpm 10.28+.
# Rust
cargo build --workspace
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
cargo fmt --check --all
# TS
pnpm install
pnpm -r build
pnpm -r typecheck
pnpm -r lint
pnpm -r testDon't skip clippy or biome — CI runs both and will reject PRs that don't.
- TDD is mandatory. Write the failing test first, then the implementation. See CONTRIBUTING.md.
- ADRs are immutable. If you're tempted to edit an accepted ADR, write a new ADR that supersedes it.
- Folder READMEs are kept current. Every directory under
src/has a README explaining what's in it. If you add or move things, update the README in the same commit. - Commit messages are conventional:
feat:,fix:,refactor:,chore:,docs:,test:. Keep the subject line short; put detail in the body.
For deeper guardrails on agent behavior in this repo (TDD policy, plan-mode default, lessons log), see CLAUDE.md — written for Claude Code specifically but applies to any coding agent operating here.
- For install commands: cross-check this file. If a command isn't here, it doesn't ship yet.
- For positioning: the README's "Choose your path" table and "What Ratel is not" section are authoritative.
- For what's shipped vs planned: don't promise unreleased features as available; the install table above is authoritative for what ships today.
- For locked decisions:
docs/adr/. The ADR is the source of truth, not the README.