Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

nanobot User Guide

Generated June 2026 from HKUDS/nanobot at 6a0368b

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

🐈 nanobot is an open-source, ultra-lightweight agent runtime for people who want to own their AI agent stack. It gives you a small, readable core plus the practical pieces for real long-running agents: a WebUI, chat channels, tools, memory, MCP, model routing, image generation, and deployment — all driven by a single ~/.nanobot/config.json file.

This guide shows you how to install nanobot, get a working agent running in about two minutes, connect it to your favorite chat apps, and use its day-to-day features. Written from the source code of nanobot v0.2.1. For architecture, the complete configuration reference, security hardening, and developer internals, see the companion Admin Guide.

Note

nanobot installs from PyPI as the package nanobot-ai but the command you run is always nanobot. Requires Python ≥ 3.11.


1. Quick Start

Get a working AI agent in three commands.

Step 1 — Install

pip

pip install nanobot-ai

uv (fast)

uv tool install nanobot-ai

From source

git clone https://github.com/HKUDS/nanobot.git
cd nanobot
pip install -e .

Tip

Install from PyPI or uv for the most stable day-to-day experience. Install from source if you want the newest features and experiments — they land there first.

Step 2 — Initialize

nanobot onboard
✓ Created ~/.nanobot/config.json
✓ Created ~/.nanobot/workspace/

This creates your config and workspace under ~/.nanobot/. Add --wizard to walk through an interactive setup that helps you pick a provider and model:

nanobot onboard --wizard

Step 3 — Configure your key and model

Open ~/.nanobot/config.json and set just two things — a provider API key and a model. Everything else has sensible defaults. OpenRouter is recommended for global users because it can reach almost any model with one key.

{
  "providers": {
    "openrouter": {
      "apiKey": "sk-or-v1-xxx"
    }
  },
  "agents": {
    "defaults": {
      "provider": "openrouter",
      "model": "anthropic/claude-opus-4-6"
    }
  }
}

Important

Add or merge these blocks into your existing config — don't replace the whole file. nanobot onboard already filled it with defaults you want to keep.

Step 4 — Chat

nanobot agent
nanobot 🐈  (type /help for commands, /quit to exit)
you ›

That's it — you have a working AI agent. Send a one-off message instead of entering interactive mode with -m:

nanobot agent -m "What time is it in Tokyo?"

2. Installation in Detail

Requirements

Requirement Detail
Python 3.11 or newer
OS Linux, macOS, Windows (Windows is explicitly supported)
Node.js Only needed for the WhatsApp channel (≥ 18)
An LLM API key From any supported provider — or a local model (Ollama, LM Studio, vLLM, etc.) with no key

Optional features (extras)

Some channels and capabilities need extra dependencies. Install them with pip "extras":

pip install "nanobot-ai[matrix]"     # Matrix channel
pip install "nanobot-ai[discord]"    # Discord channel
pip install "nanobot-ai[weixin]"     # WeChat (Weixin) channel
pip install "nanobot-ai[wecom]"      # WeCom channel
pip install "nanobot-ai[msteams]"    # Microsoft Teams channel
pip install "nanobot-ai[api]"        # OpenAI-compatible API server
pip install "nanobot-ai[azure]"      # Azure OpenAI (Entra ID auth)
pip install "nanobot-ai[pdf]"        # Faster/richer PDF reading (PyMuPDF)

Note

Matrix is not supported on Windows. Its matrix-nio[e2e] dependency needs python-olm, which has no Windows wheel. Use macOS, Linux, or WSL2 for the Matrix channel.

Updating

# pip
pip install -U nanobot-ai
nanobot --version

# uv
uv tool upgrade nanobot-ai
nanobot --version

Warning

If you use WhatsApp, the local bridge is not rebuilt automatically when you upgrade. After updating, rebuild it:

rm -rf ~/.nanobot/bridge
nanobot channels login whatsapp

3. The Three Ways to Run nanobot

nanobot is one program with several front doors. Pick the one that fits what you're doing.

Command What it starts Use it when
nanobot agent A local interactive (or one-shot) chat in your terminal You want to talk to the agent directly, test config, or script it
nanobot gateway The long-running service that connects all your enabled chat channels and serves the WebUI You want nanobot online 24/7 reachable from Telegram, Discord, the browser, etc.
nanobot serve A minimal OpenAI-compatible HTTP API You want to call nanobot from your own code/tools as if it were OpenAI

Important

nanobot agent runs its own local agent. It does not attach to or proxy through a running nanobot gateway — they are independent processes that share the same config and workspace.


4. Everyday Usage

4.1 Interactive terminal chat

nanobot agent

Useful flags:

Flag Effect
-m "..." Send one message and exit (non-interactive)
--no-markdown Show plain-text replies instead of rendered markdown
--logs Show runtime logs during the chat
-w <workspace> Use a specific workspace directory
-c <config> Use a specific config file

Exit interactive mode with any of: exit, quit, /exit, /quit, :q, or Ctrl+D.

4.2 In-chat slash commands

These work everywhere — the terminal, the WebUI, and every chat channel. They control the live agent, not the service.

Command Description
/new Stop the current task and start a fresh conversation
/stop Stop the current task
/restart Restart the bot
/status Show bot status
/model Show the current model and available presets
/model <preset> Switch the runtime model preset for future turns
/dream Run Dream memory consolidation now
/dream-log Show the latest Dream memory change
/dream-log <sha> Show a specific Dream memory change
/dream-restore List recent Dream memory versions
/dream-restore <sha> Restore memory to the state before a change
/skill List enabled skills and their descriptions
/pairing List pending pairing requests
/pairing approve <code> Approve a pairing code
/pairing deny <code> Deny a pending pairing request
/pairing revoke <user_id> Revoke an approved user on the current channel
/help Show available in-chat commands

Tip

Slash commands are different from the shell CLI (nanobot agent, nanobot gateway…). The shell CLI manages the service; slash commands operate on the live conversation. You can also fire a slash command from the terminal: nanobot agent -m "/status".

4.3 What the agent can do — the tool kit

nanobot's agent decides on its own which tools to call to complete your request. You never call tools directly; you just describe what you want. These are the built-in capabilities:

Tool What it lets the agent do
read_file, write_file, edit_file, list_dir Read, create, modify, and browse files in its workspace
apply_patch Apply a structured multi-file patch
exec Run shell commands (sandboxable — see Admin Guide)
web_search Search the web (DuckDuckGo by default, no key needed)
web_fetch Fetch a web page and read it as Markdown
spawn Spin up a subagent to work on a sub-task in parallel
long_task / goal Pursue a long-running objective across many turns
cron Schedule its own reminders and recurring tasks
message Proactively send a message to one of your chat channels
generate_image Generate or edit images (when enabled)
my Inspect and tune its own runtime state (model, context window, iteration budget)
cli_apps Drive installed command-line apps
MCP tools Any tool exposed by an external MCP server you connect

Note

Web tools (web_search + web_fetch) are on by default and work out of the box with no API key. See Web search to switch to Brave, Tavily, Kagi, and others.

4.4 Talking to your agent in chat apps

The real power of nanobot is reaching your agent from the messaging apps you already use. Enable a channel in config, run nanobot gateway, and message your bot. See Section 5 for per-platform setup.


5. Connect Chat Apps

nanobot can front your agent across many platforms at once from a single nanobot gateway process. Enable each channel under channels in ~/.nanobot/config.json.

Channel What you need Public IP needed?
Telegram Bot token from @BotFather No (long-poll) / optional webhook
Discord Bot token + Message Content intent No
WhatsApp QR code scan (nanobot channels login whatsapp) No
WeChat (Weixin) QR code scan (nanobot channels login weixin) No
Feishu / Lark App ID + App Secret No (WebSocket)
DingTalk App Key + App Secret No (Stream mode)
Slack Bot token + App-Level token No (Socket mode)
Matrix Homeserver URL + access token (or password) No
Email IMAP/SMTP credentials No
QQ App ID + App Secret No
Napcat (QQ) Forward-WebSocket URL + access token No
WeCom (企业微信) Bot ID + Bot Secret No
Microsoft Teams App ID + Password + public HTTPS endpoint Yes (webhook)
Mochat Claw token (auto-setup available) No
Signal signal-cli daemon + phone number No
WebSocket / WebUI Nothing (built-in) No

After enabling any channel, start the service:

nanobot gateway
  1. Open Telegram, message @BotFather, send /newbot, and copy the token.
  2. Configure:
{
  "channels": {
    "telegram": {
      "enabled": true,
      "token": "YOUR_BOT_TOKEN",
      "allowFrom": ["YOUR_USER_ID"]
    }
  }
}
  1. Run nanobot gateway and message your bot.

Tip

Find your numeric User ID with @userinfobot and paste it without the @. Telegram uses long polling by default — no public IP required. A webhook mode is available (see Admin Guide).

5.2 Discord

{
  "channels": {
    "discord": {
      "enabled": true,
      "token": "YOUR_BOT_TOKEN",
      "allowFrom": ["YOUR_USER_ID"],
      "groupPolicy": "mention",
      "streaming": true
    }
  }
}

Enable the MESSAGE CONTENT INTENT in the Discord developer portal, invite the bot with Send Messages + Read Message History permissions, then run nanobot gateway.

groupPolicy controls group behavior: "mention" (default — reply only when @mentioned) or "open" (reply to everything). DMs always respond for users in allowFrom.

5.3 Slack

Uses Socket Mode — no public URL needed. Create a Slack app, turn on Socket Mode, add the bot scopes (chat:write, app_mentions:read, files:read, files:write, channel histories), subscribe to message.im / app_mention events, then:

{
  "channels": {
    "slack": {
      "enabled": true,
      "botToken": "xoxb-...",
      "appToken": "xapp-...",
      "allowFrom": ["YOUR_SLACK_USER_ID"],
      "groupPolicy": "mention"
    }
  }
}

5.4 Feishu / Lark

Uses a WebSocket long connection — no public IP. Create a Feishu app, enable the Bot capability, add the im:message permissions (plus cardkit:card:write for streaming replies), subscribe to im.message.receive_v1 in Long Connection mode, then:

{
  "channels": {
    "feishu": {
      "enabled": true,
      "appId": "cli_xxx",
      "appSecret": "xxx",
      "allowFrom": ["ou_YOUR_OPEN_ID"],
      "streaming": true,
      "domain": "feishu"
    }
  }
}

Set "domain": "lark" for international Lark. If you can't add cardkit:card:write, set "streaming": false — replies still work, just without token-by-token streaming.

5.5 WhatsApp

Requires Node.js ≥ 18. nanobot ships a local bridge (built on Baileys) that links to your phone via QR code.

# Terminal 1 — link your device (scan the QR with WhatsApp → Linked Devices)
nanobot channels login whatsapp

# Terminal 2 — run the service
nanobot gateway
{
  "channels": {
    "whatsapp": {
      "enabled": true,
      "allowFrom": ["+1234567890"]
    }
  }
}

5.6 Email

Give nanobot its own mailbox; it polls IMAP and replies via SMTP like a personal email assistant.

{
  "channels": {
    "email": {
      "enabled": true,
      "consentGranted": true,
      "imapHost": "imap.gmail.com",
      "imapPort": 993,
      "imapUsername": "[email removed]",
      "imapPassword": "your-app-password",
      "smtpHost": "smtp.gmail.com",
      "smtpPort": 587,
      "smtpUsername": "[email removed]",
      "smtpPassword": "your-app-password",
      "fromAddress": "[email removed]",
      "allowFrom": ["[email removed]"]
    }
  }
}

Caution

consentGranted must be true to allow mailbox access — it's a deliberate safety gate. Set "autoReplyEnabled": false if you only want nanobot to read/analyze mail without sending automatic replies. For Gmail, create a dedicated account and an App Password.

5.7 Other channels

DingTalk (Stream mode), QQ / Napcat, WeChat (Weixin), WeCom, Matrix (Element, with E2EE), Microsoft Teams, Mochat, and Signal are all supported with the same channels.<name> pattern. Each one's exact fields and setup steps are in the Admin Guide's Channel Reference.

Important

Access control matters. Since v0.1.4.post4, an empty allowFrom denies everyone. Set ["*"] to allow all users, or list specific user IDs. If you don't set allowFrom, unapproved users who DM the bot get a pairing code instead — a safe default.


6. Models, Providers, and Web Tools

6.1 Choosing a provider and model

nanobot speaks to ~40 LLM providers, plus any OpenAI-compatible endpoint. You set a key under providers.<name> and a model under agents.defaults. The model is written as provider-prefix/model-name for gateways like OpenRouter, or just the bare model name for a pinned provider.

Popular choices:

Provider provider value Notes
OpenRouter openrouter One key, access to nearly every model (recommended)
Anthropic (Claude) anthropic Direct Claude access
OpenAI openai GPT models + Whisper voice transcription
Google Gemini gemini Direct Gemini
DeepSeek deepseek Direct DeepSeek
Groq groq Fast inference + free Whisper transcription (default)
AWS Bedrock bedrock Claude/Nova/Llama via the Converse API
Azure OpenAI azure_openai API key or Microsoft Entra ID auth
Local — Ollama ollama No key; apiBase: "http://localhost:11434"
Local — LM Studio lm_studio No key; OpenAI-compatible local server
Local — vLLM vllm No key; any OpenAI-compatible server
Any OpenAI-compatible API custom Point apiBase at your endpoint

Tip

Running fully local? Use Ollama, LM Studio, vLLM, OVMS, or Atomic Chat. Set "apiKey": null for servers that don't need authentication. The full provider table, OAuth providers (OpenAI Codex, GitHub Copilot), and per-provider quirks are in the Admin Guide.

Local model example (Ollama)

{
  "providers": {
    "ollama": { "apiBase": "http://localhost:11434" }
  },
  "agents": {
    "defaults": { "provider": "ollama", "model": "llama3.2" }
  }
}

Web search is on by default using DuckDuckGo (zero config, no key). To use a different backend, configure tools.web.search:

Provider Free? Config
duckduckgo (default) Yes none
searxng (self-hosted) Yes baseUrl
jina Free tier (10M tokens) apiKey
brave No apiKey
tavily No apiKey
kagi No apiKey
olostep No apiKey
volcengine Monthly quota apiKey
{
  "tools": {
    "web": {
      "search": { "provider": "brave", "apiKey": "${BRAVE_API_KEY}" }
    }
  }
}

To disable all web tools entirely, set tools.web.enable to false.

6.3 Voice messages

Voice notes from Telegram and WhatsApp are automatically transcribed with Whisper. By default the free Groq tier is used; switch to OpenAI with "transcriptionProvider": "openai" under channels, and optionally hint the language with "transcriptionLanguage": "en".

6.4 Switching models on the fly with presets

A model preset is a named, complete model configuration you can switch to at runtime with /model <preset> — without editing config.

{
  "modelPresets": {
    "fast": { "model": "openai/gpt-4.1-mini", "provider": "openai", "reasoningEffort": "low" },
    "deep": { "model": "anthropic/claude-opus-4-5", "provider": "anthropic", "reasoningEffort": "high" }
  },
  "agents": {
    "defaults": { "modelPreset": "fast", "fallbackModels": ["deep"] }
  }
}

Then in chat:

/model deep      # switch to your "deep" preset for future turns
/model default   # return to agents.defaults.*

Note

/model switching is runtime-only — it never rewrites config.json, and an in-progress turn keeps the model it started with. default is always available and means agents.defaults.*.

6.5 Automatic model fallback

agents.defaults.fallbackModels is an ordered failover chain. If your primary provider returns a retryable error (timeout, 5xx, 429 rate limit, overload, quota exhaustion) before any answer has started streaming, nanobot transparently retries with the next candidate. It does not fall back on auth errors, content refusals, or malformed requests.

6.6 Image generation

nanobot can generate and edit images through the generate_image tool. It's off by default — enable it and pick a provider:

{
  "tools": {
    "imageGeneration": {
      "enabled": true,
      "provider": "openrouter",
      "model": "openai/gpt-5.4-image-2"
    }
  }
}

In the WebUI composer, click Image Generation, choose an aspect ratio (1:1, 16:9, 9:16, 4:3, 3:4, or Auto), describe the image, and iterate ("make it warmer", "try a 16:9 version"). Supported providers include OpenRouter, MiniMax, Gemini, StepFun, Zhipu, AIHubMix, Ollama, and any OpenAI-compatible custom endpoint. Generated artifacts are stored under ~/.nanobot/media/generated/. Full per-provider details: Admin Guide.

6.7 MCP — connect external tools

nanobot is an MCP client. Connect external tool servers and the agent uses them as native tools — no code changes. The config format is compatible with Claude Desktop / Cursor, so you can paste server configs straight from any MCP README.

{
  "tools": {
    "mcpServers": {
      "filesystem": {
        "command": "npx",
        "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]
      },
      "my-remote-mcp": {
        "url": "https://example.com/mcp/",
        "headers": { "Authorization": "Bearer xxxxx" }
      }
    }
  }
}

Both stdio (command + args) and HTTP (url + optional headers) transports are supported. Tools are discovered and registered automatically on startup.


7. Access Control and Pairing

7.1 Pairing — granting access

Pairing lets people get access to your bot through a simple code exchange — no config editing.

  1. An un-approved user DMs the bot on any channel.
  2. The bot replies with a pairing code like ABCD-EFGH (valid 10 minutes) and tells them to forward it to you.
  3. You approve it:
/pairing approve ABCD-EFGH
  1. They can now chat normally.

Note

Pairing only works in DMs — unapproved users in group chats are silently ignored. This also covers an already-approved user connecting from a new channel (e.g. they were on Telegram, now setting up Discord). Use /pairing to see who's waiting and /pairing revoke <user_id> to remove someone later.

7.2 Allow everyone (open mode)

{ "channels": { "telegram": { "enabled": true, "allowFrom": ["*"] } } }

8. The WebUI

The WebUI ships inside the published wheel — no extra build step. It's a chat workbench in your browser with Thought/response timelines, live file-edit activity, model and context controls, and image generation.

1. Enable the WebSocket channel:

{ "channels": { "websocket": { "enabled": true } } }

2. Start the gateway:

nanobot gateway

3. Open it: visit http://127.0.0.1:8765.

Tip

To reach the WebUI from another device on your LAN — or from a Docker container — you must change the bind address from the default 127.0.0.1 to 0.0.0.0 and protect it with a token. See the Admin Guide's deployment and security sections.


9. Workflows & Recipes

9.1 Run a 24/7 personal assistant in Telegram

pip install nanobot-ai
nanobot onboard
# edit ~/.nanobot/config.json: add provider key + model + telegram block with allowFrom
nanobot gateway

Now message your bot from anywhere. Keep it online permanently with a systemd / launchd service (Admin Guide → Deployment).

9.2 Give the agent recurring tasks (Heartbeat)

The gateway wakes every 30 minutes and checks ~/.nanobot/workspace/HEARTBEAT.md. Any task under ## Active Tasks gets executed, and results are delivered to your most recently active chat.

## Active Tasks

- [ ] Check the weather forecast and send me a summary
- [ ] Scan my inbox for urgent emails

Note

The gateway must be running and you must have chatted with the bot at least once (so it knows which channel to deliver to). You can also just ask the agent to "add a periodic task" and it will edit HEARTBEAT.md for you.

9.3 Pursue a long-term goal

Ask the agent to hold a sustained objective and it uses its goal / long_task tools to keep working across many turns, showing visible multi-step progress. Example: "Track this stock all day and message me if it drops more than 3%."

9.4 Use nanobot from your own code (Python SDK)

No CLI, no gateway — just a library:

import asyncio
from nanobot import Nanobot

async def main():
    bot = Nanobot.from_config()                 # reuses ~/.nanobot/config.json
    result = await bot.run("What time is it in Tokyo?")
    print(result.content)

asyncio.run(main())

Isolate conversations with session_key, target a specific workspace, and attach observability hooks:

bot = Nanobot.from_config(workspace="/my/project")
await bot.run("hi", session_key="user-alice")

The full hook lifecycle (before_iteration, on_stream, before_execute_tools, finalize_content, …) is documented in the Admin Guide.

9.5 Call nanobot like the OpenAI API

pip install "nanobot-ai[api]"
nanobot serve            # binds 127.0.0.1:8900 by default
curl http://127.0.0.1:8900/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"messages":[{"role":"user","content":"hi"}],"session_id":"my-session"}'
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:8900/v1", api_key="dummy")
resp = client.chat.completions.create(
    model="MiniMax-M2.7",
    messages=[{"role": "user", "content": "hi"}],
    extra_body={"session_id": "my-session"},
)
print(resp.choices[0].message.content)

Note

Each request must contain exactly one user message. Pass session_id to isolate conversations, set stream=true for SSE streaming, and attach files (images, PDF, Word, Excel, PowerPoint) via base64 or multipart/form-data up to 10 MB each. Endpoints: GET /health, GET /v1/models, POST /v1/chat/completions.

9.6 Run multiple isolated bots

Point --config at separate config files to run independent instances (e.g. one Telegram bot and one Discord bot) with their own workspaces, memory, and cron jobs:

nanobot onboard --config ~/.nanobot-telegram/config.json --workspace ~/.nanobot-telegram/workspace
nanobot gateway --config ~/.nanobot-telegram/config.json
nanobot gateway --config ~/.nanobot-discord/config.json --port 18792

Each instance must use a different port if they run at the same time.


10. How nanobot Remembers (Memory)

nanobot keeps memory in layers so conversations stay fast in the moment but reflective over time. You don't have to manage any of it, but you can inspect and steer it.

File (in your workspace) Role
SOUL.md The bot's long-term voice and communication style
USER.md Stable knowledge about you and your preferences
memory/MEMORY.md Durable project facts and decisions
memory/history.jsonl Append-only archive of compressed past turns

Two stages keep it tidy:

  • Consolidator — when a conversation grows large, it summarizes the oldest safe slice and appends it to history.jsonl.
  • Dream — a slower, scheduled pass that reads new history plus your durable files and makes the smallest honest edit to keep SOUL.md / USER.md / MEMORY.md coherent. Every change is version-controlled.

Inspect and steer memory from chat:

/dream                 # consolidate now
/dream-log             # see the latest memory change
/dream-restore         # list recent versions
/dream-restore <sha>   # roll memory back to before a change

Tip

Because Dream changes are versioned, memory is auditable — you can always see what changed and restore a previous state.


11. Troubleshooting

Error: Environment variable 'NAME' referenced in config is not set

Cause: Your config.json uses a ${NAME} placeholder but that environment variable isn't set in the gateway's environment. nanobot fails fast at startup rather than running with a missing secret. Solution: Export the variable before launching (export NAME=...), use a --env-file with Docker, or put the literal value in config. Prevention: ${VAR} is not shell-style default syntax — there is no fallback. Make sure every referenced variable exists in the process environment.

Error: Permission denied on ~/.nanobot (Docker)

Cause: The container runs as user nanobot (UID 1000) but your mounted ~/.nanobot is owned by a different UID. Solution: sudo chown -R 1000:1000 ~/.nanobot, or run with --user $(id -u):$(id -g) (Podman: --userns=keep-id). Prevention: Always mount your host config to /home/nanobot/.nanobot, not /root/.nanobot.

The WebUI / a port isn't reachable from another device or Docker

Cause: The gateway and WebSocket channel default to host: "127.0.0.1" (loopback only). Docker -p forwarding and LAN clients cannot reach loopback. Solution: Set both gateway.host and channels.websocket.host to "0.0.0.0" in config — and add a token or tokenIssueSecret, because the WebSocket channel refuses to start on 0.0.0.0 without one. Prevention: Treat 0.0.0.0 as "exposed" and always pair it with authentication.

Unapproved users can't talk to the bot / everyone is denied

Cause: Since v0.1.4.post4, an empty allowFrom denies all users by default. Solution: Set "allowFrom": ["*"] to allow everyone, or list specific user IDs. Or leave it unset and approve people via pairing. Prevention: Decide per channel whether you want open access, an allow-list, or pairing-only.

generate_image is not available

Cause: Image generation is disabled by default. Solution: Set tools.imageGeneration.enabled to true, configure a provider, and restart the gateway.

Missing API key error for image generation

Cause: No providers.<provider>.apiKey, or a ${VAR} reference that the gateway process can't see. Solution: Set the provider key; if using ${VAR_NAME}, confirm the variable is visible to the gateway process.

WhatsApp stopped working after upgrading nanobot

Cause: The local WhatsApp bridge is not rebuilt on upgrade. Solution: rm -rf ~/.nanobot/bridge && nanobot channels login whatsapp.

Matrix channel fails to start on Windows

Cause: matrix-nio[e2e] (via python-olm) has no Windows wheel and is skipped on Windows. Solution: Use macOS, Linux, or WSL2 for the Matrix channel.

Feishu replies aren't streaming

Cause: The Feishu app lacks the cardkit:card:write permission. Solution: Add the permission and publish a new app version, or set "streaming": false under channels.feishu to use normal cards.

The agent isn't searching the web

Cause: Web tools are disabled (tools.web.enable: false), or the configured search provider has no/invalid key. Solution: Ensure tools.web.enable is true; the default duckduckgo provider needs no key. For paid providers, verify the API key.

Web fetch fails on Cloudflare / proof-of-work pages

Cause: The default Jina Reader path can be blocked by anti-bot challenges. Solution: Set a random user agent and disable Jina Reader:

{ "tools": { "web": { "userAgent": "Not-A-Browser", "fetch": { "useJinaReader": false } } } }

Replies fail to deliver: Failed to send to {channel} after N attempts

Cause: Persistent delivery failure — invalid token, revoked access, or an unreachable channel. nanobot retries (default 3 attempts with backoff) before giving up. Solution: Check the channel's token/credentials and that the platform is reachable. Watch logs for this line to spot the failing channel.


12. FAQ

Q: What's the difference between nanobot agent, gateway, and serve? agent is a local terminal chat (one-shot or interactive). gateway is the always-on service that connects your chat channels and serves the WebUI. serve exposes a minimal OpenAI-compatible HTTP API. They're independent processes that share config + workspace.

Q: Do I need an API key? For hosted models, yes. For local models (Ollama, LM Studio, vLLM, OVMS, Atomic Chat) you can set "apiKey": null and pay nothing.

Q: Where is my data stored? Everything lives under ~/.nanobot/ — config.json, your workspace/ (memory, sessions, skills), media/, and channel auth state. Chat history is stored locally, not in any cloud.

Q: Can one bot run on many chat apps at once? Yes. Enable as many channels as you like; a single nanobot gateway serves all of them. Enable agents.defaults.unifiedSession if you want them to share one conversation across devices.

Q: How do I switch models without restarting? Define modelPresets, then use /model <preset> in chat. It's runtime-only and doesn't touch your config file.

Q: How do I keep my API keys out of config.json? Use ${VAR_NAME} references anywhere in config; nanobot resolves them from environment variables at startup and never writes the resolved value back to disk.

Q: Is it safe to let the agent run shell commands? The exec tool blocks obviously dangerous patterns, but for real isolation enable the bubblewrap sandbox (tools.exec.sandbox: "bwrap", Linux only) and tools.restrictToWorkspace. See the Admin Guide's security section before exposing the agent to untrusted input.

Q: Can I add my own chat channel or tool? Yes — channels and tools are discovered via Python entry points. See the Admin Guide's extension guide (and docs/channel-plugin-guide.md).

Q: How do I run multiple bots on one machine? Use --config (and optionally --workspace) to point each instance at its own files, with a different port per instance.

Q: Does nanobot support voice? Yes — voice messages on Telegram and WhatsApp are auto-transcribed with Whisper (Groq free tier by default).

Q: What is "Dream"? A scheduled memory-consolidation pass that distills your conversation history into durable, versioned long-term memory files. Trigger it manually with /dream.

Q: Where's the official documentation? Repo docs ship in docs/ and the stable docs live at nanobot.wiki.


13. Quick Reference

Shell commands

Command Purpose
nanobot onboard [--wizard] Initialize/refresh config + workspace
nanobot agent [-m "..."] Local chat (interactive or one-shot)
nanobot gateway Start the channel + WebUI service
nanobot serve Start the OpenAI-compatible API
nanobot status Show status
nanobot provider login <name> OAuth login (OpenAI Codex, GitHub Copilot)
nanobot channels login <channel> Interactive channel login (QR, etc.)
nanobot channels status Show channel status
nanobot --version Show installed version

Common flags

Flag Applies to Effect
-c, --config <path> most commands Use a specific config file
-w, --workspace <path> agent, gateway, onboard Use a specific workspace
-m "..." agent One-shot message
--no-markdown agent Plain-text replies
--logs agent Show runtime logs
--port <n> gateway Override the gateway port

Key files & ports

Item Default
Config ~/.nanobot/config.json
Workspace ~/.nanobot/workspace/
Media / generated images ~/.nanobot/media/
Gateway health endpoint 127.0.0.1:18790 (GET /health)
WebUI / WebSocket 127.0.0.1:8765
OpenAI-compatible API 127.0.0.1:8900