The Problem
Personal AI assistants such as Clawdbot are enormous (430k+ lines of code), which makes them hard to read, modify, and extend for research. nanobot solves this by delivering the core agent loop, tooling, and multi-channel chat integration in roughly 4,000 lines of Python, so a developer can trace the whole system in an afternoon.
What This Does
nanobot is a lightweight personal AI assistant. The Python core in nanobot/ handles the agent loop (nanobot/agent/loop.py), tool execution (nanobot/agent/tools/), provider abstraction via LiteLLM (nanobot/providers/litellm_provider.py), cron scheduling (nanobot/cron/service.py), session memory (nanobot/session/manager.py), and chat channels for Discord, Telegram, Feishu, DingTalk, and WhatsApp. A separate TypeScript bridge/ package handles WhatsApp transport. The repo also ships skill definitions (nanobot/skills/) and a Dockerfile.
How It Is Wired
Execution starts at nanobot/__main__.py, which routes through nanobot/cli/commands.py into the agent loop's run() (nanobot/agent/loop.py:110), which reaches 67 functions. From there start_all in nanobot/channels/manager.py dispatches outbound messages over the network via channel.send — two hops from the entry point to a socket. The filesystem path is similar: execute → _add_job → _load_store, which reads store_path directly.
Everything routes through nanobot/bus/events.py — 13 modules import it — making it the highest-blast-radius hub; churn there breaks a third of the codebase. _load_store is called from 7 places, _now_ms and ensure_dir from 6 each, so changes to those ripple widely. The module graph resolves 117 import edges with zero circular dependencies, which keeps the architecture navigable.
How To Use It
git clone https://github.com/moses-y/nanobot
cd nanobot
pip install -e .
Configuration lives in nanobot/config/schema.py; providers and API keys are resolved there. The Dockerfile builds a container image. The README documents a uv-based install path as well. No CI workflow or lockfile exists, so builds are not reproducible as shipped.
Real-World Use
A developer runs nanobot as a 24/7 assistant: it watches a chat channel, routes messages through the agent loop, calls tools (filesystem, shell, web, cron), and schedules recurring jobs via nanobot/cron/service.py — e.g., a daily market-analysis task that posts results back to Discord or Feishu. The cron store persists to disk through _load_store/_save_store, and session history is kept per-user in nanobot/session/manager.py.
Code Health & Issues
Static analysis found 25 findings (2 high, 23 medium) across 5 kinds. High: deep nesting (max indentation depth 6 in nanobot/bus/queue.py, nanobot/session/manager.py, nanobot/agent/subagent.py) and duplicated 6-line blocks across agent/loop.py, agent/subagent.py, and both provider files. Medium: broad exception handling in 6 spots, high branching density in agent/skills.py, and the bus/events.py hub.
SDLC gaps: no CI workflow, no lockfile beside bridge/package.json, no Docker build gate, no Dependabot, unpinned base image in the Dockerfile, 3 GIFs over 5MB in case/, no non-root USER in the image, and a test suite of 1 file against 52 source files.
The Bottom Line
nanobot is a genuinely small, readable agent core with clean module boundaries and no circular imports — a good base for research or a self-hosted personal assistant. It ships without CI, lockfiles, or meaningful tests, so treat it as a starting point and add those gates before trusting it in production.