Base URL
http://localhost:3333/api/· Authentication · Conventions
Skill Routes
Base path: /api/skills
Manage reusable agent skills — named instruction sets that can be assigned to agents.
Get All Skills
GET /
- Authentication: Required
- Description: Get all skills for the authenticated user
- Response:
{
"skills": [
{
"id": "skill-uuid",
"name": "Code Reviewer",
"description": "Reviews code for quality and security",
"instructions": "When reviewing code...",
"icon": "fas fa-code",
"category": "development",
"allowed_tools": "[\"code-search\",\"file-read\"]",
"license": "",
"compatibility": "",
"metadata": "{\"relations\":{\"depends-on\":[\"hyperframes-core\"]},\"provenance\":{\"source-trace\":\"goal-uuid\",\"rationale\":\"...\"}}",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
]
}Get Skill by ID
GET /:id
- Authentication: Required
- Parameters:
id(path): Skill ID
- Response:
{
"skill": { ... }
}- Error (404): Skill not found
Create Skill
POST /
- Authentication: Required
- Body:
{
"skill": {
"name": "Code Reviewer",
"description": "Reviews code for quality and security",
"instructions": "When reviewing code, focus on...",
"icon": "fas fa-code",
"category": "development",
"allowedTools": ["code-search", "file-read"]
}
}- Response (201):
{
"skill": { ... },
"skillId": "skill-uuid"
}Update Skill
PUT /:id
- Authentication: Required
- Parameters:
id(path): Skill ID
- Body:
{
"skill": {
"name": "Updated Name",
"description": "Updated description",
"instructions": "Updated instructions..."
}
}- Response:
{
"skill": { ... }
}Delete Skill
DELETE /:id
- Authentication: Required
- Parameters:
id(path): Skill ID
- Response:
{
"message": "Skill deleted"
}- Error (404): Skill not found
Export Skill as Markdown
GET /:id/export
- Authentication: Required
- Parameters:
id(path): Skill ID
- Description: Export a skill as a
.SKILL.mdfile with YAML frontmatter and markdown body - Response:
text/markdownfile download
Import Skill from Markdown
POST /import
- Authentication: Required
- Content-Type:
text/plain - Description: Import a skill from SKILL.md content (YAML frontmatter + markdown body)
- Body: Raw text content of a
.SKILL.mdfile
---
name: "My Skill"
description: "Skill description"
category: "general"
icon: "fas fa-puzzle-piece"
allowed-tools:
- code-search
- file-read
---
Instructions for the skill go here...- Response (201):
{
"skill": { ... },
"skillId": "skill-uuid"
}Skill relations and provenance
Skills can declare how they relate to other skills, and where they came from.
Both live inside the spec's free-form metadata map, so no new frontmatter
fields are introduced and skills stay portable to other agentskills.io clients
(which simply ignore metadata).
In a SKILL.md file:
---
name: hyperframes-cli
description: Use the HyperFrames CLI development loop.
metadata:
relations:
depends-on:
- hyperframes-core # activate that skill too
composes-with:
- media-use # complementary, often used together
supersedes:
- old-render-pipeline # prefer this skill over that one
provenance:
source-trace: 9acd74bc-34e5-4f25-bde2-1aef13965318
extracted: "2026-08-03"
rationale: Extracted from the batch-render loop; generalizes to any batch render, fails on multi-repo targets.
confidence: 0.82
---Over the API, metadata is a JSON string on database-backed skills
(/api/skills) and a parsed object on filesystem-discovered skills
(/api/skills/discovered). Consumers should handle both.
Relation types
| Key | Meaning |
|---|---|
depends-on |
This skill requires the target to function. Activating it surfaces a prompt to activate the target as well. |
composes-with |
Complementary skill, frequently useful alongside this one. |
supersedes |
This skill replaces the target. While both are present, the target is omitted from the skill catalog and activating it warns the caller. |
Values are arrays of skill slugs (a bare string is accepted and treated as a
single-element array). Unknown relation types and malformed slugs produce
warnings, never errors — the rest of the skill still loads.
Provenance fields
| Field | Meaning |
|---|---|
source-trace |
Goal or execution ID the skill was extracted from. |
extracted |
YYYY-MM-DD extraction date. |
rationale |
Where the pattern came from, when it generalizes, when it fails. |
confidence |
0.0–1.0 judge confidence at extraction time. |
history |
Appended on each SkillForge refinement: one entry per version, giving the skill a lineage. |
Skills forged automatically by SkillForge populateprovenance from the trace analysis. Refinements append to provenance.history
rather than overwriting the original extraction record.
Effect on the skill catalog
The <available-skills> catalog injected into agent prompts is relation-aware:
- A
depends-onrelation is annotated inline —- hyperframes-cli: … [needs: hyperframes-core]. - A skill is omitted from the catalog when another skill present in the same
catalog declares that itsupersedesit. If the successor is absent the
superseded skill is still listed, so a capability is never orphaned.
Relations and provenance survive a full GET /:id/export → POST /import
round-trip.
SkillForge Routes
Base path: /api/skillforge
SkillForge is the skill evolution subsystem within the unified evolution engine. It analyzes goal execution traces via the TraceAnalyzer, extracts patterns and anti-patterns, evolves skills with improved instructions, and tracks performance over time using a Skill Evolution Score (SES). Runs automatically after goal completion when autoAnalyze is enabled, or can be triggered manually.
Get Eligible Goals
GET /eligible-goals
- Authentication: Required
- Description: List completed goals that are available for skill forging/analysis
- Response:
{
"success": true,
"goals": [
{
"id": "goal-id",
"title": "Goal Title",
"status": "completed",
"completedAt": "2024-01-01T00:00:00Z"
}
]
}Analyze Goal Trace
POST /analyze/:goalId
- Authentication: Required
- Parameters:
goalId(path): Goal ID
- Body (optional):
{
"provider": "anthropic",
"model": "claude-sonnet-4-20250514"
}- Description: Analyze a goal's execution trace using LLM-as-judge to extract patterns, anti-patterns, and a reusable skill candidate. Provider/model override the user's defaults for the LLM analysis call.
- Response:
{
"success": true,
"analysis": {
"patterns": [],
"antipatterns": [],
"insights": [],
"skillCandidate": {}
}
}Evolve Skill
POST /evolve/:goalId
- Authentication: Required
- Parameters:
goalId(path): Goal ID
- Body (optional):
{
"provider": "anthropic",
"model": "claude-sonnet-4-20250514"
}- Description: Full analysis and skill evolution — analyzes the goal trace, creates or updates a skill with merged instructions, and records the evolution with SES tracking. Provider/model are forwarded to trace analysis and skill instruction merging.
- Response:
{
"success": true,
"result": {
"skillId": "skill-id",
"previousVersion": 1,
"newVersion": 2,
"sesDelta": 0.15,
"improvements": []
}
}Get All Evaluations
GET /evaluations
- Authentication: Required
- Parameters:
limit(query, optional): Max results (default: 50)
- Description: List all skill evaluations for the authenticated user
- Response:
{
"success": true,
"evaluations": [
{
"id": "eval-id",
"skillId": "skill-id",
"score": 85,
"sesDelta": 0.12,
"createdAt": "2024-01-01T00:00:00Z"
}
]
}Get Evaluations for Skill
GET /evaluations/:skillId
- Authentication: Required
- Parameters:
skillId(path): Skill ID
- Description: Get all evaluations for a specific skill
- Response:
{
"success": true,
"evaluations": [
{
"id": "eval-id",
"skillId": "skill-id",
"score": 85,
"sesDelta": 0.12,
"version": 2,
"createdAt": "2024-01-01T00:00:00Z"
}
]
}Get Leaderboard
GET /leaderboard
- Authentication: Required
- Parameters:
limit(query, optional): Max results (default: 20)
- Description: Get top skills ranked by average SES delta
- Response:
{
"success": true,
"leaderboard": [
{
"skillId": "skill-id",
"skillName": "Code Reviewer",
"avgSesDelta": 0.25,
"totalEvolutions": 8,
"currentVersion": 5
}
]
}Get Skill Version History
GET /skill/:skillId/versions
- Authentication: Required
- Parameters:
skillId(path): Skill ID
- Description: Get the version history for a skill's evolution
- Response:
{
"success": true,
"versions": [
{
"version": 3,
"sesDelta": 0.15,
"changes": "Improved error handling patterns",
"createdAt": "2024-01-01T00:00:00Z"
}
]
}Get Skill Lineage
GET /skill/:skillId/lineage
- Authentication: Required
- Parameters:
skillId(path): Skill ID
- Description: Get the full evolutionary lineage of a skill — every ancestor, mutation, and stats
- Response:
{
"success": true,
"lineage": [
{
"version": 1,
"parentGoalId": "goal-id",
"sesDelta": 0.0,
"createdAt": "2024-01-01T00:00:00Z"
}
],
"stats": {
"totalEvolutions": 5,
"avgSesDelta": 0.18,
"bestVersion": 4
}
}Get Aggregate Stats
GET /stats
- Authentication: Required
- Description: Get aggregate SkillForge statistics for the user
- Response:
{
"success": true,
"stats": {
"totalSkills": 12,
"totalEvolutions": 45,
"totalEvaluations": 120,
"avgSesDelta": 0.15,
"topSkill": "Code Reviewer"
}
}Get SkillForge Settings
GET /settings
- Authentication: Required
- Description: Get SkillForge configuration settings
- Response:
{
"success": true,
"settings": {
"autoAnalyze": false,
"evaluationThreshold": 0.7,
"maxVersions": 50
}
}Update SkillForge Settings
POST /settings
- Authentication: Required
- Body:
{
"autoAnalyze": true,
"evaluationThreshold": 0.8,
"maxVersions": 100
}- Response:
{
"success": true,
"settings": {
"autoAnalyze": true,
"evaluationThreshold": 0.8,
"maxVersions": 100
}
}Skill Discovery Routes
Base path: /api/skills/discovered
Skill Discovery scans the filesystem for skill definitions (e.g., a user's ~/.claude/skills/ directory or a project-local skills folder) and exposes them as a read-only catalog. Discovered skills are separate from database-backed skills until imported. Use these endpoints to browse filesystem skills and promote them into the user's skill library.
List Discovered Skills
GET /
- Authentication: Required
- Description: Get the catalog of all filesystem-discovered skills (summary only — no instructions body)
- Response:
{
"skills": [
{
"name": "hyperframes-cli",
"description": "Skill description",
"source": "filesystem",
"scope": "user",
"client": "agnt",
"trusted": true,
"metadata": { "relations": { "depends-on": ["hyperframes-core"] } }
}
],
"lastScan": "2024-01-01T00:00:00Z",
"scanLocations": [
{ "path": "/home/user/.agnt/skills", "scope": "user", "client": "agnt", "priority": 8 }
],
"total": 42,
"parseFailures": []
}sourceis always"filesystem"(it distinguishes these entries from database-backed skills). The project-vs-user distinction isscope.metadatais the parsed frontmattermetadatamap, ornull. This is where
relations and provenance live — note that it is a parsed
object here, whereas/api/skillsreturns it as a JSON string.parseFailureslists skills found on disk that could not be loaded — see below.
Parse failures
A SKILL.md that fails to parse is skipped, which used to be invisible: the
skill simply never appeared and nothing said why. Every scan now records its
failures and both list endpoints return them:
{
"parseFailures": [
{
"name": "broken-skill",
"path": "/home/user/.agnt/skills/broken-skill/SKILL.md",
"errors": ["Missing required \"description\" (no ## Description section found)"],
"skipped": true,
"at": "2026-08-04T01:22:33.000Z"
}
]
}skipped: true means the skill was dropped from the catalog entirely; false
means it loaded with degraded metadata. The list is rebuilt on every scan, so a
repaired skill disappears from it on the next rescan.
Name collisions across clients
The same skill name may exist in several client directories (~/.agnt/skills,~/.claude/skills, ~/.agents/skills, …). Discovery keys skills by name and the
highest-priority copy wins — project-level beats ancestor-level beats~/.agnt/skills beats other user-level client dirs. When editing skills on disk,
edit every copy: an unedited higher-priority copy silently shadows the change.
Rescan Skill Locations
POST /rescan
- Authentication: Required
- Body (optional):
{
"projectRoot": "/optional/project/root/path"
}- Description: Trigger a fresh scan of the filesystem skill locations. If
projectRootis provided, also scan that project for local skills. - Response: same entry shape as
GET /, includingparseFailures
{
"skills": [],
"lastScan": "2024-01-01T00:00:00Z",
"total": 42,
"parseFailures": []
}Get Discovered Skill
GET /:name
- Authentication: Required
- Parameters:
name(path): Skill name (kebab-case, matches directory name)
- Description: Get the full content (metadata + instructions + frontmatter) of a discovered skill
- Response:
{
"skill": {
"name": "skill-name",
"description": "Skill description",
"instructions": "Full skill instructions markdown...",
"frontmatter": {
"name": "skill-name",
"license": "MIT",
"compatibility": "...",
"metadata": { "relations": {}, "provenance": {} },
"allowed-tools": []
},
"dirPath": "/path/to/skill/dir",
"skillMdPath": "/path/to/skill/dir/SKILL.md",
"scope": "user",
"client": "agnt",
"priority": 8,
"trusted": true,
"validName": true,
"discoveredAt": "2024-01-01T00:00:00Z"
}
}frontmatter.metadata carries relations and provenance.
Encoding note.
SKILL.mdfiles are parsed as UTF-8 and a leading byte
order mark is stripped before parsing. A BOM used to defeat the frontmatter
delimiter, which made a valid skill fail with a misleading "missing
description" error.
List Skill Resources
GET /:name/resources
- Authentication: Required
- Parameters:
name(path): Skill name
- Description: List bundled resource files (non-instruction files) shipped with a skill, e.g. templates, scripts, example data
- Response:
{
"resources": [
{ "path": "templates/prompt.md", "size": 1234, "type": "file" }
]
}Read Skill Resource
GET /:name/resources/*
- Authentication: Required
- Parameters:
name(path): Skill name*(wildcard path): Relative path to the resource file within the skill directory
- Description: Read the raw content of a bundled resource file. Paths are validated to prevent escaping the skill directory.
- Response:
text/plain; charset=utf-8with the file contents - Errors:
400if the resource path is missing403if the path escapes the skill directory404if the resource is not found
Import Discovered Skill
POST /:name/import
- Authentication: Required
- Parameters:
name(path): Skill name (kebab-case)
- Description: Import a filesystem-discovered skill into the user's database-backed skill library. The kebab-case name is converted to Title Case for display; the original slug is preserved for lookups. Frontmatter fields (license, compatibility, metadata, allowed-tools) are copied into the skill record.
- Response:
201 Created
{
"skill": {
"id": "new-skill-id",
"name": "Skill Name",
"slug": "skill-name",
"description": "...",
"instructions": "..."
},
"skillId": "new-skill-id",
"importedFrom": "/path/to/source/skill/dir"
}