---
title: 'The web wasn''t built for agents. Neither is your app.'
published date: '2026-10-01'
author: 'Miguel Salinas'
title-image: 'https://camelai.com/blog/assets/images/covers/the-web-wasnt-built-for-agents.png'
---

In 1970, IBM researcher Edgar Codd [argued](https://dl.acm.org/doi/10.1145/362384.362685) that apps shouldn't need to know how their data is stored. At the time, each app kept its records in its own file format, with its own code to read and write them. Some thought Codd's idea was impractical. His relational model became the basis for SQL databases, and today it would be crazy for an app to manage its own storage.

The same thing is happening to agents right now. Apps shouldn't need to know how their agents run.

Last month we removed the agent loop from our [coding agent](https://camelai.com/code) and deleted about 72,000 lines of code. camelCode's agents now run on our new hosted runtime, camelRun.

This is the fifth time we've built infrastructure for an AI agent in 3 years. Each time our loop improved but it still took most of our development time and was responsible for the vast majority of production issues.

After years of forcing agents onto infrastructure that wasn't built for them, we realized the problem. The web is built for stateless requests. A server gets a request, answers it quickly, and forgets it. Agents are stateful and long-lived. A single turn can run for minutes, sometimes hours. Your app has to stream that turn to the user over a WebSocket or SSE connection, and pick up where it left off every time the connection drops.

We believe that agents are a new primitive. Just like every app has a database, every app will have some type of agent, either serving users or running behind the scenes. Like a database, an agent is essential to your app and inherently complicated. No app should have to rebuild one from scratch. We believe all you should have to do is pick a model, tell the agent what it does, and give it tools to complete those tasks.

We built camelRun for stateful, long-lived agents. It runs them outside your app, so your app can remain a normal web app. It's [open source](https://github.com/qaml-ai/run) and our harness is built on [Pi](https://github.com/earendil-works/pi).

## An agent is a definition, not a program

At its core, an agent is a model, a system prompt, and the tools it can call, run in a loop. So why is running your own agent so hard?

The hard parts are the harness and the hosting. The harness has to fit long conversations into the context window, run tool calls in parallel, keep up with new models, and also handle every edge case without crashing. Then the harness needs somewhere to run. If you own the agent, you own both.

Most teams still write their own harness and host it themselves. They might use a framework, like [LangGraph](https://www.langchain.com/langgraph) or Cloudflare's [Agents SDK](https://developers.cloudflare.com/agents/). A framework gives you libraries, but the agent is still a program you have to deploy and keep running.

To us, that looks like every app writing its own database. Nobody does that. They pick [Postgres](https://www.postgresql.org/), and most pay someone else to host it.

## Agents run outside your app

Your app talks to its database over a connection, and deploying the app doesn't touch the database. Agents should work the same way.

In camelCode, the agents ran inside the product, and each could take the other down. Deploying the product interrupted running agents, which left users' chats stuck on a loading spinner. Agent crashes leaked into the product too. A turn killed by a crash could leave its thread marked as running for days.

Agents should run as a separate service and talk to your app via API, like your database. Your app and your agents work together through the tools you define. We handle tools through our SDK. It opens a connection from your app out to camelRun, so you don't expose anything to the internet. To the agent, your app looks like any other MCP server.

You can deploy your app whenever you want without interrupting an agent, and an agent's crash doesn't land on your servers. If your app goes down, calls to its tools fail, and the agent keeps going. Your app gets to stay a normal web app.

## Many agents share one process

So where do our agents run?

The usual answer is to give each agent its own container or VM, because agents write and run code. camelCode started that way. Each user got an [always-on container](https://camelai.com/blog/we-tried-every-container-service-then-built-our-own), and the agent ran inside it with a full Linux environment. It was heavy, expensive and slow.

We tried to [move the harness into a Cloudflare Durable Object](https://camelai.com/blog/our-coding-agent-runs-in-a-cloudflare-durable-object-not-a-vm), one per chat thread. That was cheaper and faster than the containers, but long conversations kept running out of memory [along with a host of other issues](https://camelai.com/blog/should-you-build-on-cloudflare). We learned that the code the model writes needs a sandbox, but the harness doesn't. The harness is our code, and we know what it does.

In fact, the harness doesn't need its own box at all. Packing many agents into one Node.js process sounds scary, but it's what web servers have always done. An old Django or PHP app runs a few worker processes, and each one serves many users. Nobody gives each request its own VM. In a shared process, an idle agent uses tens of kilobytes rather than 50MB+, so users can run thousands of agents at once. An agent turn is a long request that spends most of its time waiting, and waiting is cheap.

## Agents get JavaScript, not a Linux machine

The code the model writes still needs a sandbox, but it doesn't need a Linux machine. The current default is to give the model a Linux machine with a shell. Then the agent can do anything a computer can. 

Most code an agent writes is just glue. It calls a tool, filters the result, and passes it to another tool. JavaScript handles glue well, and it's much easier to sandbox. Cloudflare's [Code Mode](https://blog.cloudflare.com/code-mode/) showed us this shape, where the model writes JavaScript that calls its tools.

We run the model's code in [QuickJS](https://bellard.org/quickjs/), a small JavaScript engine, compiled to WebAssembly. The sandboxes run in separate processes with no network and no secrets.

From inside the sandbox, the model's code can only call the agent's tools, including the ones that read and write its files. The code can't do anything the agent couldn't already do with a tool call.

## Try it out

camelRun is live at [camelai.com/run](https://camelai.com/run), and the code is at [github.com/qaml-ai/run](https://github.com/qaml-ai/run). It costs $0.01 per agent-hour of active run time, plus model usage. It's in the same category as [Claude Managed Agents](https://platform.claude.com/docs/en/managed-agents/overview), OpenAI's [Agents API](https://developers.openai.com/api/docs/guides/agents-api/overview), and [Amazon Bedrock AgentCore](https://aws.amazon.com/bedrock/agentcore/).