picobot: a 9MB single-binary AI agent with channels and memory
A lightweight self-hosted bot in a single binary, written in Go.
At a glance
- What is it?
- picobot is a Go implementation of a personal agent, distributed as one roughly 9MB binary with no Python or Node runtime, built around a chat hub and an agent loop with sixteen built-in tools, persistent memory, a skills system and Telegram, Discord, Slack and WhatsApp channels. The stated target is a five dollar VPS or a Raspberry Pi.
- Who is it for?
- Adopt picobot if you want a personal agent you can run on a small machine without a container runtime, a Python environment or a large model of your own, and you are comfortable pointing it at an OpenAI-compatible endpoint. Do not adopt it as a multi-user platform, because the design is a single instance with one config and one memory directory, and do not expect the lite builds to be feature complete without checking which channels they carry.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 36 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The pitch is the size
picobot describes itself as the AI agent that runs anywhere, even on a five dollar VPS, and the argument is made with a comparison table against what the README calls typical agent frameworks.
The numbers are specific. The binary is about 9MB against 200MB or more for a Python install with its dependencies. The Docker image is about 29MB on Alpine against 500MB to over a gigabyte. Cold start is instant against 5 to 30 seconds. Idle RAM is about 10MB against 200MB to a gigabyte. And the dependency list is zero, a single binary, against Python, pip, a virtual environment and Node.
The README puts it plainly: no Python, no Node, no 500MB container, just one Go binary and a config file. The stated targets are a five dollar per month VPS, a Raspberry Pi, and even an old Android phone running Termux.
That framing also explains the positioning. The project is explicitly inspired by OpenClaw and is pitched at people who like the idea of an open source agent but not the footprint. Whether the footprint matters to you depends on where you are running it, but for a machine you own, an agent that starts instantly and sits in ten megabytes of memory is a genuinely different operational profile from one that needs a runtime stack and a container image.
The project is written in Go, licensed under MIT, and the current release is v0.3.0 from 2026-09-17, with v0.2.0 from 2026-03-18 and v0.1.10 from 2026-03-14 before it. The last push to the repository was the same day as the v0.3.0 tag.
A chat hub and an agent loop
The architecture section is short, and the description is of a deliberately simple pipeline.
Messages flow through a Chat Hub, which handles the inbound and outbound channels, into the Agent Loop. The Agent Loop builds context from memory, sessions and skills, calls the LLM through an OpenAI-compatible API, executes tools such as filesystem, exec and web, and then sends the replies back through the hub.
That is the whole design, and the value of the diagram is in what it leaves out. There is no message broker, no separate worker tier, no queue, no database server. The hub and the loop are in the same process, which is exactly why a single binary is possible.
The channel is a term for a communication channel, and the README is explicit that this means Telegram, Discord, Slack and WhatsApp among others. The loop is the same regardless of which side a message arrived from, so adding a channel adds a transport rather than a second implementation of the agent.
The LLM call goes through an OpenAI-compatible API, and the Docker examples configure it with OPENAI_API_KEY, OPENAI_API_BASE pointing at an OpenRouter endpoint and PICOBOT_MODEL set to a free model on that provider. The base URL and the model are environment variables, so the agent is not tied to a single vendor, and the config example shows a hosted free model rather than a paid one, which tells you what the author's own usage looks like.
Sixteen tools, and MCP for the rest
The tools table is the substance of the agent, and there are sixteen of them, grouped by what they touch.
The action tools are filesystem, which reads, writes and lists files, exec, which runs shell commands, web, which fetches web pages and APIs, web_search, which searches through DuckDuckGo, message, which sends messages to channels, spawn, which launches background subagents, and cron, which schedules recurring tasks.
Then there are the memory tools: write_memory to persist information across sessions, list_memory to list all memory files, read_memory to read one, edit_memory to find and replace text in a file, and delete_memory to remove a daily memory file.
And the skill tools: create_skill to create reusable skill packages, list_skills, read_skill and delete_skill.
The rationale for splitting memory and skills into separate tool families is that they behave differently. Memory is a running log the agent appends to, and skills are knowledge packages it consults, and the agent needs different verbs on each.
Beyond the built-ins, MCP servers extend the agent with any MCP-compliant server, launched through npx, uvx, a plain binary, docker run, or an HTTP endpoint. The tools are registered automatically at startup under the name mcp_{server}_{tool}, so an MCP server's tools appear in the same list as the built-in ones and the agent does not need to know where they came from. The configuration is documented in the MCP servers section of the configuration reference.
Memory that is files, and skills that are markdown
The memory model is three ideas rather than one. There are daily notes, which are auto-organised by date, a long-term memory that survives restarts, and ranked recall, which retrieves the most relevant memories for each query.
The CLI exposes two of those directly:
picobot memory recent --days 7 # what happened this week?
picobot memory rank -q "meeting" # find relevant memoriesThe recent command is a time window over the daily notes, and the rank command is a relevance search across the memory, which is the part that matters once the memory grows past a few days of notes.
Skills are simpler and deliberately more transparent. The README describes them as modular knowledge packages that extend the agent, and the demonstration is a conversation: you ask the agent to create a skill for checking weather using curl wttr.in, and it reports that it created the skill named weather and will use it from now on. The storage is plain markdown files in the workspace skills directory, and the README says explicitly that you can create them via the agent or manually.
That last point is the design decision worth noting. Skills are not opaque blobs the tool produced; they are files you can read, edit, diff and keep in version control, which means a skill is reviewable in the same way as any other piece of configuration you keep next to a project.
Three ways to run it
The quick start is thirty seconds, and there are three routes.
The first is a single container:
docker run -d --name picobot \
-e OPENAI_API_KEY="your-key" \
-e OPENAI_API_BASE="https://openrouter.ai/api/v1" \
-e PICOBOT_MODEL="openrouter/free" \
-e PICOBOT_MAX_TOKENS=8192 \
-e PICOBOT_MAX_TOOL_ITERATIONS=100 \
-e TELEGRAM_BOT_TOKEN="your-telegram-token" \
-v ./picobot-data:/home/picobot/.picobot \
--restart unless-stopped \
louisho5/picobot:latestThe volume is the part to keep, because all config, memory and skills are persisted in that directory on the host. The two PICOBOT_ variables set the token budget and how many tool iterations the agent may take in one turn, which is the knob that stops a confused agent from looping.
The second route is Docker Compose, with the same environment expressed as a service and the same volume mapping:
services:
picobot:
image: louisho5/picobot:latest
container_name: picobot
restart: unless-stopped
environment:
- OPENAI_API_KEY=your-key
- OPENAI_API_BASE=https://openrouter.ai/api/v1
- PICOBOT_MODEL=openrouter/free
- PICOBOT_MAX_TOKENS=8192
- PICOBOT_MAX_TOOL_ITERATIONS=100
- TELEGRAM_BOT_TOKEN=your-telegram-token
- TELEGRAM_ALLOW_FROM=your-user-id
volumes:
- ./picobot-data:/home/picobot/.picobotThe third route is from source, and the subcommands show the shape of the tool:
go build -o picobot ./cmd/picobot
./picobot onboard # creates ~/.picobot config + workspace
./picobot agent -m "Hello!" # single-shot query
./picobot channels login # login to channels (Telegram, Discord, Slack, WhatsApp)
./picobot gateway # long-running mode with TelegramOnboard creates the config and the workspace, agent is a one-shot query, channels login handles the channel authentication, and gateway is the long-running mode.
The channel setups, and the ones that need attention
Each channel has its own setup, and the README documents all of them in the same shape.
Telegram is the quickest. You message BotFather with /newbot, copy the token, add it to the config or pass it as TELEGRAM_BOT_TOKEN, and start the gateway. The compose example also sets TELEGRAM_ALLOW_FROM to a user id, which is the setting that decides who the bot answers. Without it, a bot with a model and shell access behind it is a liability rather than a tool.
Discord takes a little more. You create an application and a bot in the Discord Developer Portal, enable the Message Content Intent in the bot settings, copy the bot token and add it to the config under channels.discord in the config file. The bot responds when mentioned in servers, or to all messages in direct messages.
Slack goes through Socket Mode, which is the modern way to avoid a public endpoint. You create an app in the Slack API apps page, enable Socket Mode and generate an app-level token, add the bot token scopes for app_mentions:read, chat:write, channels:history, groups:history, im:history, mpim:history and files:read, enable Event Subscriptions for app_mention and message.im, install the app to your workspace and copy the bot token, then add it to the config under channels.slack.
The detailed walkthroughs for BotFather and for the Discord bot are in the startup guide, HOW_TO_START.md, which is where to go when a channel does not connect and you need the exact steps rather than the summary.
The dependency list, the lite builds, and a module path to fix
The go.mod is short, and it explains what the binary actually contains. There is spf13/cobra for the command line, discordgo for Discord, slack-go for Slack, whatsmeow for WhatsApp, modernc.org/sqlite for the database, mdp/qrterminal for the terminal QR codes the channel logins use, and a long list of indirect dependencies that are what makes those two chat libraries and the WhatsApp one work.
The WhatsApp dependency is the heaviest thing in the tree, because whatsmeow brings its own cryptography and networking stack. That is presumably what the lite build variants are for.
The Makefile shows the release matrix: linux_amd64, linux_arm64 and mac_arm64, each built with CGO_ENABLED=0 and the -s -w linker flags, and then a parallel set of lite targets built with the lite build tag, and a build-all target that produces all six. A static binary with CGO disabled and the symbol table stripped is exactly how you get a 9MB artefact that runs on a Raspberry Pi and in an Alpine container, and it also means the SQLite dependency has to be the pure Go modernc build rather than the cgo one.
One detail to flag if you plan to build from source. The module path in go.mod is github.com/local/picobot, while the repository is louisho5/picobot. The build commands in the README work regardless, since the module path is only used for import paths inside the module, but it is the sort of leftover that trips up tooling that resolves the module remotely.
The rest of the repository is cmd/ for the entry point, internal/ for the implementation, embeds/ for the embedded assets, docker/ for the image build, docs/ for the documentation including CONFIG.md and HOW_TO_START.md, a golangci-lint configuration, and a Makefile. The Docker Hub pulls badge and the docker-publish workflow badge are in the README, so the image is built automatically.
Editorial conclusion
Adopt picobot if you want a personal agent you can run on a small machine without a container runtime, a Python environment or a large model of your own, and you are comfortable pointing it at an OpenAI-compatible endpoint. Do not adopt it as a multi-user platform, because the design is a single instance with one config and one memory directory, and do not expect the lite builds to be feature complete without checking which channels they carry. Before you start, set the model and the API base, mount the data directory so memory and skills survive a restart, set TELEGRAM_ALLOW_FROM to your own user id so the bot does not answer strangers, and read the CONFIG.md section on MCP servers if you plan to add tools.
Frequently asked questions
How small is picobot and what does it need to run?
The README gives about 9MB for the binary, about 29MB for the Docker image on Alpine, instant cold start and about 10MB of idle RAM, against 200MB to a gigabyte for typical Python based agent frameworks. It runs on a five dollar per month VPS, a Raspberry Pi, or an old Android phone via Termux, and needs no Python or Node runtime.
Which tools does the picobot agent have built in?
Sixteen: filesystem, exec, web, web_search, message, spawn and cron for actions, write_memory, list_memory, read_memory, edit_memory and delete_memory for memory, and create_skill, list_skills, read_skill and delete_skill for skills. Additional tools come from MCP servers, which are registered automatically as mcp_{server}_{tool} at startup.
How does picobot run from source?
Run go build -o picobot ./cmd/picobot, then ./picobot onboard to create the config and workspace, ./picobot agent -m "Hello!" for a single-shot query, ./picobot channels login to authenticate the channels, and ./picobot gateway for the long-running mode. The Makefile also has cross-build targets for Linux and macOS with a lite build tag.
How does picobot store memory and skills?
Memory is organised as daily notes auto-organised by date plus a long-term memory that survives restarts, with ranked recall retrieving the most relevant entries for each query, and the CLI exposes picobot memory recent --days 7 and picobot memory rank. Skills are markdown files in the workspace skills directory that you can create through the agent or by hand.
Which chat channels does picobot support?
Telegram, Discord, Slack and WhatsApp. Telegram needs a BotFather token, Discord needs a bot with the Message Content Intent enabled, Slack connects through Socket Mode with the app_mention and message.im event subscriptions, and each channel is configured under channels in the config file with the token supplied.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/louisho5-picobot)Was this useful?