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:

Column Type Description
category text The integration or functional grouping (e.g., quickbooks, sage-intacct, web, platform).
skill_name text The skill identifier in kebab-case (e.g., profit-and-loss-report, query-customer).
version text The 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:

Column Type Description
id uuid Auto-generated primary key.
category text Skill category / integration name.
skill_name text Kebab-case skill identifier.
version text Skill version string.
display_name text Human-readable skill name shown in the UI.
description text A description of what the skill does.
parameters_schema jsonb JSON Schema defining the skill’s input parameters.
output_schema jsonb JSON Schema describing the skill’s output structure.
required_scopes text[] API key scopes required to execute this skill.
is_active boolean Whether the skill is currently available for execution.
created_at timestamptz When the skill was registered.
updated_at timestamptz When 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
categorystringFilter 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 requiredstringThe skill category (e.g., 'quickbooks').
version requiredstringThe skill version (e.g., 'v1.0').
skillName requiredstringThe 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.


Status Error Description
401 authentication_required Missing or invalid API key.
403 insufficient_scope API key lacks the required scope.
404 skill_not_found No active skill matches the specified category, version, and name.
400 validation_error Invalid query parameter values.
429 rate_limit_exceeded API key rate limit exceeded.