feat: openclaw-style secrets (env.vars + \) and per-task model routing
- Replace python-dotenv with config.json env.vars block + \ substitution - Add models section for per-task model routing (heartbeat, subagent, default) - Heartbeat/subagent tasks can use different models/providers than main chat - Remove python-dotenv from dependencies - Update all docs to reflect new config approach - Reorganize docs into project/ and research/ subdirectories
This commit is contained in:
207
docs/research/nanobot.md
Normal file
207
docs/research/nanobot.md
Normal file
@@ -0,0 +1,207 @@
|
||||
# 🐈 Nanobot — Architecture & How It Works
|
||||
|
||||
> **Ultra-Lightweight Personal AI Assistant** — ~4,000 lines of Python, 99% smaller than OpenClaw.
|
||||
|
||||
## Overview
|
||||
|
||||
Nanobot is a minimalist personal AI assistant written in Python that focuses on delivering core agent functionality with the smallest possible codebase. It uses LiteLLM for multi-provider LLM routing, supports 9+ chat channels, and includes memory, skills, scheduled tasks, and MCP tool integration.
|
||||
|
||||
| Attribute | Value |
|
||||
|-----------|-------|
|
||||
| **Language** | Python 3.11+ |
|
||||
| **Lines of Code** | ~4,000 (core agent) |
|
||||
| **Config** | `~/.nanobot/config.json` |
|
||||
| **Package** | `pip install nanobot-ai` |
|
||||
| **LLM Routing** | LiteLLM (multi-provider) |
|
||||
|
||||
---
|
||||
|
||||
## Architecture Flowchart
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph Channels["📱 Chat Channels"]
|
||||
TG["Telegram"]
|
||||
DC["Discord"]
|
||||
WA["WhatsApp"]
|
||||
FS["Feishu"]
|
||||
MC["Mochat"]
|
||||
DT["DingTalk"]
|
||||
SL["Slack"]
|
||||
EM["Email"]
|
||||
QQ["QQ"]
|
||||
end
|
||||
|
||||
subgraph Gateway["🌐 Gateway (nanobot gateway)"]
|
||||
CH["Channel Manager"]
|
||||
MQ["Message Queue"]
|
||||
end
|
||||
|
||||
subgraph Agent["🧠 Core Agent"]
|
||||
LOOP["Agent Loop\n(loop.py)"]
|
||||
CTX["Context Builder\n(context.py)"]
|
||||
MEM["Memory System\n(memory.py)"]
|
||||
SK["Skills Loader\n(skills.py)"]
|
||||
SA["Subagent\n(subagent.py)"]
|
||||
end
|
||||
|
||||
subgraph Tools["🔧 Built-in Tools"]
|
||||
SHELL["Shell Exec"]
|
||||
FILE["File R/W/Edit"]
|
||||
WEB["Web Search"]
|
||||
SPAWN["Spawn Subagent"]
|
||||
MCP["MCP Servers"]
|
||||
end
|
||||
|
||||
subgraph Providers["☁️ LLM Providers (LiteLLM)"]
|
||||
OR["OpenRouter"]
|
||||
AN["Anthropic"]
|
||||
OA["OpenAI"]
|
||||
DS["DeepSeek"]
|
||||
GR["Groq"]
|
||||
GE["Gemini"]
|
||||
VL["vLLM (local)"]
|
||||
end
|
||||
|
||||
Channels --> Gateway
|
||||
Gateway --> Agent
|
||||
CTX --> LOOP
|
||||
MEM --> CTX
|
||||
SK --> CTX
|
||||
LOOP --> Tools
|
||||
LOOP --> Providers
|
||||
SA --> LOOP
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Message Flow
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User
|
||||
participant Channel as Chat Channel
|
||||
participant GW as Gateway
|
||||
participant Agent as Agent Loop
|
||||
participant LLM as LLM Provider
|
||||
participant Tools as Tools
|
||||
|
||||
User->>Channel: Send message
|
||||
Channel->>GW: Forward message
|
||||
GW->>Agent: Route to agent
|
||||
Agent->>Agent: Build context (memory, skills, identity)
|
||||
Agent->>LLM: Send prompt + tools
|
||||
LLM-->>Agent: Response (text or tool call)
|
||||
|
||||
alt Tool Call
|
||||
Agent->>Tools: Execute tool
|
||||
Tools-->>Agent: Tool result
|
||||
Agent->>LLM: Send tool result
|
||||
LLM-->>Agent: Final response
|
||||
end
|
||||
|
||||
Agent->>Agent: Update memory
|
||||
Agent-->>GW: Return response
|
||||
GW-->>Channel: Send reply
|
||||
Channel-->>User: Display response
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Key Components
|
||||
|
||||
### 1. Agent Loop (`agent/loop.py`)
|
||||
The core loop that manages the LLM ↔ tool execution cycle:
|
||||
- Builds a prompt using context (memory, skills, identity files)
|
||||
- Sends to LLM via LiteLLM
|
||||
- If LLM returns a tool call → executes it → sends result back
|
||||
- Continues until LLM returns a text response (no more tool calls)
|
||||
|
||||
### 2. Context Builder (`agent/context.py`)
|
||||
Assembles the system prompt from:
|
||||
- **Identity files**: `AGENTS.md`, `SOUL.md`, `USER.md`, `TOOLS.md`, `IDENTITY.md`
|
||||
- **Memory**: Persistent `MEMORY.md` with recall
|
||||
- **Skills**: Loaded from `~/.nanobot/workspace/skills/`
|
||||
- **Conversation history**: Session-based context
|
||||
|
||||
### 3. Memory System (`agent/memory.py`)
|
||||
- Persistent memory stored in `MEMORY.md` in the workspace
|
||||
- Agent can read and write memories
|
||||
- Survives across sessions
|
||||
|
||||
### 4. Provider Registry (`providers/registry.py`)
|
||||
- Single-source-of-truth for all LLM providers
|
||||
- Adding a new provider = 2 steps (add `ProviderSpec` + config field)
|
||||
- Auto-prefixes model names for LiteLLM routing
|
||||
- Supports 12+ providers including local vLLM
|
||||
|
||||
### 5. Channel System (`channels/`)
|
||||
- 9 chat platforms supported (Telegram, Discord, WhatsApp, Feishu, Mochat, DingTalk, Slack, Email, QQ)
|
||||
- Each channel handles auth, message parsing, and response delivery
|
||||
- Allowlist-based security (`allowFrom`)
|
||||
- Started via `nanobot gateway`
|
||||
|
||||
### 6. Skills (`skills/`)
|
||||
- Bundled skills: GitHub, weather, tmux, etc.
|
||||
- Custom skills loaded from workspace
|
||||
- Skills are injected into the agent's context
|
||||
|
||||
### 7. Scheduled Tasks (Cron)
|
||||
- Add jobs via `nanobot cron add`
|
||||
- Supports cron expressions and interval-based scheduling
|
||||
- Jobs stored persistently
|
||||
|
||||
### 8. MCP Integration
|
||||
- Supports Model Context Protocol servers
|
||||
- Stdio and HTTP transport modes
|
||||
- Compatible with Claude Desktop / Cursor MCP configs
|
||||
- Tools auto-discovered and registered at startup
|
||||
|
||||
---
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
nanobot/
|
||||
├── agent/ # 🧠 Core agent logic
|
||||
│ ├── loop.py # Agent loop (LLM ↔ tool execution)
|
||||
│ ├── context.py # Prompt builder
|
||||
│ ├── memory.py # Persistent memory
|
||||
│ ├── skills.py # Skills loader
|
||||
│ ├── subagent.py # Background task execution
|
||||
│ └── tools/ # Built-in tools (incl. spawn)
|
||||
├── skills/ # 🎯 Bundled skills (github, weather, tmux...)
|
||||
├── channels/ # 📱 Chat channel integrations
|
||||
├── providers/ # ☁️ LLM provider registry
|
||||
├── config/ # ⚙️ Configuration schema
|
||||
├── cron/ # ⏰ Scheduled tasks
|
||||
├── heartbeat/ # 💓 Heartbeat system
|
||||
├── session/ # 📝 Session management
|
||||
├── bus/ # 📨 Internal event bus
|
||||
├── cli/ # 🖥️ CLI commands
|
||||
└── utils/ # 🔧 Utilities
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## CLI Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `nanobot onboard` | Initialize config & workspace |
|
||||
| `nanobot agent -m "..."` | Chat with the agent |
|
||||
| `nanobot agent` | Interactive chat mode |
|
||||
| `nanobot gateway` | Start all channels |
|
||||
| `nanobot status` | Show status |
|
||||
| `nanobot cron add/list/remove` | Manage scheduled tasks |
|
||||
| `nanobot channels login` | Link WhatsApp device |
|
||||
|
||||
---
|
||||
|
||||
## Key Design Decisions
|
||||
|
||||
1. **LiteLLM for provider abstraction** — One interface for all LLM providers
|
||||
2. **JSON config over env vars** — Single `config.json` file for all settings
|
||||
3. **Skills-based extensibility** — Modular skill system for adding capabilities
|
||||
4. **Provider Registry pattern** — Adding providers is 2-step, zero if-elif chains
|
||||
5. **Agent social network** — Can join MoltBook, ClawdChat communities
|
||||
Reference in New Issue
Block a user