5.9 KiB
Skill Registry
The Skill Registry provides persistent storage for skill definitions in
CleverAgents. Skills are namespaced, reusable collections of tools
registered via YAML config and persisted to the skills and
skill_items database tables.
Registration Behavior
Skills are registered with a namespaced name (namespace/short_name)
as the unique identifier. The registry enforces:
- Name uniqueness: Duplicate names are rejected with
DuplicateSkillError. - Name validation: Names must match
^[a-zA-Z0-9_-]+/[a-zA-Z0-9_-]+$. - Cascading deletes: Removing a skill cascades to all child
skill_itemsrows.
Skill Items
Each skill stores its components as ordered items in the skill_items
table. The item_type discriminator distinguishes:
| item_type | Description |
|---|---|
tool_ref |
Reference to a named tool in the registry |
include |
Recursive inclusion of another skill |
inline_tool |
Anonymous tool defined inline |
mcp_source |
MCP server tool source |
agent_source |
Agent Skills Standard folder source |
Items are stored with a stable item_order to preserve definition
ordering across round-trips.
Filters
The SkillRegistryService.list_skills() method supports:
- Namespace filter: Pass
namespace="local"to list only skills in thelocalnamespace.
Service API
from cleveragents.application.services import SkillRegistryService
from cleveragents.infrastructure.database.repositories import SkillRepository
svc = SkillRegistryService(skill_repo=SkillRepository(session_factory))
# Register
svc.add_skill(skill)
# Retrieve
skill = svc.get_skill("local/code-tools")
# List with filter
skills = svc.list_skills(namespace="local")
# Update
svc.update_skill(updated_skill)
# Remove
svc.remove_skill("local/code-tools")
Database Schema
skills
| Column | Type | Description |
|---|---|---|
| name | String(255) | PK, namespaced name |
| namespace | String(100) | Extracted namespace |
| short_name | String(150) | Extracted short name |
| description | Text | Skill description |
| version | String(50) | Optional version string |
| metadata_json | Text | JSON metadata (overrides, etc.) |
| created_at | String(30) | ISO-8601 creation timestamp |
| updated_at | String(30) | ISO-8601 update timestamp |
skill_items
| Column | Type | Description |
|---|---|---|
| id | Integer | Auto-increment PK |
| skill_name | String(255) | FK to skills.name (CASCADE) |
| item_type | String(30) | Discriminator (tool_ref, etc.) |
| item_name | String(500) | Item identifier or name |
| item_config | Text | Optional JSON configuration |
| item_order | Integer | Stable ordering index |
| created_at | String(30) | ISO-8601 creation timestamp |
Testing
Behave BDD Tests
The Behave feature file features/skill_registry.feature contains 23
scenarios covering the full SkillRegistryService and SkillRepository
persistence layer:
| Area | Scenarios | Description |
|---|---|---|
| Registration | 6 | Each skill item type (tool_ref, include, inline_tool, mcp_source, agent_source) plus basic round-trip |
| Duplicate rejection | 1 | DuplicateSkillError on name collision |
| Retrieval | 2 | Get by name, non-existent returns None |
| Listing | 2 | List all, list with namespace filter |
| Update | 2 | Description change, non-existent raises SkillNotFoundError |
| Deletion | 2 | Remove existing (cascades items), remove non-existent returns False |
| Overrides | 1 | Override metadata survives persistence round-trip |
| Item ordering | 1 | Mixed item types maintain stable order across round-trip |
| Name validation | 3 | Empty name, no-slash name, special characters rejected at persistence layer |
| Large payload | 1 | 50 tool refs persist correctly |
| Domain objects | 1 | Listed skills are Skill domain instances |
Step definitions: features/steps/skill_registry_steps.py
Session management note: Each scenario creates a fresh in-memory
SQLite database with a single shared Session that is reused across all
repository calls within the scenario. This mirrors the production
UnitOfWork pattern (ADR-019) and avoids transaction-scoping issues
inherent to multiple ephemeral sessions on a single StaticPool
connection.
Run the Behave suite via:
nox -s unit_tests -- features/skill_registry.feature
Robot Smoke Tests
A Robot Framework smoke suite validates core registry operations:
robot/skill_registry.robot
robot/helper_skill_registry.py
| Test Case | What it validates |
|---|---|
| Register And Retrieve A Skill | Round-trip: register then get by name |
| List Skills With Namespace Filter | Register multiple skills, filter by namespace |
| Update A Skill | Change description after registration |
| Reject Duplicate Skill Name | Duplicate name produces error |
| Remove A Skill | Remove and verify absence |
nox -s integration_tests -- robot/skill_registry.robot
ASV Benchmarks
Performance benchmarks live in benchmarks/skill_registry_bench.py:
SkillModelConstruction--time_from_domain(domain-to-ORM mapping)SkillModelReconstruction--time_to_domain(ORM-to-domain mapping)SkillRepositoryCRUD--time_create_skill,time_get_skill,time_list_all,time_list_namespaceSkillRegistryListPerformance--time_list_100_skills,time_list_100_skills_filtered
nox -s benchmark