AI coworkers have moved beyond command-line chat bubbles. pi-durable-bot, nicknamed Pots, positions itself as an open-source alternative to closed products like Grok Bot, Claude Tag, and Meta Muse. Where those products run on someone else's computer with someone else's model, Pots installs on your machine, runs the model you choose, and connects to the channels your team already uses.
The comparison table makes the difference immediate. Source code: open, MIT-licensed for Pots; closed for every named competitor. Where it runs: your server, your VM, your office box—versus each vendor's cloud. Model choice: any subscription, 40+ API providers, or a local model through Ollama, LM Studio, or llama.cpp. Your data stays in each bot's folder, not sent to xAI, OpenAI, Anthropic, or Meta. Custom work: change the code, add tools, connect your own systems. The other products lock you into what the vendor allows.
Pots speaks in five plain words: channel, place, thread, message, person. Platform details live inside one adapter per platform. Slack, Discord, and Telegram work today; Teams or email require only another adapter, not a rewrite. One bot can inhabit many channels and maintain the same persona everywhere.
What a real coworker does differently
Most AI bots are a command line with a chat bubble. You @ them, they answer, they forget. A real coworker works differently.
| A chat bot | pi-durable-bot | |
|---|---|---|
| What it sees | The message that mentions it | Everything in the places it was invited to: chats, DMs, emails, events, pages it watches |
| When it acts | When you @ it | When it decides it should. It can also answer when you @ it |
| What it remembers | This thread, maybe | One long memory across every channel, kept on disk |
| How it works | Calls the tools someone wired in | Writes and runs its own code on its own computer |
| What happens later | Nothing | It sets its own reminders and comes back |
| After a crash | Starts over, or sends twice | Picks up where it stopped. Never sends the same message twice (on Telegram it can, see why) |
Every message in every place you invite it to lands in one inbox: channel messages that never mention it, edits, deletions, reactions, people joining, and its own messages. It keeps all of it in a local SQLite log and reads that log with SQL whenever it needs context. Nothing is thrown away when a conversation gets long.
It is woken in three ways, the same three ways a person notices work.
| Like a coworker who... | How | |
|---|---|---|
| Someone asks | gets a message or an @ | A mention or a DM wakes it at once |
| It notices | overhears something that is their job | Every message that does not mention it comes to it too, and it decides itself whether it is about its work. You can also set a judge that reads these messages first and asks two questions: is this about me? and should I respond? It sees the bot's own list of responsibilities. The judge is a fast classifier such as TypeSafe's Jev, a local model, or the bot's own model |
| It checks in | looks around now and then, and keeps promises | It sets its own timed wakes and routines: "check Acme's pricing every Monday", "follow up at 5 pm". While no timed wake is pending, it looks around every two hours |
Being woken is not the same as speaking. Each time, the agent reads the log and decides if it should say anything, where, and when. Most of the time the right answer is to stay quiet.
It has a real machine with a shell, files, the internet, and a screen it uses like a person: the browser and the apps on it, with the mouse and keyboard. It does not wait for a plugin. It writes the script it needs, runs it, fixes it, and keeps the useful ones. That covers research, spreadsheets, reports, monitoring a web page, filling a form, or booking a flight, and also code.
Code mode
This is code mode: the agent gets a few general tools—read, write, edit, bash, screen—plus three channel actions (send, react, call), and builds the rest itself. One more tool, task, hands work to its helpers. With code mode, pi's code mode, it writes a JavaScript script that calls these tools and the tools of MCP servers in a sandbox; only what the script returns comes back to it.
screen is bash with the screen's environment, such as DISPLAY; bash does not have it. A screen runs one task at a time, as a person's desktop does: the first screen command of an agent takes the screen until its work ends, also across bots and the Pots processes of the same user on the machine. Another agent that tries then learns who has it, since when, and when it frees, and decides itself what to do. A bot that sets up its own desktop, such as an Xvfb display, writes its environment into screen in its bot.json.
One agent at a time per screen is enforced only on Linux, where plain bash has no DISPLAY or WAYLAND_DISPLAY and so cannot reach the screen. On macOS and Windows the screen does not depend on those variables, so bash can still use it; there the agents use the screen tool because the prompt tells them to.
Longer work does not keep it from talking. With its task tool the bot starts children: agents that work in the background with read, write, edit, bash, screen and code mode, without the channel actions and task, on a brief it writes for them. It answers the person first, hands the work to a child, and stays free for the next message. A child starts from an empty conversation and its brief, so the bot's own context stays small; it sees the bot's memory index as it was when it started. When a child ends, done, failed or with a question for a person, its final message comes back to the bot as a wake, exactly once, also across crashes and restarts; the bot passes on what matters, and sends the child the answer to its question. While a child works for a place, new messages there go to the bot, so it can pass them on. Its timed and fallback wakes list the children that work and how long each has run. A stopped child reports nothing and does nothing more, also when the process dies in the middle of the stop.
Children use the bot's model, or the childModel of bot.json; a change counts for new children and those that exist, also when childModel is taken out. The bot chooses each child's thinking level when it starts it: high, xhigh or max, and without a choice the childThinking of bot.json (xhigh by default). A child keeps its level for its whole life, so a new childThinking counts for new children only; a level the model does not have becomes the nearest one it has. settings.maxChildren (50 by default) caps how many work at once. pots children lists them, and pots children --stop <id> or --stop-all stops them.
Memory that survives restarts
It works like a pi session: it reads AGENTS.md and uses Agent Skills from the same places pi does, so the skills you give pi, the bot can use too. Screenshots and photos are shrunk to fit the model, as in pi.
When it speaks, it speaks like a teammate: in the right channel or thread, in its own words, with the file attached. It can reply in a thread, start a new message, DM a person, add a reaction, edit its own message, or call any other platform API.
Some things do not fit in a chat message. For a plan, a report or a dashboard, the bot writes a web page and sends a link. A page can ask, too: people choose, comment, fill in, approve or reject on it, and each answer wakes the bot at once.
- Buttons and forms in the chat. On Slack and Discord the bot sends the platform's own buttons, menus and forms; on Telegram, inline buttons. A click wakes it within a second, and a form opens at once.
- A password page for secrets. When the bot needs an API key from you, it sends a one-time link to a page of Pots' own. You type the key there. It goes into a file in the secrets folder, never into the chat, the log or a trace.
- No public address needed. The first link starts a Cloudflare Quick Tunnel, so pages work from a laptop behind a home router. For a fixed address, the bot sets up Tailscale Funnel with you, or uses your own domain.
It promises to come back, and it does. A timed wake (pots wake) wakes it once, at a time it chooses. A routine (pots routine) repeats: every 30 minutes, say, or on a cron schedule in the computer's time zone. Both live in the same database as everything else, so they survive restarts. It can also add normal cron jobs on its machine.
| Command | What it does |
|---|---|
| pots routine add <name> (--every <duration> | --cron "<expr>") (--note "<text>" | --run "<command>") [--timeout <duration>] | Add a routine, or replace the one with that name. Names are letters, digits, - and _; durations are as pots wake --in :90s, 30m, 2h, 1d |
| pots routine list | Each routine's schedule, what it does, its next time and its last run; and the fallback check-in |
| pots routine remove <name> | Remove a routine |
--note wakes the bot with the note at each time. --run makes Pots run the command at each time, in the bot's shell, folder and environment, with POTS_FROM set to the routine's name. The command decides itself whether to wake the bot with pots wake, so watching an inbox every few minutes costs no model request until there is mail.
- A run is skipped while the last run of the same routine still runs. Times missed while the gateway was stopped or the computer was off or asleep are skipped, not made up: the next run is the next time from now.
- A command runs at most 10 minutes, or its --timeout; then Pots stops it and the processes it started. When the gateway stops, it stops the commands it runs.
- Pots keeps each run's start, end, exit code and last lines of output for 7 days. A failed run (a non-zero exit code, or the timeout) wakes the bot once, with that output; later failures of the same routine do not, until one of its runs succeeds.
- A script that calls pots wake says where the wake comes from with --from <name> (letters, digits, - and _) or $POTS_FROM. The wake then tells the bot that it comes from a command on this computer, not from a person, so outside text in its note, such as an email's subject, does not read as the bot's own plan. With --id <id>, a second pots wake with the same ID gives back the first wake and sets none, as pots send --id does.
- The fallback check-in (fallbackWakeMinutes in bot.json, 120 by default) comes while no wake set with pots wake is pending. Routines do not hold it back.
Memory system
Each bot has one long conversation, across every channel. Its memory works as Claude Code's automatic memory: plain markdown files, one per memory, and an index, MEMORY.md, that the bot sees at the start of every page and that points to them. The bot saves what is worth keeping—preferences, rules, facts about people and the work, decisions—when it sees it, and after each piece of work its own model, continuing the same conversation in the background, saves what it missed. That pass never sends a message or holds up a reply; its request starts as the bot's last one did, so the provider's prompt cache serves most of it, and code lets it change nothing but the memory. Once a day, after enough changes, a dream tidies the memory up the same way. The bot's next wake says what a pass or a dream changed; as in Claude Code, a restart before that wake loses the note, not the memory. A memory file read two days or more after it changed says how old it is. Each bot has its own memory, in memory/ in its folder, and the bots of one computer share one more, in ~/.pots/memory/, for facts about you. "Remember this" and "forget that" work by talking to it; to forget is to delete the file, as in Claude Code. "settings": {"autoMemory": false} in bot.json turns the memory off.
When the context gets full, the bot decides when to turn the page: it writes notes for itself, starts a fresh context, and the notes and the memory come with it. The full message log stays on disk, so nothing is lost. Its AGENTS.md, its responsibilities and its notes are plain files it edits itself.
Built to survive crashes
Built on pi-durable, every step is journaled. Kill the process in the middle of a task and it continues after restart. Every incoming event is written to disk before it is acknowledged. Every outgoing message carries a send ID, and after a crash the bot checks whether the message already went out before it sends again.
Getting started
You need Node.js 24 or newer, on macOS, Linux or Windows (with Git for Windows).
npm install -g pi-durable-bot
pots init
pots init asks four things:
- Your bot's name.
- Its AI. Sign in with a subscription you already pay for (ChatGPT, Claude, GitHub Copilot, Grok, Kimi and more), use an API key, or point it at a local server (Ollama, LM Studio, llama.cpp).
- Who decides on group messages that do not mention it. By default the bot itself is the judge.
- Where to put bot data.
Important: the bot gets full control of the computer it runs on, with no approval step. Give it a computer or VM of its own.
For teams and developers
Pots is not affiliated with xAI, OpenAI, Anthropic, or Meta. It is MIT-licensed and runs where you put it. For developers, the implications are straightforward: you can self-host, avoid sending data to third-party clouds, and extend the bot by editing plain markdown and JavaScript files. The agent model, code mode, and journaled design mean you can build on top of it without being locked into a vendor's roadmap. Teams can run several bots on one machine, each with its own name, persona, responsibilities and memory. A bot can even edit its own definition, or create a new bot.
The incident with the hockey-wielding teenager in the first article highlighted how physical interaction contexts matter for androids deployed in human spaces. Pots addresses a different kind of context problem: an AI that must navigate persistent conversational history, memory across channels, and real-world tasks without constant human prompting. For teams deploying service robots or AI teammates, the lesson is similar—clear escalation paths, transparent reasoning, and debug logging that captures what the system one model actually decided remain essential. With Pots, that logging is built in, and the model running the agent is the one you choose, not one imposed by a vendor.
Pots is available now. npm install -g pi-durable-bot, pots init, and you have a coworker that reads every channel, decides what matters, and acts on its own computer.