> your AI agent picks dependencies from memory; give it dated facts — try starlog.dev ↗ vet your agent's deps ↗ vibe-coding is fine. vibe-importing isn’t. — try starlog.dev ↗ vibe-importing isn’t fine ↗ your agent has never seen your private packages — try starlog.dev ↗ facts for private packages ↗ a linter for the dependencies your AI agent picks — try starlog.dev ↗ a linter for agent deps ↗ whois is redacted, cdns mask the rest — get the real operator — try whoisgeni.us ↗ who really runs that domain ↗ domain attribution that shows its work — full evidence chain — try whoisgeni.us ↗ domain intel w/ evidence ↗

← Back to Articles

Cloudflare OS: Building an Agent Operating System with Capability-Based Security

[ View on GitHub ]

Cloudflare OS: Building an Agent Operating System with Capability-Based Security

Hook

What if agents could continue executing destructive operations while waiting for your approval, receiving synthetic responses that let them plan ahead without touching real systems?

Context

Traditional AI coding assistants operate under a problematic security model: they either run with ambient permissions (full filesystem access, unrestricted API calls) or block on synchronous approval gates that destroy productivity. Claude Desktop with MCP servers can read your entire database. Cursor has your AWS credentials. Replit Agent deploys to production with a single confirmation click.

Cloudflare OS takes a radically different approach by treating agent workspaces as an actual operating system problem. Instead of bolting permissions onto existing dev tools, it implements capability-based security from the ground up using Cloudflare Workers primitives. Each workspace is a Durable Object. Each gadget (think: mini-application) runs in an isolated Worker. Agents execute code in the same sandboxed context as users, subject to identical restrictions. External service access isn't controlled by API keys in environment variables—it's mediated through Gatekeeper workers that can simulate responses, queue operations for approval, or grant capabilities dynamically. This architecture is genuinely novel because it solves the asynchronous approval problem: agents receive fake data for destructive operations, continue planning with that synthetic context, and only pause when human decisions would actually change their execution path.

Technical Insight

The core architectural insight is using Durable Objects as workspace kernels. Each workspace is a persistent DO instance that coordinates access to gadgets through Dynamic Worker Facets—a Workers feature that lets you spawn isolated V8 contexts on-demand while sharing the parent DO's state.

Here's how a gadget gets loaded into a workspace:

// Workspace DO spawns a Dynamic Worker Facet for each gadget
class WorkspaceKernel extends DurableObject {
  async loadGadget(blueprintId: string, userId: string) {
    // Each gadget instance runs in isolated Worker context
    const facet = await this.env.DYNAMIC_WORKERS.get(blueprintId);
    
    // Inject capability bindings—gadget can ONLY access what's granted
    const gadgetEnv = {
      STORAGE: this.ctx.storage, // Workspace-scoped storage
      GITHUB: this.gatekeepers.github.createFacet(userId),
      // NO ambient network access—internet is disabled by default
    };
    
    return facet.fetch(request, gadgetEnv);
  }
}

The security boundary is elegant: gadgets are just TypeScript code, but they cannot make arbitrary HTTP requests. The only way to interact with external systems is through bindings—environment variables that expose specific APIs. A GitHub Gatekeeper might expose createIssue() and listRepos() but nothing else. The gadget's server code literally cannot access other GitHub endpoints.

Client-side security follows the same pattern using Cap'n Web RPC, a capability-based RPC protocol over postMessage. Gadget UIs run in sandboxed iframes and communicate with server code through strictly typed interfaces:

// Gadget server exposes capabilities via Cap'n Web schema
export interface GadgetAPI {
  // Each method is a capability grant
  readDocument(id: string): Promise<Document>;
  updateDocument(id: string, content: string): Promise<void>;
}

// Client code gets a typed RPC proxy—no direct DOM access to parent
const api = await connectCapnWeb<GadgetAPI>(parent);
const doc = await api.readDocument('123'); // Type-safe, capability-restricted

This is architectural leverage: requiring structured RPC means every gadget automatically produces agent-consumable APIs. When an agent runs in Code Mode—executing generated TypeScript directly in the workspace—it uses the exact same interfaces as human users.

The Gatekeeper pattern is where asynchronous approval gets implemented. Instead of blocking when an agent tries to deploy code or charge a credit card, the Gatekeeper returns simulated data:

class DeploymentGatekeeper extends WorkersBase {
  async deploy(code: string, config: DeployConfig): Promise<DeployResult> {
    // Queue for human approval
    await this.env.APPROVAL_QUEUE.send({
      operation: 'deploy',
      code,
      config,
      workspaceId: this.workspaceId
    });
    
    // Return synthetic success response immediately
    return {
      deploymentId: `pending-${randomId()}`,
      url: `https://preview-${randomId()}.workers.dev`,
      status: 'simulated'
    };
  }
}

The agent receives a fake deployment URL, continues planning its next steps (maybe updating documentation or notifying stakeholders), and only stops if it needs real feedback. Meanwhile, a human reviews the queued operation and either approves (replaying with real data) or rejects (the agent's subsequent steps were speculative anyway).

The per-user gadget model inverts SaaS economics. Traditional apps prevent users from modifying shared code. Cloudflare OS assumes every user will fork and customize their gadgets:

// Blueprint is the template
const blueprint = await fetchGadget('todo-app-v1');

// Each user gets their own instance with isolated storage
const myTodoApp = await workspace.installGadget(blueprint, {
  userId: 'alice',
  customizations: {
    // Alice's agent modified the UI to show priorities differently
    priorityAlgorithm: 'eisenhower-matrix'
  }
});

Storage multiplies linearly with users, but Workers' economics make this viable—each gadget instance is just a V8 isolate, not a container. The tradeoff is operational complexity: no obvious garbage collection for abandoned instances, and blueprint updates don't auto-propagate to forks.

What makes this genuinely novel isn't any single piece—it's the integration. Capability-based security isn't new (see seL4, Capsicum). Agent code execution isn't new (every REPL tool does this). But combining them with asynchronous approval simulation and per-user isolation creates something that doesn't exist elsewhere: an agent workspace where non-technical users can safely delegate complex workflows to AI without IT losing control.

Gotcha

The 'early access' warning is sincere—this is versioned 2.0 but described as having 'many rough edges.' Expect core workflows to break, documentation to lag implementation, and migration paths between versions to not exist. You're not adopting a stable tool; you're partnering with Cloudflare to develop one.

Cap'n Web RPC creates real lock-in. It's a Cloudflare-specific protocol with near-zero adoption outside Workers. Integrating with existing MCP servers requires bridging fundamentally incompatible models: MCP assumes servers have ambient network access and expose tools synchronously, while Cloudflare OS's capability model forbids both. The promised MCP compatibility will likely be 'you can wrap an MCP server in a Gatekeeper' rather than seamless interop. Per-user gadget instances also create scaling challenges invisible in traditional SaaS: storage costs multiply with users, and there's no clear story for versioning—when you patch a security bug in a blueprint, how do the 300 user forks that customized it get the fix? The architecture assumes users want customization but provides no mechanism for upstream updates. Finally, asynchronous approval simulation only works when agents can operate on synthetic data. Complex workflows requiring real API responses (like 'create a PR, read the CI output, fix failures') degrade to synchronous approval anyway, eliminating the productivity benefit.

Verdict

Use if: You're a platform team at a mid-to-large company already on Cloudflare Workers (or willing to run workerd self-hosted), you need organizational control over AI workflows without vendor lock-in to closed platforms, and you have specific compliance requirements around non-technical users delegating work to AI—particularly industries where audit trails and asynchronous approval workflows are regulatory requirements. The capability-based security model is genuinely superior for enterprises where IT cannot tolerate ambient access to corporate systems, and the per-user isolation enables use cases (like letting customers build custom integrations with AI assistance) that are architecturally impossible in traditional SaaS. Skip if: You want turnkey deployment, stable APIs, or are an individual developer—use Cursor, Windsurf, or Claude Desktop instead. The complexity only pays off at organizational scale where custom security policies and multi-user collaboration justify operating your own infrastructure. Also skip if you need deep integration with existing MCP tooling or expect frequent breaking changes to derail your roadmap. This is for teams with Workers expertise who can debug novel architecture when things break, not teams looking for a productivity tool to install and forget.