There is a quiet assumption baked into most AI products: that the human is always there. You type, it answers, you type again. Close the tab and the whole thing evaporates. That is fine for a chatbot. It is useless for work.
Real work is not a conversation. It is a job that runs over hours and days: chase the invoice, watch the pipeline, triage the tickets, brief me in the morning. None of that fits inside a single request-and-response. So when we started building AgentNava, the first question was not “which model” or “which UI framework.” It was simpler: how does an agent keep working when nobody is watching?
The close-the-tab problem
A typical AI app is stateless by design. Each message is a fresh call to a model, with the previous turns replayed as context. That works beautifully for a fast exchange, and it scales because there is nothing to hold onto between requests. But it means the “agent” only exists for the few seconds it is generating a reply. There is no it the rest of the time.
For a proactive agent, that is the whole ballgame. If the work only advances while you have the tab open, you do not have an employee. You have a very expensive autocomplete.
An agent you have to babysit is just a tool with extra steps. The point is to hand off the job and get on with your day.
So the runtime needs two things a stateless app does not have: somewhere durable to keep the agent’s state, and a way to start running again without a person triggering it.
State that outlives the session
Every AgentNava agent is backed by a Durable Object: a single-threaded, addressable piece of compute with its own strongly-consistent SQLite storage, living on Cloudflare’s edge. That is where the agent’s memory lives. Not in your browser, not in a request that is about to end, but in a long-lived object that stays put between sessions.
Because it is durable, an agent can accumulate context across days: what it did last Monday, which deals it already followed up on, what is still waiting on you. When you reopen the workspace, you are not starting a new conversation. You are checking in on work that has been continuing without you.
Waking without a human
Durable storage solves memory. It does not, by itself, make anything happen. For that, the runtime leans on two edge primitives: alarms and the event loop that survives a closed tab.
An agent can set an alarm on its own Durable Object: “wake me at 8am,” or “check back in four hours.” When the alarm fires, Cloudflare invokes the object, the agent picks up exactly where it left off, does its work, and (usually) sets the next alarm before going quiet again. No cron server to run, no queue to babysit. The schedule lives inside the agent.
- Scheduled work: a morning brief, a Monday pipeline sweep, an end-of-day summary.
- Deferred work: “follow up in three days if they have not replied.”
- Reactive work: a webhook or inbound email wakes the agent to handle something the moment it lands.
Critically, all of this runs whether or not you are online. The tab is just one way to watch the agent. It was never where the agent lived.
A worked example
Here is the shape of a proactive agent that keeps a sales pipeline warm. The interesting part is the last two lines: the agent schedules its own next run.
// Runs every Monday at 8am, then re-arms itself.
export default defineAgent({
name: "pipeline-warmer",
async onWake(ctx) {
const stale = await ctx.tools.crm.findDeals({ quietForDays: 7 });
for (const deal of stale) {
const change = await ctx.tools.research.whatChanged(deal.company);
await ctx.draftFollowUp(deal, change); // waits for your approval
}
// hand the work off and go quiet until next week
await ctx.scheduleNext({ cron: "0 8 * * 1" });
},
});
When Monday comes, the agent wakes on its own, does the sweep, leaves drafts waiting for your yes, and goes back to sleep. You never opened a tab. You just find the work done, staged for approval, the next time you look.
What we traded away
None of this is free. Putting a durable, single-threaded object behind every agent is a stronger commitment than a stateless function, and it comes with real constraints worth naming.
| Decision | What we gain | What it costs |
|---|---|---|
| Durable Object per agent | Consistent memory, self-scheduling | One agent is one thread; heavy fan-out needs care |
| Edge-resident state | Low latency, runs near the user | Storage model is SQLite, not a big warehouse |
| Self-set alarms | No external scheduler to operate | The agent owns its own reliability |
For the work AgentNava is built to do (a proactive agent per user, keeping a job moving) this is exactly the right trade. When a job genuinely needs heavy parallel compute or a filesystem, the agent hands that part off to a sandbox runtime instead. The Durable Object stays the calm, consistent brain; the heavy lifting happens elsewhere and reports back.
- An agent is not a conversation. It is a job that has to survive a closed tab.
- Durable Objects give each agent consistent memory that outlives the session.
- Self-set alarms let an agent wake, work, and re-arm with no external scheduler.
- The result: you hand off the work and check in on progress, instead of driving every step.
Where this goes next
The runtime that keeps an agent alive is the foundation for everything above it: connections to the tools you already use, a canvas you can co-edit with the agent, and the phase indicator that shows you, in plain language, what the agent is doing right now. We will dig into each of those in future posts.
For now, the one idea worth keeping: the agent was never in the tab. Close it whenever you like. The work keeps moving.