<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Kwant on WebDevStation</title>
    <link>https://webdevstation.com/tags/kwant/</link>
    <description>1 article tagged Kwant — tutorials, code examples and notes from building real systems, newest first.</description>
    <generator>Hugo</generator>
    <language>en</language>
    <managingEditor>Alex</managingEditor>
    <webMaster>Alex</webMaster>
    <copyright>© 2026 WebDevStation</copyright>
    <lastBuildDate>Mon, 02 Nov 2026 21:46:34 +0100</lastBuildDate>
    <atom:link href="https://webdevstation.com/tags/kwant/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Self-Host a Team of AI Agents in One Binary</title>
      <link>https://webdevstation.com/posts/self-hosted-ai-agent-team-one-binary/</link>
      <pubDate>Mon, 02 Nov 2026 21:46:34 +0100</pubDate>
      <author>Alex</author>
      <guid isPermaLink="true">https://webdevstation.com/posts/self-hosted-ai-agent-team-one-binary/</guid>
      <description>Run a self-hosted team of AI agents on your laptop or a VPS: one binary, shared chats, @mention handoffs, routines and approvals — with Claude, Codex, Grok or your…</description>
      <content:encoded><![CDATA[<p>Most “AI agent” posts stop at the loop: send a message, run a tool, feed the result back, repeat. That loop is real — I walked through it in <a href="/posts/tool-use-in-go-agent-loop/">Tool Use in Go</a> — but a loop is not a team. A team needs more than one role, a way to hand work across roles, somewhere for state to live when you close the laptop, and a gate before a bot runs something you would rather approve yourself.</p>
<p>This post is a practical path to that shape without writing the harness yourself. The tool is <a href="https://kwant.si">kwant</a>: an open-source (AGPL-3.0), self-hosted team of AI agents packaged as one Rust binary with the web UI and SQLite database inside it. Data lives under <code>~/.kwnt</code>. It runs as a Mac app, as a Linux app (beta: <code>.deb</code> or AppImage), or on a VPS. Think of it in the same product category as xAI&rsquo;s <a href="https://x.ai/news/introducing-grok-bot">Grok Bot</a>, Anthropic&rsquo;s <a href="https://claude.com/product/claude-duet">Claude Duet</a>, and OpenAI&rsquo;s <a href="https://openai.com/index/introducing-dots/">dots</a> — persistent teammates — except kwant runs on hardware you control, not the vendor&rsquo;s cloud.</p>
<p>Install steps and feature claims below come from the <a href="https://github.com/alexsergivan/kwant">kwant README</a> and <a href="https://kwant.si/docs/quickstart">docs</a>. No invented benchmarks.</p>
<h2 id="what-a-team-means-here">What “a team” means here</h2>
<p>Three properties separate a self-hosted agent <strong>team</strong> from a single assistant chat:</p>
<ol>
<li><strong>Several bots with roles.</strong> Architect, TechLead, DevOps — each with its own instructions, voice and model (or <code>auto</code>).</li>
<li><strong>Shared context and handoffs.</strong> Bots sit in the same channel. One finishes a piece of work and <code>@mentions</code> another; the next bot sees the thread.</li>
<li><strong>Work that continues without you.</strong> Routines on a schedule, an inbox of what finished or got stuck, and approvals for the steps that should not run silently.</li>
</ol>
<p>kwant starts a fresh install with three bots in <code>#general</code> on a <code>@core-engineering</code> team: Architect, TechLead and DevOps. You can add more from presets or from scratch. In a channel, it picks the bot that fits a message and shows a one-line reason under the reply. <code>@Architect</code> addresses one bot directly; <code>@core-engineering</code> can trigger a short team discussion that ends in one summary.</p>
<p>That is the product surface this tutorial aims at. Frameworks you wire in Python or TypeScript can do pieces of the same job; they are a different category (you own the runtime, queue and UI).</p>
<h2 id="pick-an-install-path">Pick an install path</h2>
<p>You need at least one AI account eventually: the <code>claude</code> CLI (kwant has a <strong>Sign in with Claude</strong> button), a signed-in <code>codex</code> or <code>grok</code> CLI, or an Anthropic / OpenAI / xAI API key. OpenAI-compatible servers (local or remote) work too once you add them under <strong>Settings → This space → Accounts</strong>.</p>
<h3 id="path-a--develop-from-a-clone-any-os-with-rust--node">Path A — develop from a clone (any OS with Rust + Node)</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git clone https://github.com/alexsergivan/kwant.git
</span></span><span style="display:flex;"><span>cd kwant
</span></span><span style="display:flex;"><span>make run   <span style="color:#75715e"># builds the web app, then `cargo run -- serve`</span>
</span></span></code></pre></div><p>Open <a href="http://127.0.0.1:8799">http://127.0.0.1:8799</a>. On the machine that runs the process there is nothing to sign in to for the UI itself.</p>
<p><code>make run</code> is required once so <code>frontend/dist</code> exists; the binary embeds that build. The first start also installs the optional <a href="https://huggingface.co/convaiinnovations/laya">Laya</a> router and downloads its model (~420 MB) in the background. Bots still answer while that runs. To skip Laya: <code>cargo run -- serve --no-laya</code>.</p>
<p>Release binary later:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>make build
</span></span><span style="display:flex;"><span>./target/release/kwnt serve
</span></span></code></pre></div><h3 id="path-b--mac-app">Path B — Mac app</h3>
<p>Download the universal <code>.dmg</code> from the <a href="https://github.com/alexsergivan/kwant/releases/latest">latest release</a> (<code>kwant_universal.dmg</code>), drag it to Applications, and open it. The app uses the same <code>~/.kwnt</code> folder as <code>kwnt serve</code> and stays in the menu bar when you close the window.</p>
<p>The build is signed ad hoc, not notarized by Apple. On first open, click <strong>Done</strong>, then <strong>System Settings → Privacy &amp; Security → Open Anyway</strong> (on older macOS, right-click → <strong>Open</strong>).</p>
<h3 id="path-c--linux-app-beta-x86_64">Path C — Linux app (beta, x86_64)</h3>
<ul>
<li>
<p><strong>Ubuntu 22.04+ / Debian 12+:</strong> download <a href="https://github.com/alexsergivan/kwant/releases/latest/download/kwant_amd64.deb"><code>kwant_amd64.deb</code></a>, then:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo apt install ./kwant_amd64.deb
</span></span></code></pre></div></li>
<li>
<p><strong>Other distros:</strong> download <a href="https://github.com/alexsergivan/kwant/releases/latest/download/kwant_x86_64.AppImage"><code>kwant_x86_64.AppImage</code></a>, then:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>chmod +x kwant_x86_64.AppImage
</span></span><span style="display:flex;"><span>./kwant_x86_64.AppImage
</span></span></code></pre></div><p>The AppImage expects a normal GTK desktop and FUSE.</p>
</li>
</ul>
<p>Updates are signed and applied in-app (the <code>.deb</code> path asks for your password). Removing the package leaves <code>~/.kwnt</code> alone. Treat Linux as beta: tray, Wayland and HiDPI can vary; there is no ARM Linux or Windows app yet.</p>
<h3 id="path-d--always-on-vps">Path D — always-on VPS</h3>
<p>For routines that must keep running with the laptop closed, run the binary on a server or use the repo’s Docker Compose stack (kwant + Laya + a private Chromium). A short Compose path:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git clone https://github.com/alexsergivan/kwant.git <span style="color:#f92672">&amp;&amp;</span> cd kwant
</span></span><span style="display:flex;"><span>KWNT_CLIS<span style="color:#f92672">=</span>claude,codex docker compose up -d --build
</span></span><span style="display:flex;"><span>docker compose exec kwnt kwnt doctor
</span></span><span style="display:flex;"><span>docker compose exec kwnt kwnt signin-link
</span></span></code></pre></div><p>Put TLS in front of <code>127.0.0.1:8799</code> and set <code>KWNT_ALLOWED_ORIGINS</code> to your public origin. Full systemd / proxy notes belong in a dedicated VPS post; the README’s <a href="https://github.com/alexsergivan/kwant#self-hosting-on-a-vps">self-hosting section</a> is the source of truth until then.</p>
<h2 id="add-an-account">Add an account</h2>
<p>If nothing is configured yet, kwant shows a <strong>Get ready</strong> banner with <strong>Add an account</strong>.</p>
<table>
	<thead>
			<tr>
					<th>You have…</th>
					<th>What to do</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Claude Code CLI</td>
					<td><strong>Sign in with Claude</strong> in the UI, open the link, paste the code back</td>
			</tr>
			<tr>
					<td>Codex or Grok CLI</td>
					<td><code>codex login</code> / <code>grok login</code> on the same machine; kwant picks them up</td>
			</tr>
			<tr>
					<td>API key</td>
					<td><strong>Settings → This space → Accounts</strong> — Anthropic, OpenAI or xAI. Keys are write-only after save</td>
			</tr>
			<tr>
					<td>Local / other OpenAI-compatible server</td>
					<td>Same Accounts screen; point at your endpoint</td>
			</tr>
	</tbody>
</table>
<p>You can keep several accounts per engine (work + personal), set a default and a fallback order. When one runs out of usage, the turn moves to the next and the chat says so. Pin a bot to one account when you need that.</p>
<p>Optional: run <code>kwnt doctor</code> (or <strong>Setup</strong> in the app) so missing pieces print an install command instead of failing later.</p>
<h2 id="ask-once-then-hand-work-across-bots">Ask once, then hand work across bots</h2>
<p>Open <code>#general</code> and ask something that fits one role — architecture, a quick prototype, a shell check. Watch which bot answers and the reason line under its name. If it picked wrong, use <strong>Wrong bot?</strong>; kwant remembers the correction for next time.</p>
<p>Then force a handoff the way a real team works:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>@TechLead draft a one-page outline for rate-limiting a Go HTTP API.
</span></span><span style="display:flex;"><span>When you are done, @DevOps list the nginx and process checks you would run before ship.
</span></span></code></pre></div><p>What you want to see:</p>
<ul>
<li>TechLead writes in the shared channel.</li>
<li>An <code>@DevOps</code> mention appears (from you or from TechLead).</li>
<li>DevOps continues with the full thread visible — no copy-paste into a second chat tab.</li>
</ul>
<p>That @mention pattern is the whole multi-agent trick for day one. You are not writing a graph library; you are naming who owns the next step. The Mission board can turn hand-offs into cards; a card turns <strong>Verified</strong> only when kwant runs a check itself (for example a file or test check), not when a bot claims it is done. Evidence attachments are for you to read — they do not mark a card verified on their own.</p>
<p>If you have already built tool loops in Go, this is the layer that sits <em>above</em> <a href="/posts/tool-use-in-go-agent-loop/">the agent loop</a> and <a href="/posts/calling-claude-from-go/">the Claude client wiring</a>: routing, persistence, and human gates without another weekend of scaffolding.</p>
<h2 id="spaces-keep-work-and-home-from-leaking">Spaces: keep work and home from leaking</h2>
<p>Each <strong>space</strong> has its own bots, channels, routines, accounts and approval rules. Nothing crosses the boundary unless you copy it.</p>
<p>A useful first split:</p>
<ul>
<li><strong>Work</strong> — company Claude / Codex logins, bots that may touch work repos, stricter approvals.</li>
<li><strong>Home</strong> — personal keys or a local model, bots for mail and side projects.</li>
</ul>
<p>Switch with the space rail (⌘/Ctrl + 1–9 on desktop). This is the feature to set up before you connect an IMAP inbox or a GitHub token: credentials and memory stay where you put them.</p>
<h2 id="routines-and-approvals-the-safety-net">Routines and approvals (the safety net)</h2>
<p>Say something like “every weekday at 9, summarise what changed in the deploy channel” and let the bot create a routine card with <strong>Undo</strong>, <strong>Edit</strong> and <strong>Pause</strong>. Come back to the <strong>Inbox</strong> for what is waiting on you, what finished and what failed.</p>
<p>Approvals default to <strong>Ask only when risky</strong> (<code>smart</code>) on new spaces: ordinary work runs; steps such as <code>git push</code>, network calls, unknown commands or changes outside the bot’s folder show a card with the exact command — <strong>Allow once</strong>, <strong>Always allow</strong> or <strong>Deny</strong>. <strong>Payments always ask</strong>, in every mode, including a checkout in the bot’s browser behind a plain “Continue”. You can tighten to <strong>Ask before running commands</strong>, or loosen to <strong>Don’t ask</strong>, per space or per bot.</p>
<p>Two advanced systems — Flight School (bots earn more freedom per kind of work) and the Truth Ledger (conflicting facts side by side) — ship <strong>off until you turn them on</strong>. Skip them for the first week.</p>
<h2 id="what-this-is-not">What this is not</h2>
<ul>
<li>Not a replacement for writing your own <a href="/posts/tool-use-in-go-agent-loop/">tool-use loop</a> inside a product you ship as code.</li>
<li>Not a visual workflow builder in the n8n / Dify sense.</li>
<li>Not a hosted stand-in for Grok Bot, Claude Duet or OpenAI dots: those run on the vendor’s cloud; kwant runs on hardware you control, and you bring the model accounts.</li>
</ul>
<p>If you want a fair feature-by-feature comparison with other open-source projects in that category, that is a separate article. For getting a team running today, the install paths above are enough.</p>
<h2 id="checklist">Checklist</h2>
<ul>
<li><input disabled="" type="checkbox"> Clone + <code>make run</code>, or install the Mac / Linux app</li>
<li><input disabled="" type="checkbox"> Add at least one account (CLI or key)</li>
<li><input disabled="" type="checkbox"> Ask in <code>#general</code> and read the “why this bot” line</li>
<li><input disabled="" type="checkbox"> Run one deliberate <code>@mention</code> handoff between two bots</li>
<li><input disabled="" type="checkbox"> Create a second space before mixing work and personal accounts</li>
<li><input disabled="" type="checkbox"> Try one routine and one approval on a disposable command</li>
<li><input disabled="" type="checkbox"> <a href="https://github.com/alexsergivan/kwant">Star the repo</a> and install from the paths above if the shape fits</li>
</ul>
<h2 id="conclusion">Conclusion</h2>
<p>A self-hosted AI agent team is not magic — it is roles, shared chats, handoffs, schedules and a gate on the dangerous bits. kwant packages that into one binary you can run on a laptop or a VPS, with data in <code>~/.kwnt</code> and model accounts you already pay for. Start with Path A or the desktop app, get one handoff working, then decide whether Spaces and a small VPS are worth the next evening.</p>
<p>Site and docs: <a href="https://kwant.si">kwant.si</a>. Source and releases: <a href="https://github.com/alexsergivan/kwant">github.com/alexsergivan/kwant</a> — starring the repo (and installing it) is the shortest way to help it show up for the next person searching for a self-hosted team.</p>]]></content:encoded>
      <category>AI Engineering</category>
      <category>DevOps</category>
    </item>
  </channel>
</rss>
