Skills API
The Skills Agent provides a unified tool/skill management interface, integrating built-in tools, custom tools (data/skills), and MCP server tools.
All routes are mounted under the /api/skills prefix.
Response Format Convention
Except for SSE endpoints, all endpoints return the unified ChaiteResponse envelope:
{
"code": 0,
"data": {},
"message": "ok"
}code:0means success, non-zero means failure (defaults to-1on failure).data: business payload; usuallynullon failure.message: hint text;okon success, error description on failure.
The "Response" examples below only show the inner structure of the data field.
SSE Real-time Status
GET /api/skills/sseEstablishes a text/event-stream long-lived connection that pushes skill and server status changes in real time. A connected event is pushed immediately after the connection is established, followed by a heartbeat every 30 seconds.
const es = new EventSource('/api/skills/sse')
es.addEventListener('connected', (e) => console.log('Connected', JSON.parse(e.data)))
es.addEventListener('tool-executed', (e) => console.log(JSON.parse(e.data)))Event types:
| Event | Trigger | data fields |
|---|---|---|
connected | Connection established | { time } |
heartbeat | Every 30 seconds | { time } |
tool-executed | A single skill execution completed | { toolName, success, timestamp } |
batch-executed | Batch execution completed | { count, timestamp } |
category-toggled | A category's enabled state toggled | { category, enabled, timestamp } |
tool-toggled | A tool's enabled state toggled | { tool, enabled, timestamp } |
tools-reloaded | All tools reloaded | { ...result, timestamp } |
tools-enabled-all | All tools enabled | { ...result, timestamp } |
tools-disabled-all | All tools disabled | { ...result, timestamp } |
server-connecting / server-connected / server-error | Adding an MCP server | { name, ... , timestamp } |
server-removed | Removing an MCP server | { name, timestamp } |
server-reconnecting / server-reconnected | Reconnecting an MCP server | { name, timestamp } |
skill-loaded / skill-unloaded | Skill loaded/unloaded | { name, timestamp } |
Get Overall Status
GET /api/skills/statusReturns aggregated server, statistics, and category status.
Response (data)
{
"servers": [
{
"name": "server-name",
"status": "connected",
"type": "stdio",
"toolsCount": 5,
"connectedAt": 1720000000000
}
],
"stats": {},
"categories": [
{
"key": "basic",
"name": "Basic",
"toolCount": 9,
"enabled": true
}
],
"timestamp": 1720000000000
}Get All Skills
GET /api/skills/toolsQuery Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
includeBuiltin | string | true | Whether to include built-in tools ('true' takes effect) |
includeMcp | string | true | Whether to include MCP tools ('true' takes effect) |
presetId | string | default | Preset ID |
Response (data)
{
"count": 80,
"tools": []
}Get Skills Grouped by Source
GET /api/skills/tools/by-sourceGroups skills by builtin / custom / mcp (MCP tools grouped by server name).
Response (data)
{
"builtin": {
"count": 9,
"tools": [{ "name": "execute_command", "description": "Execute command" }]
},
"custom": {
"count": 2,
"tools": [{ "name": "my_tool", "description": "Custom tool" }]
},
"mcp": {
"server-name": {
"count": 5,
"tools": [{ "name": "mcp_tool", "description": "MCP tool" }]
}
}
}Get Document Skills
GET /api/skills/documentsReturns document-style skills such as SKILL.md scanned from the data/skills directory.
Response (data)
{
"count": 3,
"documents": [
{
"name": "my-skill",
"description": "Skill description",
"triggers": ["trigger 1"],
"allowedTools": ["tool1"],
"disallowedTools": [],
"path": "my-skill/SKILL.md",
"directory": "my-skill"
}
]
}Execute a Skill
POST /api/skills/executeRequest Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
toolName | string | Yes | - | Name of the tool/skill to execute |
args | object | No | {} | Execution arguments |
presetId | string | No | default | Preset ID |
Returns 400 when toolName is missing. Broadcasts a tool-executed event after execution completes.
Response (data)
Returns the execution result object with an isError field indicating whether an error occurred.
{
"content": [],
"isError": false
}Search Skills
GET /api/skills/searchQuery Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
q | string | '' | Search keyword |
limit | string | 20 | Maximum number of results |
category | string | - | Filter by category |
source | string | - | Filter by source |
Response (data)
{
"query": "keyword",
"count": 5,
"results": []
}Get Discovery Summary
GET /api/skills/discoverReturns a per-category statistics summary and the total number of skills.
Response (data)
{
"total": 80,
"categories": {}
}Get Skill Details
GET /api/skills/tools/:name/detailPath Parameters
name- Skill name
Returns 404 when the skill does not exist, with message set to Skill {name} does not exist.
Response (data)
Returns the skill's detail object.
Recommend Skills
POST /api/skills/recommendRecommends relevant skills based on context text.
Request Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
context | string | Yes | - | Context text |
limit | number | No | 5 | Maximum number of recommendations |
Returns 400 when context is missing.
Response (data)
{
"context": "context text",
"count": 3,
"recommendations": []
}Execute Skills in Batch
POST /api/skills/execute/batchRequest Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
calls | array | Yes | [] | List of execution calls; must be a non-empty array |
presetId | string | No | default | Preset ID |
Returns 400 when calls is not an array or is empty. Broadcasts a batch-executed event after execution completes.
Response (data)
{
"count": 2,
"results": []
}Get Tool Categories
GET /api/skills/categoriesResponse (data)
Returns the category array (raw structure from getToolCategories()).
[
{
"key": "basic",
"name": "Basic",
"toolCount": 9,
"enabled": true
}
]Toggle a Category's Enabled State
POST /api/skills/categories/:key/togglePath Parameters
key- Category key
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
enabled | boolean | Yes | Whether to enable; non-boolean values return 400 |
Broadcasts a category-toggled event after toggling.
Toggle a Single Tool's Enabled State
POST /api/skills/tools/:name/togglePath Parameters
name- Tool name
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
enabled | boolean | Yes | Whether to enable; non-boolean values return 400 |
Broadcasts a tool-toggled event after toggling.
Reload All Tools
POST /api/skills/reloadBroadcasts a tools-reloaded event after the reload completes.
Enable All / Disable All
POST /api/skills/enable-all
POST /api/skills/disable-allBroadcasts tools-enabled-all / tools-disabled-all respectively.
Get Tool Statistics
GET /api/skills/statsResponse (data)
Returns the getToolStats() structure.
{
"totalTools": 80,
"enabledTools": 65,
"categories": 22,
"mcpServers": 2
}MCP Server Management
Get Server List
GET /api/skills/mcp/serversResponse (data): array of servers.
Get a Single Server's Details
GET /api/skills/mcp/servers/:nameReturns 404 when the server does not exist, with message set to Server not found.
Add a Server
POST /api/skills/mcp/serversRequest Body
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Server name; returns 400 when missing |
config | object | No | Server connection configuration |
Broadcasts server-connecting during connection, then server-connected on success or server-error on failure. Returns 201 on success.
Remove a Server
DELETE /api/skills/mcp/servers/:nameBroadcasts a server-removed event after removal.
Response (data)
{ "success": true }Reconnect a Server
POST /api/skills/mcp/servers/:name/reconnectBroadcasts server-reconnecting during reconnection, then server-reconnected on success or server-error on failure.
Response (data)
{ "success": true }Get Context Config
GET /api/skills/context-configResponse (data)
{
"maxTokens": 0,
"maxMessages": 20,
"compressionThreshold": 0.8,
"compressionStrategy": "summarize",
"preserveSystemPrompt": true,
"preserveRecentMessages": 4,
"autoReloadSkills": true
}Update Context Config
POST /api/skills/context-configOnly the following whitelisted fields are accepted (all other fields are ignored); they are merged into the context key of config.
Request Body
| Parameter | Type | Description |
|---|---|---|
maxTokens | number | Max tokens; 0 = unlimited |
maxMessages | number | Max messages |
compressionThreshold | number | Compression trigger threshold (0-1) |
compressionStrategy | string | Compression strategy: summarize / truncate / sliding-window |
preserveSystemPrompt | boolean | Preserve the system prompt when compressing |
preserveRecentMessages | number | Number of recent messages to preserve when compressing |
autoReloadSkills | boolean | Auto-reload skills after compression |
Response
data contains the fields that actually took effect; message is Context config updated.
Get Loaded Skills
GET /api/skills/loadedReturns an empty list when Skills is not initialized.
Response (data)
{
"skills": [],
"loaded": ["skill-name-1", "skill-name-2"]
}Load a Skill
POST /api/skills/load/:namePath Parameters
name- Skill name
Returns 500 when Skills is not initialized; returns 404 (message is Skill {name} does not exist) when the skill does not exist. Broadcasts a skill-loaded event on success.
Response (data)
{
"name": "skill-name",
"loaded": true
}Unload a Skill
POST /api/skills/unload/:namePath Parameters
name- Skill name
Returns 500 when Skills is not initialized. Broadcasts a skill-unloaded event after unloading.
Response (data)
{
"name": "skill-name",
"loaded": false
}Skill File Formats
The Skills system scans the data/skills directory for multiple skill file formats:
| File type | Description |
|---|---|
SKILL.md | Markdown format: frontmatter + instruction body |
*.skill.yaml / *.skill.yml | YAML skill definitions |
*.skill.json | JSON skill definitions |
skill.yaml / skill.json | Skill definition inside a folder |
SKILL.md Format
---
name: my-skill
description: Skill description
triggers: [trigger 1, trigger 2]
allowedTools: [tool1, tool2]
disallowedTools: []
priority: 10
autoActivate: true
---
Skill instruction body...YAML Format
name: my-skill
description: Skill description
triggers:
- trigger 1
- trigger 2
allowedTools:
- tool1
- tool2
disallowedTools: []
instructions: |
Skill instruction body...
capabilities:
- tool_use
priority: 10
autoActivate: trueBuilt-in Tool: list_skills
Lists all available skills and their descriptions. The model can call this tool to learn which skills are available to load.
{
"name": "list_skills",
"inputSchema": {
"type": "object",
"properties": {},
"required": []
}
}Built-in Tool: load_skill
Loads the specified skill into the current session. The skill's instructions take effect in subsequent conversations.
{
"name": "load_skill",
"inputSchema": {
"type": "object",
"properties": {
"name": { "type": "string", "description": "Name of the skill to load" }
},
"required": ["name"]
}
}Built-in Tool: get_skill_info
Gets detailed information about a specific skill.
{
"name": "get_skill_info",
"inputSchema": {
"type": "object",
"properties": {
"name": { "type": "string", "description": "Skill name" }
},
"required": ["name"]
}
}