Blog/Engineering
EngineeringRuntime

Agents that keep working after you close the tab

Most AI apps stop the moment you stop typing. We built AgentNava on Cloudflare's edge so an agent can hold state, wake itself on a schedule, and keep a job moving while you sleep. Here is how the runtime does it.

Engineering · Runtime

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 falls short for work that runs for days.

Real work 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 a simple one: 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 well 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, what you have is 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

On our default runtime, every AgentNava conversation runs in its own 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 conversation’s history and files live: in a long-lived object that stays put between visits.

Because it is durable, a conversation can accumulate context across days: what the agent did last Monday, which deals it already followed up on, what is still waiting on you. When you reopen the workspace, you check in on work that has continued without you.

Consistency matters here. A Durable Object is single-threaded and owns its storage, and there is exactly one object per conversation. That object is the source of truth for the conversation’s state.

Waking without a human

Durable storage solves memory. It does not, by itself, make anything happen. For that, the platform leans on two Cloudflare primitives: Cron Triggers and Durable Object alarms.

Every agent has trigger settings: run on a schedule (“every Monday at 8am, my time”), run when a webhook arrives, or run when someone asks. From inside a conversation, an agent can also schedule its own follow-up: “check back in an hour.” Schedules and self-set follow-ups are saved as rows. A Cron Trigger checks for due rows every minute and replays the saved instruction into the agent’s conversation, so the agent picks up with its history and files in place. Interval triggers, set through the API, run on a Durable Object alarm. Cloudflare runs both, so there is no scheduler server for anyone to operate.

  • 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 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, set up with our SDK. It assumes a CRM such as HubSpot is connected. The interesting part is the last call: the schedule is part of the agent’s configuration.

agent · pipeline-warmer.ts
import { AgentNava } from '@cerebro-labs/agentnava-sdk';

const ws = AgentNava.getWorkspace(); // reads AGENTNAVA_API_KEY

const agent = await ws.agents.create({
  name: 'Pipeline warmer',
  instructions:
    'Find deals with no activity for seven days. ' +
    'Research what changed at each company. ' +
    'Draft one follow-up per deal and post the drafts here. ' +
    'Do not send anything.',
});

// Every Monday at 8am Pacific, with nobody at the keyboard.
await agent.setTriggers([
  { kind: 'chat' },
  {
    kind: 'schedule',
    cron: '0 8 * * 1',
    timezone: 'America/Los_Angeles',
    message: 'Run the Monday pipeline sweep.',
  },
]);

When Monday comes, the agent wakes on its own, does the sweep, leaves the drafts for you, and goes back to sleep. You never opened a tab. You just find the work done the next time you look.

What we traded away

None of this is free. Putting a durable, single-threaded object behind every conversation is a stronger commitment than a stateless function, and it comes with real constraints worth naming.

DecisionWhat we gainWhat it costs
Durable Object per conversationConsistent state that outlives the tabOne conversation is one thread; heavy fan-out needs care
Edge-resident stateFast, local reads and writesStorage is SQLite per conversation; queries across conversations need another store
Wakeups on a once-a-minute cronNo scheduler server to operateA wakeup can fire up to a minute late

For the work AgentNava is built to do (a proactive agent keeping a job moving) we think this is the right trade. The agent still gets a working filesystem and a shell: each conversation’s files live in the same object’s storage, with large files in R2 object storage.

Key takeaways
  • Real work is a job that has to survive a closed tab.
  • Durable Objects give each conversation consistent state that outlives the tab.
  • Schedules, webhooks and self-set wakeups let an agent wake and work with no scheduler server to run.
  • The result: you hand off the work and check in on progress.

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, 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.

RP
Raj Kiran
Founder · AgentNava

Building the workspace where non-developers describe the work and get a proactive agent that keeps it moving in production. Writes here about the runtime, the product, and the playbooks behind both.

Stay in the loop

New posts, in your inbox.

A short note when we publish something worth your time. Product releases, engineering write-ups, and playbooks. No noise.

One email per post. Unsubscribe anytime.