Ratel Docs
TypeScript SDK

Quickstart

Install @ratel-ai/sdk, create the ratel() core, register your tools and prompt playbooks, and hand any agent loop the three capability tools.

This is the TypeScript path. Python reader? Start at the Python quickstart. Rather not write the integration yourself? Point your coding agent at the skills suite.

Ratel is framework-agnostic: everything the SDK hands you is a plain executable tool (metadata plus an execute handler) that plugs into any agent loop. This page shows the two ways in: starting from scratch and migrating an existing agent.

Before you start

Use Node.js 20 or newer. Nothing on this page calls a model, so no API key is needed.

How it works

Everything starts with ratel(): one core holding a tool catalog and a skill catalog. Register each of your tools once on r.tools, pairing its metadata (id, description, JSON schemas) with the handler that runs it; register Markdown playbooks on r.skills, ranked in their own corpus.

The agent reaches both through the three capability tools from r.modelTools(): search_capabilities (find tools and skills by description), invoke_tool (run a tool by id), and get_skill_content (load a skill's body), so the full catalog never enters the prompt. How the pieces fit per turn is covered in Architecture.

Start from scratch

Create a project and install the SDK

mkdir ratel-quickstart && cd ratel-quickstart
npm init -y
npm pkg set type=module
npm install @ratel-ai/sdk
npm install --save-dev tsx

Requirements, prebuilt targets, and optional packages are on Install.

Register a tool and a skill

Create index.ts. Tools carry their metadata and handler; skills carry a description and a Markdown body:

import { ratel } from "@ratel-ai/sdk";

const r = ratel();

await r.tools.register({
  id: "get_weather",
  name: "get_weather",
  description: "Get the current weather for a city.",
  inputSchema: {
    type: "object",
    properties: {
      city: { type: "string", description: "City name" },
    },
    required: ["city"],
  },
  outputSchema: {
    type: "object",
    properties: {
      city: { type: "string" },
      temperatureC: { type: "number" },
      condition: { type: "string" },
    },
    required: ["city", "temperatureC", "condition"],
  },
  execute: async ({ city }) => ({
    city,
    temperatureC: 24,
    condition: "sunny",
  }),
});

await r.skills.register({
  id: "weather-briefing",
  name: "weather-briefing",
  description: "How to report the weather: temperature first, then condition.",
  body: "## Weather briefing\nAnswer in one sentence: temperature first, then the condition. No filler.",
});

// The three capability tools are the only tools your agent needs to see.
// Always all three — the set never depends on registration order.
const { search_capabilities, invoke_tool, get_skill_content } = r.modelTools();

Run the discovery loop by hand

Append the exact calls a model makes at runtime, then run the file:

console.log(await search_capabilities.execute({ query: "weather in Rome" }));
console.log(await invoke_tool.execute({ toolId: "get_weather", args: { city: "Rome" } }));
console.log(await get_skill_content.execute({ skillId: "weather-briefing" }));
npx tsx index.ts

Three results, no model key involved:

  • search_capabilities returns two independently-ranked buckets: get_weather under tools, weather-briefing under skills. Neither schema nor body entered any prompt to get there.
  • invoke_tool runs the handler and returns its result untouched: { city: "Rome", temperatureC: 24, condition: "sunny" }.
  • get_skill_content returns the playbook: { body: "## Weather briefing\n…" }.

The full result shapes and error contract are on Progressive disclosure tools.

Hand the loop to your agent

Using the Vercel AI SDK or Mastra? r.adaptTo(...) gives the same core a framework-shaped view through an official adapter — see Framework integrations.

Anywhere else, each capability tool is a plain ExecutableTool: { id, name, description, inputSchema, outputSchema, execute }. Map those fields onto your framework's tool type (a few lines), add the three tools to the agent's tool list, and tell it to search before answering:

Find tools and playbooks with search_capabilities. Run tools with invoke_tool.
When a skill matches, load it with get_skill_content and follow it.

Host-driven ranking is there too: await r.recall(query) returns the canonical search_capabilities result (or null on no match) without going through the model. More on Use the discovery tools.

Migrate an existing agent

A migration changes where capabilities live, not your model or business logic. Start with one workflow, prove it still behaves the same, then repeat.

Existing assetAfter migration
Tool IDs, schemas, and handlersRegister once on r.tools; keep authorization and side effects in the handler.
Conditional runbooks and examplesRegister on r.skills; load only when relevant.
Identity, safety, universal policy, output rules, and runtime contextKeep in the core prompt.
Model and agent loopKeep both; reuse the loop's prompt and tool seams.

Find the integration points

Find where your process creates long-lived dependencies and where each request builds the model's tool list. Create the ratel() core at startup; change the model-facing list at the request boundary.

Register an existing tool

Tool definitions leave the repeated model request, not your code. Preserve the ID, schema contract, handler, authorization, permissions, and side effects. Convert framework-native schemas to JSON Schema at this boundary.

// Before: the schema is sent to the model on every request
const toolsForEveryRequest = { issue_refund: existingRefundTool };

// After: the same contract is registered once at startup
const r = ratel();
await r.tools.register({
  id: "issue_refund",
  name: "issue_refund",
  description: "Issue an approved refund for an order.",
  inputSchema: issueRefundInputSchema,
  outputSchema: issueRefundOutputSchema,
  execute: issueRefund, // the existing handler
});

Register each tool in this workflow the same way — r.tools.register is variadic, so a batch is one call. During a gradual migration, leave unmigrated tools in the old list and remove each migrated definition from it.

Extract an on-demand skill

Keep instructions and runtime context that must govern every turn in the core prompt. Move only conditional guidance, such as the refund workflow, into a self-contained skill:

// Before: the refund workflow is sent on every turn
const instructions = [
  CORE_PROMPT,
  SAFETY_POLICY,
  OUTPUT_RULES,
  RUNTIME_CONTEXT,
  REFUND_RUNBOOK,
].join("\n\n");

// After: everything except the runbook stays in the core prompt
const coreInstructions = [
  CORE_PROMPT,
  SAFETY_POLICY,
  OUTPUT_RULES,
  RUNTIME_CONTEXT,
].join("\n\n");

await r.skills.register({
  id: "refund-runbook",
  name: "refund-runbook",
  description: "Check refund eligibility, obtain approval, then issue the refund.",
  tools: ["issue_refund"],
  body: REFUND_RUNBOOK,
});

The description says when to load the skill. Its tools list surfaces issue_refund beside the matched playbook.

Rewire and verify the agent

Add the discovery policy to the core prompt, then hand the agent the capability tools at the request boundary:

const discoveryInstructions = `
Find tools and playbooks with search_capabilities. Run tools with invoke_tool.
When a skill matches, load it with get_skill_content and follow it.
`.trim();

const instructions = [coreInstructions, discoveryInstructions].join("\n\n");
const capabilityTools = r.modelTools();

The capability tools are plain ExecutableTool values; Framework integrations has the official adapters and the hand-rolled recipe.

A refund request should now follow this path:

  1. search_capabilities returns refund-runbook and issue_refund.
  2. get_skill_content loads the eligibility and approval steps.
  3. invoke_tool calls the unchanged issueRefund handler.
  4. The agent answers from the tool result.

Before migrating the next workflow, verify the skill ranks, its declared tool appears, the handler receives the same arguments, and the initial request excludes the full catalog and refund runbook.

Let a coding agent do the migration

The skills suite ships skills for Claude Code, Cursor, Codex, and similar: ratel-integrate plans this migration for your codebase, and ratel-decompose-prompt splits the system prompt into skills.

Next steps

On this page