Home / Docs / Skills

Skills

Skills are user-created tools that extend Zubo's capabilities. Each skill is a single TypeScript file that the agent can invoke during conversations to perform actions, fetch data, or interact with external services. Skills are hot-loaded — you can add, edit, or remove them without restarting Zubo. User-installed skills run in sandboxed subprocesses for security, ensuring they cannot access Zubo's internal state or database.

Quick Start

The fastest way to create a skill is with the built-in scaffolding command:

zubo skills new

This interactive wizard walks you through choosing a name, writing a description, and defining parameters. It generates a ready-to-use handler.ts file in your skills directory.

Even easier — just tell Zubo what you need in plain language:

"Build a skill that checks the weather for a location"

Zubo will generate the entire skill file for you, including parameter definitions, error handling, and a working implementation. You can then refine it by chatting: "Add a units parameter that accepts celsius or fahrenheit."

Single-File Format

Every skill is a single TypeScript file with two exports: a skill configuration object and a default handler function. Here is a complete example:

export const skill = {
  name: "weather",
  description: "Get current weather for a location",
  params: {
    location: { type: "string", description: "City or coordinates", required: true },
    units: { type: "string", description: "celsius or fahrenheit" }
  }
};

export default async function (input: Record<string, unknown>): Promise<string> {
  const location = input.location as string;
  const units = (input.units as string) || "metric";
  const res = await fetch(`https://api.example.com/weather?q=${location}&units=${units}`);
  return JSON.stringify(await res.json());
}

The skill object tells the AI what this tool does and what parameters it accepts. The default export is the function that runs when the skill is invoked. This is all you need — no boilerplate, no build step, no configuration files.

Skill Config

The exported skill object defines metadata that Zubo uses to register the tool with the LLM:

FieldRequiredDescription
nameYesUnique identifier. Lowercase letters, numbers, and underscores only ([a-z0-9_]+). This is how the AI references your skill internally.
descriptionYesA natural-language explanation shown to the AI. The LLM uses this to decide when to invoke your skill, so be specific and descriptive.
paramsNoAn object mapping parameter names to their definitions (see Params Format below). If omitted, the skill accepts no parameters.

Params Format

Each key in the params object is a parameter name. The value is an object with the following fields:

FieldTypeDescription
typestringThe data type: "string", "number", or "boolean". Determines how the LLM formats the argument.
descriptionstringExplains what this parameter does. Shown to the AI to help it provide the correct value.
requiredbooleanWhether the parameter must be provided. Defaults to false if omitted.

The params are automatically converted to JSON Schema and passed to the LLM as part of the tool definition. You do not need to write JSON Schema yourself — Zubo handles the conversion.

Handler Function

The handler is the default export of your skill file. It is the function that executes when the AI decides to use your skill.

Accessing Secrets

Skills often need API keys or credentials to call external services. Zubo provides a secure way to pass secrets to skill handlers via environment variables:

export default async function (input: Record<string, unknown>): Promise<string> {
  const apiKey = process.env.ZUBO_SECRET_WEATHER_API_KEY;
  if (!apiKey) return JSON.stringify({ error: "Weather API key not configured" });

  const location = input.location as string;
  const res = await fetch(
    `https://api.weatherapi.com/v1/current.json?key=${apiKey}&q=${location}`
  );
  return JSON.stringify(await res.json());
}

Secrets referenced in the handler code are automatically passed to the sandboxed subprocess as environment variables with the ZUBO_SECRET_ prefix. Only the secrets that your handler actually references are injected — other secrets are not exposed.

Set secrets via the dashboard or by telling Zubo in chat:

"Store my weather API key: abc123"

You can also use the CLI: zubo secrets set WEATHER_API_KEY abc123

Skill Directory Structure

All skills live under the Zubo workspace directory. Each skill gets its own folder containing a handler.ts file:

~/.zubo/workspace/skills/
├── weather/
│   └── handler.ts      # Single-file skill
├── calculator/
│   ├── SKILL.md         # Legacy format (still supported)
│   └── handler.ts
├── email_sender/
│   └── handler.ts
└── stock_price/
    └── handler.ts

When Zubo starts (or when a skill is added/modified), it scans this directory and hot-loads all valid skills. You can manually place files here or use zubo skills new to scaffold them.

Sandbox Behavior

Security is a core concern when running user-authored code. Zubo enforces the following sandbox rules for user-installed skills:

Skill Registry

The Zubo skill registry is a community-driven marketplace where you can discover, install, and publish skills:

You can also browse and install skills by chatting with Zubo: "Search for a skill that sends emails" or "Install the github_issues skill."

Managing Skills

Use the CLI to manage your installed skills:

zubo skills list          # List all installed skills
zubo skills new           # Create a new skill interactively
zubo skills remove        # Remove an installed skill
zubo install weather      # Install a skill from the registry
zubo search "email"       # Search the registry for skills
zubo publish my_skill     # Publish your skill to the registry

Or manage skills conversationally by telling Zubo:

Built-in Tools Reference

Zubo ships with a comprehensive set of built-in tools that are always available. These are not sandboxed — they run in the main process and have full access to Zubo's internals.

ToolDescriptionPermission
get_current_datetimeGet current date and time with timezoneauto
memory_writeSave a fact or note to persistent memoryauto
memory_searchSearch memory using semantic and full-text searchauto
manage_skillsCreate, list, or remove user skillsauto
secret_setStore a secret (API key, token, etc.)auto
secret_listList all stored secret namesauto
secret_deleteDelete a stored secretconfirm
cron_createCreate a scheduled task (cron job)auto
cron_listList all scheduled tasksauto
cron_deleteDelete a scheduled taskauto
connect_serviceConnect an external integration (GitHub, Google, etc.)auto
delegateDelegate a task to a sub-agentauto
manage_agentsCreate, list, or remove sub-agentsauto
manage_workflowsCreate and manage multi-step workflowsauto
manage_teamsManage agent teams and coordinationauto
manage_triggersManage proactive triggers and alertsauto
run_workflowExecute a defined workflowauto
skill_registrySearch and install skills from the registryauto
shellExecute shell commands on the host systemconfirm
file_readRead the contents of a fileauto
file_writeWrite or append content to a fileconfirm
web_searchSearch the web via DuckDuckGoauto
url_fetchFetch and extract content from a web pageauto
http_requestMake a generic HTTP request (GET, POST, etc.)auto

Tools marked confirm require user confirmation before execution. Tools marked auto run immediately without prompting.

Legacy Format (SKILL.md)

Earlier versions of Zubo used a Markdown-based skill definition file called SKILL.md. This format is still fully supported for backward compatibility:

# weather
Get current weather for a location.

## Input Schema
```json
{
  "type": "object",
  "properties": {
    "location": { "type": "string", "description": "City or coordinates" }
  },
  "required": ["location"]
}
```

If both a SKILL.md file and an exported skill configuration object exist in the same skill directory, the SKILL.md definition takes precedence. For new skills, the inline export const skill format is recommended as it keeps everything in a single file.

Best Practices