Move the whole agent fleet off self-hosted cells (wells VMs) onto Flue — Pi's harness running on Cloudflare Durable Objects. No boxes to manage, no mother to birth them. Each agent configures itself.
IDENTITY.md, yearnings, working memory. Free and automatic.sqlite-vec fragility.dispatch (async) for heavy authoring, tool-RPC (sync) for quick lookups, subagents for ephemeral specialists. No more specialist cells.Cells gave each agent a real Linux box on a wells VM — and with it, a standing tax: VM provisioning, hibernate-recovery, the mother birth chain, a per-session model hack, and an analytical brain (Stoolap) that kept throwing vec0.so ABI errors. None of that is HomeZero. It's plumbing we maintain so the agents can run.
Flue moves the agent onto a Cloudflare Durable Object: a single-tenant, SQLite-backed, durably-executing instance that exists only when addressed and costs nothing idle. The spike proved the full stack end-to-end — a conversational agent you can chat with on the web, switch models mid-thread, all routed through the claudeflare-gateway. What follows is how the rest of HomeZero lands on that substrate.
The scary row was always "the box." It turns out Flue offers a tiered filesystem — including a real per-session Linux container when you need one — so nothing forces a single migration model. The advisor runs light; the scraper, when it comes, can run heavy.
| Cells capability | Flue-native landing | Status |
|---|---|---|
| Persistent box + filesystem | Workspace (durable, light) or Sandbox container (full Linux, heavy) | solved |
| Stoolap vector brain | Turso (managed libSQL + native vectors) | upgrade ↑ |
| WhatsApp / Slack two hats | Native channels, one agent, two routes | upgrade ↑ |
| Pulse heartbeats | Durable Object alarms / schedule() | native |
| cells talk (agent↔agent) | dispatch / tool-RPC / Convex blackboard | designed |
| zero-mother births a VM | Deleted — the agent self-configures on first boot | designed |
Two filesystem tiers matter: Workspace (durable files, structured code tool, no raw bash) for the advisor; Sandbox container (real shell, git, apt) reserved for agents that must shell out.
claudeflare-gateway. One billing surface, one observability pane, one set of model specifiers. The advisor's two hats (buyer / staff) still differ, but only by model choice on the same Pi harness, never by a different runtime.
This isn't a new data model — it's the four-store law you already reasoned out (Convex / R2 / Stoolap / cell-FS), ported to the new substrate: cell FS → Workspace, Stoolap → Turso, Convex stays Convex, R2 stays R2. Sorted by access pattern, not data type.
IDENTITY.md, yearnings, notes, working memory, scratch. Agent-authored prose. Backed by DO-SQLite + R2. Automatic, free.vector_top_k). Market's is heavy (comps, embeddings); advisor's is light. Hosted on Turso Cloud, one DB per agent.Workspace and DO-SQLite session memory are automatic per agent. Turso is the one deliberate add. Convex + R2 are shared and unchanged from today.
@tursodatabase/serverless (pure HTTP, zero native deps), queried from inside a tool. That second role is what we use: the per-agent brain, hosted, vectors native.
On cells, the only thing mother ever produced was a config — she reasoned a team from onboarding, then seeded template files into a freshly-birthed VM. With no VM to provision, the agent can author that config itself. This is your own law made literal: the first-run end state must be agent-authored.
zero-mother, the doorbell → wa-bridge → zero-mother chain, the birth skill, publish-template.mjs, and the whole Mac-side birth orchestration. Gone.
Place → market (via the resolver; warm-market gate still applies). Person → advisor. Finish creates the account and hands off.
POST /agents/advisor/<householdId> with the answers as the first message. The DO instantiates on that first hit. No external birther.
Reads the onboarding answers, queries the already-warm market for context, and writes its per-user understanding into the Workspace (IDENTITY.md = what it knows about you so far). Its name (Zero) and its yearnings (the standing questions, shared to start) are fixed and shipped — not invented here. Publishes a projection (market, status) to Convex for the UI.
The Workspace is the source of truth; Convex carries the projection the apps render. The same loop drives react / tend / scout / brief on Durable Object alarms.
No invented deterministic fill. /home shows the advisor's real progress: the first-run skill writes a status to Convex at each checkpoint as it genuinely completes, and the page — subscribed via Convex's reactive query — updates live. The bridge is the agent narrating itself.
IDENTITY.md + yearnings into the Workspace.Four in-flight checkpoints → ready. The advisor owns its own status field; each transition is a real Convex write, never a timer.
Flue gives two native primitives — async dispatch between deployed agents, and synchronous in-process subagents — plus the obvious third: expose a peer as a tool for a sync RPC. Each maps to a real interaction in the funnel.
Conversational. Two channel hats: WhatsApp (buyer) + Slack (staff). Reacts fast; dispatches the deep work.
Authors briefings, holds the comps + vector brain in Turso. Spawns specialists as subagents.
Born on zero. Talks to the market via dispatch; owns the home's evolving record.
Persistent peers talk via dispatch (async) and tool-RPC (sync). Ephemeral specialists are subagents. Shared truth lives in Convex.
This matches your card-authorship split exactly: the advisor reacts synchronously to the user, then dispatches the market to author the deep briefing that lands as a card. The "cells talk to cells" mesh becomes native, with no transport to maintain.
The product model is unchanged — three births (advisor, market, home agent); the user is created, not born. What changes is the body each runs in.
| Agent | Scope | Runtime | Storage | Channels |
|---|---|---|---|---|
| Advisor | per household (shared relationship, account holder owns) | DO + Workspace (light) | Workspace + light Turso; reads Convex | WhatsApp + Slack |
| Market | per county | DO + Workspace; Sandbox container if it must shell out | Workspace + heavy Turso (comps/vectors); writes Convex | — |
| Home agent | per house (born on zero) | DO + Workspace | Workspace + Turso; writes Convex | — |
Specialists (water-rights, flip-check) are no longer agents at all — they're subagents of the market, spawned per task.
IDENTITY.md, one memory) from sessions (named conversation threads inside it, each with isolated history). The advisor (named Zero) is one instance per household (id = the household's Clerk userId) holding two named sessions: buyer (WhatsApp) and staff (Slack). Separate histories — no context bleed — and model is a per-session choice, so buyer can run GPT-5.5 while staff runs Opus, on the same shared brain. (To merge channels into one thread instead — same human on WhatsApp + web — route both to the same instance and same session name. task:-prefixed names are reserved.)
Every household's advisor is named Zero. It's born, then it lives: it remembers, it dreams, and it's reachable on the channels that matter. All four ride the substrate we just defined — memory is Workspace files, dreaming is a Durable Object alarm, the two hats are channels into named sessions. Built on the self-config vertical, in this order.
Zero's Workspace holds a memory/ store of agent-authored markdown beside IDENTITY.md — what it has learned about you, your search, your constraints. It recalls the relevant files at the top of each turn and writes new ones as it goes. Durable (DO-SQLite + R2); session transcripts are kept automatically. This is the same Workspace the first-run pass already writes to — memory is just more of it.
Every Zero ships with the same set of yearnings — the standing questions it wants answered about its user: what "a home that takes care of you" means to them, their real all-in (cost-to-zero) budget, their dealbreakers, what they'd trade off, how ready they are, how they want to be advised. The questions are universal — part of Zero's identity. The answers are per-user, and accumulate in memory. Yearnings reweight what Zero studies and asks next.
Shared to start. We ship one fixed set so every Zero behaves consistently; as Zero learns a household over time, the set can grow user-specific standing questions, but the universal core stays. Start uniform, personalize later — not the other way around.
A nightly Durable Object alarm wakes Zero with no user present to run a dream skill: fold the day's sessions into durable memory, merge and prune, revisit yearnings, prep tomorrow's brief. This is the cells "nightly dream," now native to the runtime — no pulse, no claude -p, no Mac cron.
| Hat | Channel | Session | Wiring |
|---|---|---|---|
| Staff | Slack — one #advisors channel, a thread per household | staff (Opus) | Automatic for every advisor. At birth Zero posts its intro to #advisors, opening its thread, and records thread_ts ↔ userId. Staff replies in-thread route back to that household's staff session. |
| Buyer | buyer | Optional — only if the buyer gave a number. Inbound routes phone → buyer → userId (the buyers.by_phone unique index already exists) into the buyer session. |
One instance per household (id = Clerk userId) holds both sessions over one shared brain; histories stay isolated — staff talk never bleeds into the buyer's thread.
IDENTITY.md in the Workspacebuyers is the per-user record)Prove the model on the cheapest agent that exercises the whole pattern: onboarding answers → a self-configuring advisor you can chat with. Market, home agent, scraping, and the Turso vector brain each become their own later spec — but they all inherit this mold.
Goal: a real person finishes onboarding and is talking to Zero — which authored its understanding of them from their answers — on Flue, no mother in the loop. (Plan 1 of 2; memory · dream · Slack-staff · WhatsApp follow in Plan 2.)
householdId, served behind the gateway.IDENTITY.md + yearnings into the Workspace./home renders it.waking → studying_market → authoring → scouting → ready to Convex; /home renders it live via reactive query.Next step: an implementation plan for Slice 1.