FabricFabricHarness
Deployment

Cloudflare Workers + Sandbox

Deploy to Cloudflare Workers with Durable Object sessions and Cloudflare Sandbox.

The Cloudflare target emits an unbundled Worker entrypoint, a Durable Object session store, and a Cloudflare Sandbox container binding. Wrangler owns the Cloudflare bundle; Fabric Harness just emits the entry, bindings, and config.

Status: pilot/live-gated. Build, fh dev --target cloudflare, Workers AI binding, Durable Object session persistence, session routes, and R2-backed large artifacts are implemented. Treat production Cloudflare deployments as pilots until your account runs the live smoke workflow successfully. Full workspace backup/restore parity remains roadmap.

Quickstart

npx @fabric-harness/cli init my-edge-agent --template cloudflare
cd my-edge-agent
npm install
npx fabric-harness dev --target cloudflare --port 8787

The template uses the Cloudflare Workers AI binding (env.AI) so the Worker can run inference without external model API keys.

Build

fh build --target cloudflare
cd .fabricharness/build/cloudflare
npm install

Output:

.fabricharness/build/cloudflare/
  dist/worker.ts
  wrangler.jsonc
  Dockerfile         # default Cloudflare Sandbox image
  manifest.json
  README.cloudflare.md

Develop locally

fh dev --target cloudflare

This wraps wrangler dev so the same bundler runs in dev and deploy. Two reload paths run simultaneously:

  • Wrangler watches the bundle's transitive import graph and reloads workerd on body edits to your agent files.
  • Fabric Harness's structural watcher watches .fabricharness/agents/ and regenerates the Cloudflare entry whenever the agent set changes (a file is added, removed, renamed, or its trigger metadata changes). Wrangler picks up the new entry automatically.

Net result: you can edit agent bodies, add new agents, or change triggers: { webhook: true } without restarting the dev server.

Or if you've already built once and just want raw wrangler:

npx wrangler dev

Deploy

fh build --target cloudflare
cd .fabricharness/build/cloudflare
npx wrangler deploy

Routes

The Cloudflare target serves the same surface as the Node server — see HTTP Server reference for the full route table:

  • GET /health · GET /ready · GET /manifest
  • POST /agents/:name/:id — invoke
  • GET /agents/:name/:id — read session
  • GET /agents/:name/:id/stream — SSE stream of typed AgentEvent values
  • DELETE /agents/:name/:id — reserved (501 today)

Webhook trigger gating applies on the Worker too: in production mode (FABRIC_ENV=production), only agents with triggers.webhook === true are exposed publicly.

Choosing a Cloudflare sandbox mode

Fabric Harness supports two Cloudflare sandbox modes.

Containers / Cloudflare Sandbox

Use this mode when your agent needs Linux shell commands, package managers, language toolchains, bash, grep, read, write, and edit tools.

export default {
  sandbox: {
    backend: 'cloudflare',
    mode: 'sandbox',
    binding: 'Sandbox',
    cwd: '/workspace',
  },
};

Shell Workspace / @cloudflare/shell

Use this mode when you want a lightweight durable Workspace and a Worker Loader-backed JavaScript code tool. It does not provide Linux shell commands; the model uses state.* inside the code tool.

export default {
  sandbox: {
    backend: 'cloudflare',
    mode: 'shell-workspace',
    loaderBinding: 'LOADER',
    cwd: '/',
  },
};

The generated wrangler.jsonc adds:

{
  "worker_loaders": [{ "binding": "LOADER" }]
}

Helpers for custom setup and explicit R2 hydration are exported from @fabric-harness/cloudflare/shell.

If Cloudflare sandboxing isn't configured, the Worker falls back to Fabric's empty sandbox.

How it maps to Fabric primitives

Fabric primitiveCloudflare equivalent
Session storeDurable Object (one DO instance per session id)
SandboxEnvCloudflare Sandbox container binding via @cloudflare/sandbox, or Cloudflare Shell Workspace via @cloudflare/shell
Model providerenv.AI Workers AI binding via CloudflareWorkersAIModelProvider (optional; HTTP providers also work)
Webhook triggerPOST /agents/:agent/:id
Health/manifestGET /health, GET /manifest

Workers AI binding (no API tokens)

@fabric-harness/cloudflare/workers-ai ships a ModelProvider that routes inference through env.AI.run() instead of HTTP. Zero API tokens, zero egress, runs at the edge. Workers AI accepts the OpenAI Chat Completions request body, so the provider serializes through the SDK's standard OpenAI helpers.

import { CloudflareWorkersAIModelProvider } from '@fabric-harness/cloudflare/workers-ai';

export default {
  async fetch(request: Request, env: Env) {
    const fabric = await init({
      modelProvider: new CloudflareWorkersAIModelProvider({
        binding: env.AI,
        defaultModel: '@cf/meta/llama-3.1-8b-instruct',
        // Optional: route through Cloudflare AI Gateway
        // gateway: { id: 'my-gateway', skipCache: false, cacheTtl: 3600 },
      }),
    });
    // ...
  },
};

Add the binding to wrangler.jsonc:

{
  "ai": { "binding": "AI" }
}

You can still use HTTP providers (Anthropic, OpenAI-compatible, Vercel AI Gateway) on the Cloudflare target — store the API key as a Workers Secret and reference it via env.

Live validation

For a production pilot, run the live-gated Cloudflare smoke in your account before rollout:

FABRIC_CLOUDFLARE_TEST=1 \
FABRIC_CLOUDFLARE_WORKER_URL=https://<worker>.<subdomain>.workers.dev \
FABRIC_CLOUDFLARE_ARTIFACT_DIR=/path/to/.fabricharness/build/cloudflare \
CLOUDFLARE_ACCOUNT_ID=<account-id> \
pnpm --filter @fabric-harness/cloudflare test -- live.test.ts

The smoke should verify /health, /ready, /manifest, agent invocation, session/timeline/metrics/tasks/approval/artifact routes, and R2 artifact behavior when a bucket binding is configured.

Limits and considerations

  • Worker request/CPU limits apply; long-running workflows belong on the Temporal worker target.
  • Sandbox container start latency depends on the Cloudflare image; warm pools help.
  • Persistent workspace backup/restore is deferred — design agents to be replayable from the session log and durable object/R2 artifacts rather than disk state.
  • Keep FABRIC_HARNESS_API_TOKEN, body limits, rate limits, and FABRIC_ENV=production trigger gating enabled for public deployments.