Skip to main content

Skills System

Skills are pluggable capability modules that teach the agent how to perform specific tasks or use particular tools. They are implemented as markdown files with frontmatter metadata.

Overview

The skills system is implemented in nanobot/agent/skills.py through the SkillsLoader class:
class SkillsLoader:
    """
    Loader for agent skills.

    Skills are markdown files (SKILL.md) that teach the agent how to use
    specific tools or perform certain tasks.
    """

Skill Structure

Skills are organized in directories with a standard structure:
workspace/
└── skills/
    ├── web-research/
    │   ├── SKILL.md          # Skill instructions
    │   ├── templates/        # Optional templates
    │   └── scripts/          # Optional helper scripts
    ├── python-dev/
    │   └── SKILL.md
    └── data-analysis/
        └── SKILL.md
The only required file is SKILL.md — everything else is optional.

Skill Locations

Skills are loaded from two locations with priority order:
1

Workspace Skills (Highest Priority)

User-defined skills in {workspace}/skills/These override built-in skills with the same name.
2

Built-in Skills

Pre-packaged skills in nanobot/skills/These ship with nanobot and provide common capabilities.

SKILL.md Format

Skills use markdown with YAML frontmatter:
---
title: Web Research
description: Search and extract information from the web
metadata: |
  {
    "nanobot": {
      "always": false,
      "requires": {
        "env": ["BRAVE_API_KEY"]
      }
    }
  }
---

# Web Research Skill

This skill teaches you how to perform effective web research using the 
`web_search` and `web_fetch` tools.

## When to Use

Use this skill when you need to:
- Find current information not in your training data
- Research specific topics or questions
- Verify facts or claims
- Gather data from multiple sources

## Tools

### web_search

Searches the web and returns titles, URLs, and snippets.

**Parameters:**
- `query` (string, required): The search query
- `count` (integer, optional): Number of results (1-10, default: 5)

### web_fetch

Fetches a URL and extracts readable content.

**Parameters:**
- `url` (string, required): The URL to fetch
- `extractMode` (string, optional): "markdown" or "text" (default: "markdown")
- `maxChars` (integer, optional): Maximum characters to return

## Workflow

1. Use `web_search` to find relevant sources
2. Review the search results and identify the most promising URLs
3. Use `web_fetch` to extract content from selected URLs
4. Synthesize information from multiple sources
5. Cite your sources when providing information

## Example

```json
// Search for information
{"tool": "web_search", "query": "latest developments in quantum computing"}

// Fetch specific article
{"tool": "web_fetch", "url": "https://example.com/quantum-news"}

Frontmatter Metadata

The metadata field in frontmatter can contain nanobot-specific configuration:
{
  "nanobot": {
    "always": true
  }
}
Skills marked with always: true are automatically loaded into every agent context. Use this for foundational skills that should always be available.
{
  "nanobot": {
    "requires": {
      "bins": ["git", "docker"],
      "env": ["GITHUB_TOKEN", "DOCKER_HOST"]
    }
  }
}
Declare required system binaries and environment variables. Skills with unmet requirements are marked as unavailable.

Loading Skills

The SkillsLoader provides several methods for working with skills:

List Available Skills

from nanobot.agent.skills import SkillsLoader
from pathlib import Path

loader = SkillsLoader(workspace=Path("/path/to/workspace"))
skills = loader.list_skills(filter_unavailable=True)

for skill in skills:
    print(f"{skill['name']}: {skill['path']} ({skill['source']})")
Output:
web-research: /workspace/skills/web-research/SKILL.md (workspace)
python-dev: /nanobot/skills/python-dev/SKILL.md (builtin)

Load Skill Content

content = loader.load_skill("web-research")
if content:
    print(content)
else:
    print("Skill not found")

Build Skills Summary

The skills summary is included in the agent’s system prompt:
summary = loader.build_skills_summary()
Generated XML:
<skills>
  <skill available="true">
    <name>web-research</name>
    <description>Search and extract information from the web</description>
    <location>/workspace/skills/web-research/SKILL.md</location>
  </skill>
  <skill available="false">
    <name>docker-ops</name>
    <description>Manage Docker containers and images</description>
    <location>/nanobot/skills/docker-ops/SKILL.md</location>
    <requires>CLI: docker</requires>
  </skill>
</skills>
The agent can use the read_file tool to load full skill content when needed (progressive loading).

Progressive Loading

To keep context size manageable, nanobot uses progressive skill loading:
1

System Prompt Includes Summary

The system prompt contains a lightweight XML summary of all available skills with names, descriptions, and locations.
2

Agent Decides What to Load

The agent reads the summary and decides which skills are relevant to the current task.
3

Agent Loads Full Skill

The agent uses read_file to load the complete SKILL.md content when needed.
Context Builder Integration:
skills_summary = self.skills.build_skills_summary()
if skills_summary:
    parts.append(f"""# Skills

The following skills extend your capabilities. To use a skill, read its SKILL.md file using the read_file tool.
Skills with available="false" need dependencies installed first - you can try installing them with apt/brew.

{skills_summary}""")
See nanobot/agent/context.py:44-52 for implementation.

Always-Loaded Skills

Skills marked with always: true in their metadata are automatically loaded into every context:
def build_system_prompt(self, skill_names: list[str] | None = None) -> str:
    # ... identity and bootstrap ...
    
    always_skills = self.skills.get_always_skills()
    if always_skills:
        always_content = self.skills.load_skills_for_context(always_skills)
        if always_content:
            parts.append(f"# Active Skills\n\n{always_content}")
See nanobot/agent/context.py:38-42.

Checking Requirements

The loader validates skill requirements:
def _check_requirements(self, skill_meta: dict) -> bool:
    """Check if skill requirements are met (bins, env vars)."""
    requires = skill_meta.get("requires", {})
    for b in requires.get("bins", []):
        if not shutil.which(b):
            return False
    for env in requires.get("env", []):
        if not os.environ.get(env):
            return False
    return True
See nanobot/agent/skills.py:177-186.
Skills with unmet requirements are still listed but marked as available="false" in the summary.

Creating Custom Skills

1

Create Skill Directory

mkdir -p ~/workspace/skills/my-skill
2

Write SKILL.md

cat > ~/workspace/skills/my-skill/SKILL.md << 'EOF'
---
title: My Custom Skill
description: Does something awesome
metadata: |
  {
    "nanobot": {
      "always": false
    }
  }
---

# My Custom Skill

This skill helps you do X, Y, and Z.

## When to Use

Use this when...

## Instructions

1. First, do this...
2. Then, do that...
3. Finally, verify...
EOF
3

Test the Skill

The skill is immediately available to the agent. Ask:
"What skills do you have for [my task]?"
The agent will discover and load your skill.

Skill Best Practices

Be Specific

Provide concrete examples and step-by-step workflows

Document Tools

List all relevant tools with parameters and examples

Show When to Use

Clearly state the scenarios where this skill applies

Include Examples

Provide real examples of tool calls and workflows
Keep skills focused on a single capability or workflow. Don’t create mega-skills that try to do everything.

ClawHub Integration

Nanobot integrates with ClawHub for discovering and installing community skills:
# Search for skills
nanobot skill search "web scraping"

# Install a skill
nanobot skill install username/skill-name

# List installed skills
nanobot skill list
ClawHub skills are installed to your workspace skills/ directory.

Implementation Reference

Key methods in SkillsLoader (nanobot/agent/skills.py):
MethodPurposeLine
list_skills()List all available skills26
load_skill()Load a single skill by name59
load_skills_for_context()Load multiple skills for context82
build_skills_summary()Build XML summary for system prompt101
get_always_skills()Get skills marked as always-loaded193
_check_requirements()Validate skill dependencies177

Architecture

How skills fit into the system

Tools

Tools that skills teach the agent to use

Agent Loop

How skills are loaded during processing

Build docs developers (and LLMs) love