Skip to content

Skill Registry

The Skill Registry is the central catalog of all skills available in a Horizon deployment. Every skill that an agent can execute is registered here with its metadata, parameter schema, category, and version. The registry API provides read-only access for discovering skills programmatically.


Skills in Horizon are stored in a skills table in Supabase. Each skill is uniquely identified by a composite key of three fields:

ColumnTypeDescription
categorytextThe integration or functional grouping (e.g., quickbooks, sage-intacct, web, platform).
skill_nametextThe skill identifier in kebab-case (e.g., profit-and-loss-report, query-customer).
versiontextThe version string (e.g., v1.0, v2.0).

A composite unique constraint on (category, skill_name, version) ensures that no two skills share the same combination. This allows multiple versions of the same skill to coexist, enabling gradual migration without breaking existing integrations.

The full skills table includes these columns:

ColumnTypeDescription
iduuidAuto-generated primary key.
categorytextSkill category / integration name.
skill_nametextKebab-case skill identifier.
versiontextSkill version string.
display_nametextHuman-readable skill name shown in the UI.
descriptiontextA description of what the skill does.
parameters_schemajsonbJSON Schema defining the skill’s input parameters.
output_schemajsonbJSON Schema describing the skill’s output structure.
required_scopestext[]API key scopes required to execute this skill.
is_activebooleanWhether the skill is currently available for execution.
created_attimestamptzWhen the skill was registered.
updated_attimestamptzWhen the skill metadata was last modified.

When an agent executes a skill via POST /api/{category}/{version}/{skill-name}, the Express backend resolves the skill by looking up the (category, skill_name, version) tuple in the registry. If no matching active skill is found, the API returns a 404 skill_not_found error.

The registry endpoints described below let you discover what skills are available before attempting to execute them.


GET /api/skills

List all active skills in the registry, optionally filtered by category.

Requires authentication via x-api-key header.

Query Parameters

ParameterTypeDescription
category string Filter skills by category (e.g., 'quickbooks', 'web'). Returns all categories if omitted.
curl
curl -X GET "https://api.horizonplatform.ai/api/skills?category=quickbooks" \
-H "x-api-key: hz_live_abc123def456"
JavaScript
const params = new URLSearchParams({ category: 'quickbooks' });
const response = await fetch(
`https://api.horizonplatform.ai/api/skills?${params}`,
{ headers: { 'x-api-key': 'hz_live_abc123def456' } }
);
const skills = await response.json();
console.log(`Found ${skills.length} skills`);
Python
import requests
response = requests.get(
'https://api.horizonplatform.ai/api/skills',
headers={'x-api-key': 'hz_live_abc123def456'},
params={'category': 'quickbooks'}
)
skills = response.json()
print(f"Found {len(skills)} skills")
// 200 OK
[
{
"id": "sk_001",
"category": "quickbooks",
"skill_name": "profit-and-loss-report",
"version": "v1.0",
"display_name": "Profit & Loss Report",
"description": "Generate a Profit & Loss report from QuickBooks Online for a specified date range and accounting method.",
"required_scopes": ["quickbooks"],
"is_active": true,
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-03-01T08:30:00Z"
},
{
"id": "sk_002",
"category": "quickbooks",
"skill_name": "query-customer",
"version": "v1.0",
"display_name": "Query Customer",
"description": "Look up customer details in QuickBooks Online by name, email, or ID.",
"required_scopes": ["quickbooks"],
"is_active": true,
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-02-20T14:15:00Z"
},
{
"id": "sk_003",
"category": "quickbooks",
"skill_name": "balance-sheet",
"version": "v1.0",
"display_name": "Balance Sheet",
"description": "Generate a Balance Sheet report from QuickBooks Online as of a specified date.",
"required_scopes": ["quickbooks"],
"is_active": true,
"created_at": "2026-02-01T09:00:00Z",
"updated_at": "2026-02-01T09:00:00Z"
}
]

To discover all available categories, call the list endpoint without a category filter:

curl
curl -X GET https://api.horizonplatform.ai/api/skills \
-H "x-api-key: hz_live_abc123def456"

The response includes skills from all categories. You can extract unique categories client-side, or use the response to build a skill browser in your application.


GET /api/skills/:category/:version/:skillName

Retrieve full metadata for a specific skill, including its parameter schema and output schema.

Requires authentication via x-api-key header.

Path Parameters

ParameterTypeDescription
category required string The skill category (e.g., 'quickbooks').
version required string The skill version (e.g., 'v1.0').
skillName required string The skill name in kebab-case (e.g., 'profit-and-loss-report').
curl
curl -X GET https://api.horizonplatform.ai/api/skills/quickbooks/v1.0/profit-and-loss-report \
-H "x-api-key: hz_live_abc123def456"
JavaScript
const response = await fetch(
'https://api.horizonplatform.ai/api/skills/quickbooks/v1.0/profit-and-loss-report',
{ headers: { 'x-api-key': 'hz_live_abc123def456' } }
);
const skill = await response.json();
console.log(skill.display_name);
console.log(JSON.stringify(skill.parameters_schema, null, 2));
Python
import requests
import json
response = requests.get(
'https://api.horizonplatform.ai/api/skills/quickbooks/v1.0/profit-and-loss-report',
headers={'x-api-key': 'hz_live_abc123def456'}
)
skill = response.json()
print(skill['display_name'])
print(json.dumps(skill['parameters_schema'], indent=2))
// 200 OK
{
"id": "sk_001",
"category": "quickbooks",
"skill_name": "profit-and-loss-report",
"version": "v1.0",
"display_name": "Profit & Loss Report",
"description": "Generate a Profit & Loss report from QuickBooks Online for a specified date range and accounting method.",
"parameters_schema": {
"type": "object",
"properties": {
"start_date": {
"type": "string",
"format": "date",
"description": "Start date for the report period (YYYY-MM-DD)."
},
"end_date": {
"type": "string",
"format": "date",
"description": "End date for the report period (YYYY-MM-DD)."
},
"accounting_method": {
"type": "string",
"enum": ["Accrual", "Cash"],
"description": "The accounting method for the report."
}
},
"required": ["start_date", "end_date"]
},
"output_schema": {
"type": "object",
"properties": {
"report_title": { "type": "string" },
"total_income": { "type": "number" },
"total_expenses": { "type": "number" },
"net_income": { "type": "number" },
"line_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"account": { "type": "string" },
"amount": { "type": "number" }
}
}
}
}
},
"required_scopes": ["quickbooks"],
"is_active": true,
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-03-01T08:30:00Z"
}

The parameters_schema field is a standard JSON Schema object that describes the input your request body must conform to when executing this skill. Use it to build dynamic forms, validate input client-side, or generate documentation automatically.


Using the Registry for Dynamic Skill Execution

Section titled “Using the Registry for Dynamic Skill Execution”

A common pattern is to query the registry at runtime to build a dynamic skill execution layer. For example:

JavaScript
// 1. Discover available skills in a category
const skills = await fetch(
'https://api.horizonplatform.ai/api/skills?category=quickbooks',
{ headers: { 'x-api-key': apiKey } }
).then(r => r.json());
// 2. Get the full schema for the skill you want to execute
const skill = await fetch(
`https://api.horizonplatform.ai/api/skills/${skills[0].category}/${skills[0].version}/${skills[0].skill_name}`,
{ headers: { 'x-api-key': apiKey } }
).then(r => r.json());
// 3. Validate input against the parameter schema (using ajv or similar)
// 4. Execute the skill
const result = await fetch(
`https://api.horizonplatform.ai/api/${skill.category}/${skill.version}/${skill.skill_name}`,
{
method: 'POST',
headers: {
'x-api-key': apiKey,
'Content-Type': 'application/json',
},
body: JSON.stringify(inputData),
}
).then(r => r.json());

This approach decouples your application from hard-coded skill paths and allows it to adapt automatically as new skills are added to the registry.


Horizon follows a straightforward versioning model for skills:

  • Patch updates (bug fixes, minor output changes) are applied in-place to the existing version.
  • Breaking changes (new required parameters, changed output structure) result in a new version (e.g., v1.0 to v2.0).
  • Old versions remain active until explicitly deprecated, so existing integrations continue to work.

When a new version of a skill is published, both versions coexist in the registry. Clients can query both and migrate at their own pace.


StatusErrorDescription
401authentication_requiredMissing or invalid API key.
403insufficient_scopeAPI key lacks the required scope.
404skill_not_foundNo active skill matches the specified category, version, and name.
400validation_errorInvalid query parameter values.
429rate_limit_exceededAPI key rate limit exceeded.