Ratel Docs
Python SDK

Register skills

Register Markdown playbooks in a SkillCatalog and surface them through search_capabilities alongside tools.

Skills are Markdown playbooks (a deploy runbook, a debugging checklist) ranked by a separate BM25 corpus from tools. What a skill is and when to reach for one is on Tools vs MCP vs skills; Ratel's own coding-agent skills — including ratel-decompose-prompt, which extracts skills from a long system prompt — are on the Quick start.

Register a skill

from ratel_ai import Skill, SkillCatalog, get_skill_content_tool, search_capabilities_tool

skills = SkillCatalog()
skills.register(
    Skill(
        id="vercel-deploy",
        name="vercel-deploy",
        description="How to deploy to Vercel: env vars, preview vs production, rollbacks.",
        tags=["deploy", "ship to production"],      # indexed for ranking
        tools=["vercel__deploy", "fs__read_file"],  # surfaced alongside the skill when it matches
        metadata={"stacks": ["next", "vercel"]},    # non-indexed context for higher-layer ranking
        body="## Deploying to Vercel\n1. ...",       # returned by get_skill_content_tool
    )
)

search = search_capabilities_tool(catalog, skills)  # 2nd arg → result gains a populated `skills` bucket
load = get_skill_content_tool(skills)               # id == "get_skill_content"

Only id, name, and description are required; tags, tools, metadata, and body are optional. get_skill_content({skillId}) returns {"body": ...}, or {"error": ..., "isError": True} for an unknown id.

How skills surface

Pass a SkillCatalog as the second argument to search_capabilities_tool and search returns the skills bucket alongside tools, each with its own result budget, so a relevant skill is never starved by matching tools. The agent pulls a skill's full body into context on demand via get_skill_content_tool (id get_skill_content, constant GET_SKILL_CONTENT_ID).

A skill can also declare the tools its instructions call: when the skill matches a query, those tools are pulled into the tools bucket (additively, deduped) so the agent gets the playbook and the tools it needs in one turn instead of a second search.

The SkillCatalog surface

SkillCatalog(trace=None, method="bm25") takes the same constructor keywords as ToolCatalog, and its method surface mirrors it over the skill corpus:

skills.search(query, top_k)   # → list[SkillHit]  (.skill_id, .score); origin=, method= as on ToolCatalog
skills.has(skill_id)          # → bool
skills.get(skill_id)          # → Skill | None
skills.size()                 # → int
skills.invoke(skill_id)       # → str: the body; raises ValueError on an unknown id

build_embeddings(), record_event(), and drain_trace_events() work exactly as on ToolCatalog. Note that invoke is synchronous here, no await: loading a skill body is a lookup, not an executor call. It records a skill_invoke trace event.

Embeddings for skills

The skill corpus has its own embedding cache, maintained exactly like the tool one (Build the embedding cache): construct SkillCatalog with method="semantic" or "hybrid" to embed eagerly at register, or keep the BM25 default and call skills.build_embeddings() before opting in per call. The two caches are independent — skills can rank hybrid while tools stay on BM25.

Embeddings cover the same projection the ranking indexes — name, description, tags — never the body, so a long playbook costs one small embedding. When the engines are worth it is on Semantic & hybrid search.

Next steps

On this page