Add a registry of hundreds of skills selected by semantic search
Here we expose a folder of agent skills to an agent through semantic search. Instead of listing every skill in the prompt, the agent searches a duckdb-vectors index and selects the few skills relevant to the task — scaling to hundreds of skills without inflating context.
Why search skills instead of listing them
Listing hundreds of skills in every prompt is costly and dilutes the model's attention. A better pattern: index each skill's name and description once, and at task time retrieve the handful that match the user's intent. The agent then sees only relevant skills. This is tool-selection by semantic search, and it is exactly the small-corpus, fast-retrieval case duckdb-vectors targets.
Step 1 — gather the skills
Assume a folder where each skill has a markdown description (a SKILL.md or similar) with a name and a short summary of what it does and when to use it:
skills/
web-search/SKILL.md
sql-query/SKILL.md
send-email/SKILL.mdIf your skills are defined in code or YAML, generate one short markdown description per skill first — the richer the "what it does / when to use it" text, the better the semantic match.
Step 2 — index skill descriptions
Index the skills folder. Each skill becomes searchable by meaning; the skill id lives in the chunk source and metadata:
from duckdb_vectors import VectorStore
SKILLS = [
("skill:web-search", "Search the public web and return ranked results."),
("skill:sql-query", "Run read-only SQL queries against a warehouse."),
("skill:send-email", "Compose and send an email to a recipient."),
]
store = VectorStore(db_path="skills.duckdb", backend="fastembed:minishlab/potion-multilingual-128M")
store.add_texts(
ids=[sid for sid, _ in SKILLS],
texts=[desc for _, desc in SKILLS],
metadatas=[{"kind": "skill"} for _ in SKILLS],
)
store.close()A folder of SKILL.md files can be indexed the same way with index_folder(store, "skills", recursive=True).
Step 3 — expose a selection tool
Wrap retrieval as a function the agent can call to find relevant skills:
store = VectorStore(db_path="skills.duckdb", backend="fastembed:minishlab/potion-multilingual-128M", read_only=True)
def find_skills(task: str, k: int = 3) -> list[str]:
"""Return the ids of the skills most relevant to a task."""
return [hit.chunk.chunk_id for hit in store.query(task, top_k=k)]find_skills("I need to look something up online")
# ["skill:web-search", ...]Step 4 — wire the tool into the agent
Register find_skills as a tool in your harness. The agent calls it with the user's task, gets back a short list of candidate skill ids, loads only those skill definitions, and proceeds. The prompt never carries the full catalog — only the selected skills.
This keeps context small and selection fast: a few hundred skills still answer in tens of milliseconds, and adding skills does not grow the prompt.
Step 5 — runtime append for dynamic skills
If the skill set is assembled at harness startup (plugins, per-tenant skills), open the store read-write at init and append them before serving — the runtime-append lifecycle:
store = VectorStore(db_path="skills.duckdb", backend="fastembed:minishlab/potion-multilingual-128M")
store.add_texts(ids=[...], texts=[...], metadatas=[...])
# then switch to read-only queries for the rest of the sessionKeep writes to one process — a DuckDB file is single-writer. For a fixed skill set, prefer indexing once at build time and opening read-only.