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 operationsweather- Weather queriestmux- 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://..."
}
}
}
}
}
Option 2: Create a Proper Nanobot Skill (Recommended)
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/ |
Recommended Approach
For your PostgreSQL analyzer:
-
Keep the MCP server (
pg_mcp_server/server.py) - this is portable across Kimi CLI, Nanobot, Claude Desktop, etc. -
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)
-
The MCP server is the reusable part - skills are the interface layer that differs between platforms.