open source / self-hosted / MIT / built on pi durable
Durable agents for Slack, Discord, and your terminal.
Run AI agents on your Claude, ChatGPT, or Copilot subscription, or on any API key, and talk to them wherever your team already works. Every turn and tool call goes on the record before you see it, so work survives crashes, restarts, and deploys.
- 1One inbox for Slack, Discord, Telegram, webhooks, and the web.
- 2Asked in a Slack thread; @coder was picked by mention.
- 3Each agent runs its own model, here Claude Opus on a subscription.
- 4Every tool call is committed to SQLite before it is shown.
- 5@scout answered through a durable child conversation.
- 06
- channels: Slack, Discord, Telegram, webhooks, web, terminal
- 40+
- model providers, with subscription sign-in for Claude, ChatGPT, Copilot, and more
- 05
- agent skills: memory, web, delegate, schedule, workspace
- 01
- service and one volume to self-host the whole thing
- 00
- completed steps repeated after a crash or redeploy
Crash it mid-answer. It picks up where it stopped.
soloagent is built on Pi Durable. Every model turn, tool call, delegation, and reminder is a durable step in SQLite. A deploy, a crash, or a container restart is a pause, not a reset.
- Commit before show
- Every model turn and tool call is written to storage before Slack or the dashboard shows it. Streaming text is saved as it arrives.
- Resume, don't restart
- An interrupted model request is retried. Finished tool calls never run twice.
- Timers that outlive the process
- A reminder set for Friday sleeps in storage and fires on Friday, across any number of deploys.
- 1041inputslack · maya → @coder
- 1042turn@coder · claude-opus-5-5
- 1043toolbash · tail ci/build-4812.log
- 1044resultexit 0 · 7 lines
- process restarted · deploy v0.1.1
- 1045resumegeneration · attempt 2
- 1046toolask_agent → @scout
- 1047turn@scout · gpt-6-sol
- 1048answer→ #eng-deploys thread
- 1049sleepreminder · until 09:00 tomorrow
Illustrative. Steps 1041 to 1044 are not repeated after the restart.
Use the subscriptions you already pay for.
Model access runs through @earendil-works/pi-ai. Sign in with a consumer plan or paste an API key, then give each agent its own model and thinking level: coding on Claude, research on ChatGPT, triage on something cheap.
Sign in with your account
- Claude Pro & Maxoauth
- ChatGPT Plus & Prooauth
- GitHub Copilotoauth
- SuperGrok & X Premiumoauth
- OpenRouteroauth
Or bring an API key
Anthropic, OpenAI, Google Gemini, Mistral, Groq, DeepSeek, xAI, Amazon Bedrock, Azure OpenAI, Vercel AI Gateway, Together, Fireworks, Cerebras, Hugging Face, Moonshot, Z.AI, and many more.
Sealed at rest. Keys and tokens are encrypted with AES-256-GCM under a secret you control, refresh automatically, and never reach the browser. A built-in demo model works before you connect anything.
Product names are trademarks of their respective owners. Subscription sign-in is subject to each provider's terms; some bill third-party usage separately from plan limits.
One set of agents, every place your team talks.
Connect a platform once and every agent is reachable there. In chat apps, replies stream in live by editing a placeholder message while the agent works.
| # | Channel | Connects with | What it does |
|---|---|---|---|
| C1 | Slack | Socket Mode. No public URL needed. | Answers mentions in a thread, and direct messages. |
| C2 | Discord | Bot token, Message Content intent. | Mentions, replies, and DMs. Each Discord thread is its own conversation. |
| C3 | Telegram | Bot token from @BotFather. | Direct messages, group mentions, and forum topics. |
| C4 | Webhooks | Shared secret on POST /api/hooks/:id. | Answers in the response, or posts to a callback_url. |
| C5 | Web | Built in, same process. | Chat, agents, sign-ins, connections, task graph, and usage. |
| C6 | Terminal | Embedded, or soloagent connect. | Full-screen TUI, plus soloagent ask for scripts and pipes. |
Routing that reads like chat.
Start with @coder or coder: to address an agent; otherwise the channel's assigned agent answers. Send another message while it works and you steer the run in progress instead of queuing behind it.
maya@coder why did last night's deploy fail?
mayaonly check the API service steers the run
samscout: what changed in Postgres 17.2?
sam!agents !reset !stop !help
A dashboard for the team. A terminal for you.
Both talk to the same server over the same API. The terminal UI runs its own private server when you're not connected to one.


Agents with skills, not just prompts.
Give each agent a name, a handle, instructions, a model, and only the skills it needs. Skills are Pi Durable extensions, so their work is on the record too.
memoryremember · recall · forgetKeeps people, preferences, and decisions across every conversation.
webweb_fetch · web_searchReads pages and APIs as clean text, and searches the web.
delegateask_agentHands a task to another agent through a durable child conversation.
scheduleschedule_reminderReminders and follow-ups that sleep in storage and fire after restarts.
workspaceread · write · edit · bashFiles and shell, starting in the agent's own folder on the server. Not a sandbox, so it's off by default.
Scriptable from end to end.
Everything the dashboard and terminal do goes through a documented HTTP and WebSocket API. Use the typed TypeScript client, call it from CI, or embed the runtime in your own service.
- REST for agents, threads, providers, connectors, schedules
- WebSocket stream of messages, partial answers, and tool progress
- One bearer token per deployment
# ask once, print the answer
soloagent ask --agent ops \
"Summarize today's incidents"
# pipe anything in
git diff --staged | soloagent ask - --agent coder
# use a remote server from now on
soloagent connect https://solo.example.com \
--token $SOLOAGENT_TOKEN
// packages/client in the repo; not on npm yet
import { SoloClient } from "@soloagent/client";
const solo = new SoloClient({
baseUrl: "https://solo.example.com",
token: process.env.SOLOAGENT_TOKEN,
});
const thread = await solo.createThread({ agentId: "coder" });
const { answer } = await solo.ask(thread.id, "Why did CI fail?");
// stream partial answers and tool progress
solo.connect().subscribe(thread.id);
# from anything that can send a request
curl -X POST $SOLO/api/hooks/$HOOK_ID \
-H "x-solo-secret: $HOOK_SECRET" \
-H "content-type: application/json" \
-d '{"text": "@coder what changed in the last deploy?",
"thread": "deploys", "user": "ci"}'
# → {"thread":"deploys","status":"done","answer":"…"}
Your laptop, your server, or one click.
soloagent is one Node.js process with one data directory. Try it locally in a minute, then run the same thing wherever your team can reach it: a Docker host, Railway, Render, Fly.io, or a plain Linux box.
curl -fsSL https://soloagent.dev/install.sh | sh
# then
soloagent # terminal UI with a private local server
soloagent serve # web dashboard on localhost:7420
# Windows, or no installer: npm does the same
npm i -g --allow-remote=root \
https://github.com/nearbycoder/soloagent.dev/releases/latest/download/soloagent.tgz
docker run -d --name soloagent -p 7420:7420 \
-v soloagent:/data ghcr.io/nearbycoder/soloagent.dev
docker logs soloagent | grep token
# or with compose (VPS, NAS, Coolify, Dokploy)
curl -fsSLO https://raw.githubusercontent.com/nearbycoder/soloagent.dev/main/docker-compose.yml
docker compose up -d
→ railway.com/new
# 1. GitHub Repository → your fork, or paste
# github.com/nearbycoder/soloagent.dev → Deploy Repo
# 2. Add a volume mounted at /data
# 3. Set SOLOAGENT_TOKEN and SOLOAGENT_SECRET, generate a domain
# or from the CLI, in a clone of the repo
railway init && railway up
railway volume add --mount-path /data
railway domain
# one click: a Docker service, a 1 GB disk at /data,
# a health check, and a generated token and secret
→ render.com/deploy?repo=github.com/nearbycoder/soloagent.dev
# disks need a paid instance (Starter or above)
git clone https://github.com/nearbycoder/soloagent.dev && cd soloagent.dev
fly launch --copy-config --no-deploy
fly volumes create soloagent_data --size 1
fly secrets set SOLOAGENT_TOKEN=$(openssl rand -base64 32) \
SOLOAGENT_SECRET=$(openssl rand -base64 32)
fly deploy
- Your machineinstaller · npm · npx
- Any Docker hostamd64 · arm64
- Railwayrepo + volume
- Renderone-click blueprint
- Fly.iofly.toml
- Linux serversystemd unit
What it needs. A long-running process, a persistent directory, and a port. Serverless platforms like Vercel functions or Cloudflare Workers can't run it.
- Is it free?
- Yes. soloagent is MIT-licensed and self-hosted. You pay your model provider and your host, nothing else.
- Can I really use my Claude or ChatGPT subscription?
- Yes, through the same OAuth sign-in flows Pi uses. Check each provider's terms; Anthropic, for example, bills third-party usage as extra usage rather than against plan limits.
- What happens if the server restarts mid-answer?
- The run resumes from its last committed step. Completed tool calls are not repeated, and an interrupted model request is retried.
- Do I need a public URL for Slack?
- No. Slack uses Socket Mode, and Discord and Telegram connect outbound too. A domain is only needed for the dashboard, webhooks, and remote terminal access.
- Where is my data stored?
- In two SQLite databases in your data directory. Nothing leaves your server except requests to the model providers you configure.
- What is Pi?
- Earendil's open-source agent toolkit. soloagent uses
pi-aifor models,pi-durablefor durable execution, andpi-tuifor the terminal UI.