# Mounting Cloudflare R2 Buckets as Read-Only Knowledge Base Filesystems with Flue

> Mount Cloudflare R2 buckets as read-only knowledge base filesystems with Flue. Combine SQLite Durable Objects and R2 binding for tool-based search operations.

- Repository: [Astro/flue](https://github.com/withastro/flue)
- Tags: how-to-guide
- Published: 2026-05-11

---

**Mount a Cloudflare R2 bucket as a read-only POSIX filesystem inside a Flue agent's sandbox by using `getVirtualSandbox()` to combine SQLite-backed Durable Objects with your R2 binding, exposing files at `/workspace` for tool-based search operations.**

Flue's SDK enables you to mount Cloudflare R2 buckets as read-only knowledge base filesystems that persist across agent invocations without container overhead. This architecture creates a virtual sandbox where large documentation corpora or product catalogs remain instantly searchable via standard Unix tools like `grep` and `glob`. By combining Cloudflare's object storage with Durable Object SQLite persistence, agents gain durable, low-latency access to massive knowledge bases directly within their execution environment.

## How the Virtual Sandbox Architecture Works

The R2 integration relies on a virtual filesystem implementation that bridges Cloudflare's object storage with a POSIX-compatible interface. When you initialize an agent with `getVirtualSandbox(env.KNOWLEDGE_BASE)`, the SDK constructs a `WorkspaceFileSystem` that combines your R2 bucket binding with a local SQLite store from the Durable Object's [`storage.sql`](https://github.com/withastro/flue/blob/main/storage.sql) instance.

According to the source code in [`packages/sdk/src/cloudflare/virtual-sandbox.ts`](https://github.com/withastro/flue/blob/main/packages/sdk/src/cloudflare/virtual-sandbox.ts), the system performs three critical operations:

1. **Workspace Construction** – Lines 94-111 create a Cloudflare Workspace from the Worker's Durable Object SQLite database and the R2 bucket binding passed via the environment.

2. **POSIX Adaptation** – The `adaptToJustBash` wrapper transforms the R2-backed filesystem into a POSIX-compatible interface that `just-bash` expects, mounting the entire structure at `/workspace` (lines 117-121).

3. **Session Injection** – When `init({ sandbox, ... })` receives this environment, it injects the filesystem into the agent's session, allowing the LLM to invoke `read`, `glob`, and `grep` tools against remote R2 objects as if they were local files.

Because the sandbox runs inside a Cloudflare Worker with Durable Objects, the SQLite layer ensures that filesystem metadata and any uploaded changes survive across invocations, as documented in [`docs/deploy-cloudflare.md`](https://github.com/withastro/flue/blob/main/docs/deploy-cloudflare.md) (lines 44-48).

## Creating an R2-Backed Knowledge Base Agent

To mount an R2 bucket as a knowledge base, import `getVirtualSandbox` from the Cloudflare SDK module and pass your R2 binding to the initialization function:

```typescript
// .flue/agents/support.ts
import { getVirtualSandbox } from '@flue/sdk/cloudflare';
import type { FlueContext } from '@flue/sdk/client';

export const triggers = { webhook: true };

export default async function ({ init, payload, env }: FlueContext) {
  // env.KNOWLEDGE_BASE references the R2 binding defined in wrangler.jsonc
  const sandbox = await getVirtualSandbox(env.KNOWLEDGE_BASE);
  
  const harness = await init({ 
    sandbox, 
    model: 'openrouter/moonshotai/kimi-k2.6' 
  });
  
  const session = await harness.session();

  // The agent now has native access to grep, glob, and read tools
  return await session.prompt(
    `You are a support agent. Search the knowledge base for articles
    relevant to this request, then write a helpful response.

    Customer: ${payload.message}`,
    { role: 'triager' },
  );
}

```

**Key implementation details:**

- **`getVirtualSandbox(env.KNOWLEDGE_BASE)`** – Instantiates the virtual sandbox backed by your R2 bucket and Durable Object storage (virtual-sandbox.ts, lines 94-111).
- **`init({ sandbox, ... })`** – Supplies the POSIX-compatible filesystem to the Flue harness so the LLM executes within this environment (deploy-cloudflare.md, lines 176-182).
- **`session.prompt()`** – Automatically injects filesystem tools enabling the agent to search `/workspace` using semantic equivalents of `grep`, `glob`, and `read`.

## Configuring R2 Bindings in Wrangler

Before deploying, declare the R2 bucket binding in your project's `wrangler.jsonc`. Flue merges this configuration during the build process to ensure the binding is available in the Worker environment:

```jsonc
{
  "name": "my-support-agent",
  "compatibility_date": "2026-04-01",
  "compatibility_flags": ["nodejs_compat"],
  "r2_buckets": [
    {
      "binding": "KNOWLEDGE_BASE",
      "bucket_name": "my-knowledge-base"
    }
  ]
}

```

When you execute `flue build --target cloudflare`, the build system automatically merges this binding into `dist/wrangler.jsonc`, ensuring `wrangler deploy` provisions the correct permissions (deploy-cloudflare.md, lines 109-115).

## Uploading Files to Your Knowledge Base

Populate the R2 bucket using the Wrangler CLI. Files uploaded to the bucket become immediately available under `/workspace` inside the agent's sandbox:

```bash

# Upload a single documentation file

wrangler r2 object put my-knowledge-base/articles/getting-started.md \
  --file ./docs/getting-started.md

# Batch upload an entire documentation directory

for f in ./docs/**/*.md; do
  key="articles/${f#./docs/}"
  wrangler r2 object put "my-knowledge-base/$key" --file "$f"
done

```

The agent can then traverse these paths using `glob` patterns or search content using `grep`, treating the remote R2 objects as local POSIX files.

## Summary

- **Mount R2 buckets** using `getVirtualSandbox(env.KNOWLEDGE_BASE)` to create a POSIX-compatible filesystem backed by Cloudflare's object storage and Durable Object SQLite persistence.
- **Access files at `/workspace`** where the virtual sandbox presents R2 objects as local files, supporting standard Unix tool equivalents like `grep`, `glob`, and `read`.
- **Configure bindings** in `wrangler.jsonc` and rely on Flue's build process to merge them automatically for deployment.
- **Persist across requests** because the architecture uses Durable Objects, ensuring filesystem state survives between agent invocations without container cold starts.

## Frequently Asked Questions

### Can I write files back to the R2 bucket from the agent?

Yes, while the knowledge base pattern typically uses read-only access, the virtual sandbox supports read-write operations. Writes are cached in the Durable Object's SQLite layer ([`storage.sql`](https://github.com/withastro/flue/blob/main/storage.sql)) and can persist to R2 depending on your implementation. However, for pure knowledge base use cases, configure the bucket with read-only permissions in your Wrangler configuration to prevent accidental modifications.

### How does this differ from mounting a local filesystem?

Unlike ephemeral local filesystems that disappear when the container exits, this approach uses **Cloudflare R2** for durable storage combined with **Durable Objects** for session persistence. According to the implementation in [`packages/sdk/src/cloudflare/virtual-sandbox.ts`](https://github.com/withastro/flue/blob/main/packages/sdk/src/cloudflare/virtual-sandbox.ts), the filesystem survives across HTTP requests because the SQLite metadata and R2 bindings persist in the Cloudflare edge infrastructure, eliminating cold start overhead while maintaining terabyte-scale storage capacity.

### What file sizes work best with this approach?

The virtual sandbox architecture handles large text corpora efficiently because it streams data from R2 on demand rather than loading entire buckets into memory. However, individual files that the agent reads via the `read` tool should remain under the LLM's context window limits. Binary files and assets store correctly in R2 but require text extraction (like PDF parsing) before the agent can process them with `grep` or similar tools.

### Do I need to manage SQLite schemas manually?

No. Flue automatically manages the SQLite schema within the Durable Object's storage. The `getVirtualSandbox` function handles the connection to [`storage.sql`](https://github.com/withastro/flue/blob/main/storage.sql) and the R2 binding without requiring manual database configuration. The schema tracks filesystem metadata while the actual file contents remain in R2, creating a hybrid storage layer that requires zero DevOps maintenance.