nanoagent/NANOBOT_SKILL_SETUP.md

11 KiB

PostgreSQL Analyzer Skill for Nanobot

Correction: Nanobot DOES Support Skills!

From the Nanobot GitHub repo:

nanobot/
├── agent/
│   ├── skills.py          # 🎯 Skills loader
│   └── ...
├── skills/                # 🎯 Bundled skills (github, weather, tmux...)
│   └── ...

Nanobot has its own skill system that's different from Kimi CLI's SKILL.md format:

  • Kimi CLI: Markdown-based (SKILL.md)
  • Nanobot: Python-based skills + ClawHub integration

Nanobot Skill System Overview

1. Built-in Skills

Nanobot comes with bundled skills in the skills/ directory:

  • github - GitHub operations
  • weather - Weather queries
  • tmux - Terminal multiplexer
  • And more...

2. ClawHub Skills

Nanobot can search and install skills from ClawHub (similar to OpenClaw's skill ecosystem):

# Search for skills
nanobot skill search postgres

# Install a skill
nanobot skill install postgres-analyzer

3. Custom Python Skills

You can create custom skills using Python (more powerful than markdown).


Option 1: MCP Server + System Prompt (Simplest)

This is what I showed earlier - use the MCP server with a system prompt:

// ~/.nanobot/config.json
{
  "agents": {
    "defaults": {
      "model": "anthropic/claude-sonnet-4",
      "systemPrompt": "You are a PostgreSQL analyst. Use MCP tools..."
    }
  },
  "tools": {
    "mcpServers": {
      "postgres": {
        "command": "python3",
        "args": ["/path/to/pg_mcp_server/server.py"],
        "env": {
          "PG_CONNECTION_STRING": "postgresql://..."
        }
      }
    }
  }
}

Create a Python skill file that Nanobot can load:

File: ~/.nanobot/skills/postgres_analyzer/skill.py

"""
PostgreSQL Analyzer Skill for Nanobot
Provides intelligent database analysis capabilities
"""

from nanobot.skills import Skill, intent, tool
from nanobot.agent.context import Context

class PostgresAnalyzerSkill(Skill):
    """
    Analyze PostgreSQL databases and generate insights.
    """
    
    name = "postgres-analyzer"
    description = "PostgreSQL database analysis and querying"
    
    @intent("explore database")
    @intent("show tables")
    @intent("what's in my database")
    async def explore_database(self, ctx: Context):
        """
        When user wants to explore database structure.
        Triggered by: 'explore database', 'show tables', etc.
        """
        # Call MCP tool via ctx.tools.mcp.postgres
        schema = await ctx.tools.mcp.postgres.get_schema()
        
        return {
            "type": "text",
            "content": f"📊 Database Schema:\n\n{schema}"
        }
    
    @intent("analyze table")
    @intent("tell me about table")
    async def analyze_table(self, ctx: Context, table_name: str = None):
        """
        When user wants to analyze a specific table.
        Triggered by: 'analyze the orders table'
        """
        if not table_name:
            # Try to extract from context or ask
            return "Which table would you like me to analyze?"
        
        stats = await ctx.tools.mcp.postgres.get_table_stats(
            table_name=table_name,
            sample_size=5
        )
        
        return {
            "type": "text", 
            "content": f"📈 Analysis of '{table_name}':\n\n{stats}"
        }
    
    @intent("expensive book")
    @intent("cheapest book")
    @intent("best seller")
    async def book_analysis(self, ctx: Context):
        """
        When user asks about book prices or sales.
        """
        result = await ctx.tools.mcp.postgres.execute_query(
            query="""
                SELECT 
                    p.name,
                    p.price,
                    SUM(oi.quantity) as sold,
                    SUM(oi.quantity * oi.unit_price) as revenue
                FROM products p
                LEFT JOIN order_items oi ON p.id = oi.product_id
                WHERE p.category = 'Books'
                GROUP BY p.id, p.name, p.price
                ORDER BY p.price DESC
            """,
            limit=10
        )
        
        return {
            "type": "text",
            "content": f"📚 Book Analysis:\n\n{result}"
        }
    
    @intent("run query")
    @intent("execute sql")
    async def custom_query(self, ctx: Context, query: str = None):
        """
        When user wants to run a custom SQL query.
        """
        if not query:
            return "What SQL query would you like to run?"
        
        # Safety check - ensure it's read-only
        query_lower = query.lower()
        forbidden = ['insert', 'update', 'delete', 'drop', 'create', 'alter']
        if any(word in query_lower for word in forbidden):
            return "⚠️ For safety, only SELECT queries are allowed."
        
        result = await ctx.tools.mcp.postgres.execute_query(
            query=query,
            limit=100
        )
        
        return {
            "type": "text",
            "content": f"📝 Query Results:\n\n{result}"
        }
    
    @intent("price analysis")
    @intent("pricing strategy")
    async def pricing_analysis(self, ctx: Context):
        """
        When user wants pricing insights.
        """
        analysis = await ctx.tools.mcp.postgres.execute_query(
            query="""
                SELECT 
                    p.category,
                    COUNT(*) as products,
                    MIN(p.price) as min_price,
                    MAX(p.price) as max_price,
                    AVG(p.price)::numeric(10,2) as avg_price,
                    SUM(oi.quantity) as units_sold
                FROM products p
                LEFT JOIN order_items oi ON p.id = oi.product_id
                GROUP BY p.category
                ORDER BY units_sold DESC
            """,
            limit=20
        )
        
        return {
            "type": "text",
            "content": f"💰 Pricing Analysis by Category:\n\n{analysis}"
        }

# Export the skill
skill = PostgresAnalyzerSkill()

File: ~/.nanobot/skills/postgres_analyzer/skill.json

{
  "name": "postgres-analyzer",
  "version": "1.0.0",
  "description": "PostgreSQL database analysis and querying",
  "author": "Your Name",
  "entry": "skill.py",
  "intents": [
    "explore database",
    "analyze table", 
    "expensive book",
    "run query",
    "price analysis"
  ],
  "mcpServers": ["postgres"]
}

Register in Config

// ~/.nanobot/config.json
{
  "agents": {
    "defaults": {
      "skills": ["postgres_analyzer"]
    }
  },
  "tools": {
    "mcpServers": {
      "postgres": {
        "command": "python3",
        "args": ["/path/to/pg_mcp_server/server.py"],
        "env": {
          "PG_CONNECTION_STRING": "postgresql://..."
        }
      }
    }
  }
}

Option 3: ClawHub-Compatible Skill (For Sharing)

To make your skill installable via nanobot skill install, create this structure:

postgres-analyzer-skill/
├── skill.md                    # Skill documentation
├── skill.py                    # Main skill code
├── config.json                 # Default config
└── README.md

skill.md

---
name: postgres-analyzer
version: 1.0.0
description: Analyze PostgreSQL databases and extract insights
author: your-github-username
tags: [database, postgres, sql, analytics]
---

# PostgreSQL Analyzer

This skill helps you analyze PostgreSQL databases and generate insights.

## Requirements

- PostgreSQL database
- PG_CONNECTION_STRING environment variable

## Features

- Explore database schema
- Run SQL queries
- Analyze table statistics
- Generate pricing insights

## Usage

Simply ask:
- "Show me all tables"
- "What's the most expensive book?"
- "Analyze the orders table"
- "Run: SELECT * FROM users LIMIT 10"

How Nanobot Decides to Use Skills

User: "What's the most expensive book?"
           │
           ▼
┌─────────────────────────────┐
│  1. Intent Recognition       │
│  ─────────────────           │
│  Matches against skill       │
│  @intent decorators:         │
│  • "expensive book" ✅       │
│  • "analyze table"           │
│  • "run query"               │
└─────────────┬───────────────┘
              │
              ▼
┌─────────────────────────────┐
│  2. Skill Method Called      │
│  ─────────────────────       │
│  PostgresAnalyzerSkill       │
│    .book_analysis()          │
└─────────────┬───────────────┘
              │
              ▼
┌─────────────────────────────┐
│  3. MCP Tool Execution       │
│  ─────────────────────       │
│  ctx.tools.mcp.postgres      │
│    .execute_query(...)       │
└─────────────┬───────────────┘
              │
              ▼
┌─────────────────────────────┐
│  4. Result Synthesis         │
│  ─────────────────           │
│  Return formatted response   │
└─────────────────────────────┘

Comparison: Kimi CLI vs Nanobot Skills

Aspect Kimi CLI Nanobot
Format SKILL.md (markdown) Python code
Trigger Frontmatter description matching @intent() decorators
Logic LLM decides based on instructions Python code + LLM hybrid
MCP Usage Via tool descriptions Via ctx.tools.mcp
Flexibility Text-based guidance Code-based, programmatic
Installation Copy to ~/.config/agents/skills/ nanobot skill install or copy to ~/.nanobot/skills/

For your PostgreSQL analyzer:

  1. Keep the MCP server (pg_mcp_server/server.py) - this is portable across Kimi CLI, Nanobot, Claude Desktop, etc.

  2. Choose skill approach based on your needs:

    • Quick setup: Use system prompt (Option 1)
    • More control: Create Python skill (Option 2)
    • Share with community: ClawHub format (Option 3)
  3. The MCP server is the reusable part - skills are the interface layer that differs between platforms.