Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ This source repository also contains examples that demonstrate how to integrate
- **[OpenAI Agents](examples/openai-agents/research-assistant)** - Research assistant using OpenAI Agents SDK
- **[Firecracker](examples/firecracker)** - Minimal Firecracker VM with AgentFS mounted via NFSv3
- **[AI SDK + just-bash](examples/ai-sdk-just-bash)** - Interactive AI agent using Vercel AI SDK with just-bash for command execution
- **[Cloudflare Workers](examples/cloudflare)** - AI agent using AI SDK + just-bash on Cloudflare Workers with Durable Objects storage

See the **[examples](examples)** directory for more details.

Expand Down
3 changes: 3 additions & 0 deletions examples/cloudflare/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/
dist/
.wrangler/
42 changes: 42 additions & 0 deletions examples/cloudflare/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# AI Agent with AgentFS on Cloudflare

This example demonstrates running an AI agent with persistent filesystem storage on Cloudflare Workers using:

- **AgentFS** for persistent file storage (backed by Durable Objects SQLite)
- **just-bash** for bash command execution in a virtual environment
- **Workers AI** for LLM inference (Llama 3.1 70B)
- **AI SDK** for the agent framework

## Setup

```bash
npm install
```

## Development

```bash
npm run dev
```

## Deploy

```bash
npm run deploy
```

## Usage

Send a message to the agent:

```bash
curl -X POST https://your-worker.workers.dev/chat \
-H "Content-Type: application/json" \
-d '{"message": "Create a file called hello.txt with Hello World"}'
```

The agent can:
- Create, read, update, and delete files
- Create directories
- List directory contents
- All files persist across sessions in Durable Objects SQLite storage
22 changes: 22 additions & 0 deletions examples/cloudflare/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "cloudflare-agentfs-example",
"version": "1.0.0",
"description": "AI Agent with AgentFS on Cloudflare Workers",
"type": "module",
"scripts": {
"dev": "wrangler dev",
"deploy": "wrangler deploy",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"agentfs-sdk": "file:../../sdk/typescript",
"ai": "^6.0.0",
"just-bash": "^1.0.1",
"workers-ai-provider": "^3.0.0"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20241218.0",
"typescript": "^5.3.0",
"wrangler": "^3.99.0"
}
}
111 changes: 111 additions & 0 deletions examples/cloudflare/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/**
* AI Agent with AgentFS on Cloudflare Workers
*
* This example shows how to run an AI agent with just-bash and AgentFS
* on Cloudflare Workers using Durable Objects for persistent storage
* and Workers AI for inference.
*
* Deploy:
* npm install
* npm run deploy
*
* Then send prompts:
* curl -X POST https://your-worker.workers.dev/chat \
* -H "Content-Type: application/json" \
* -d '{"message": "List all files in the root directory"}'
*/

import { DurableObject } from "cloudflare:workers";
import { streamText } from "ai";
import { createWorkersAI } from "workers-ai-provider";
import { createBashTool } from "just-bash/ai";
import { AgentFS, type CloudflareStorage } from "agentfs-sdk/cloudflare";
import { agentfs } from "agentfs-sdk/just-bash";

export interface Env {
AGENT_FS: DurableObjectNamespace<AgentFSDurableObject>;
AI: Ai;
}

/**
* Durable Object that provides an AI agent with persistent filesystem.
*/
export class AgentFSDurableObject extends DurableObject<Env> {
private fs: AgentFS;

constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env);
this.fs = AgentFS.create(ctx.storage as CloudflareStorage);
}

async chat(message: string): Promise<ReadableStream<Uint8Array>> {
// Wrap the AgentFS for just-bash compatibility
const bashFs = await agentfs({ fs: this.fs });

// Create the bash tool with the persistent filesystem
const bashTool = createBashTool({
fs: bashFs,
extraInstructions: `You are an AI agent with a persistent filesystem.
Files you create will persist across sessions.

Use bash commands to interact with the filesystem:
- ls to list files
- cat <file> to read files
- echo "content" > file.txt to write files
- mkdir <dir> to create directories
- rm <file> to remove files`,
});

// Create Workers AI provider
const workersai = createWorkersAI({ binding: this.env.AI });

// Stream the response
const result = streamText({
model: workersai("@cf/meta/llama-3.1-70b-instruct"),
tools: { bash: bashTool },
messages: [{ role: "user", content: message }],
maxSteps: 10,
});

return result.toDataStream();
}
}

export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);

if (url.pathname === "/chat" && request.method === "POST") {
const { message } = await request.json<{ message: string }>();

if (!message) {
return new Response("Missing message", { status: 400 });
}

// Route to the Durable Object
const id = env.AGENT_FS.idFromName("default");
const stub = env.AGENT_FS.get(id);
const stream = await stub.chat(message);

return new Response(stream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
},
});
}

return new Response(
`AI Agent with AgentFS on Cloudflare

POST /chat - Send a message to the agent

Example:
curl -X POST ${url.origin}/chat \\
-H "Content-Type: application/json" \\
-d '{"message": "Create a file called hello.txt with Hello World"}'
`,
{ headers: { "Content-Type": "text/plain" } }
);
},
};
13 changes: 13 additions & 0 deletions examples/cloudflare/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"lib": ["ES2022"],
"types": ["@cloudflare/workers-types"]
},
"include": ["src/**/*.ts"]
}
14 changes: 14 additions & 0 deletions examples/cloudflare/wrangler.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name = "agentfs-cloudflare-example"
main = "src/index.ts"
compatibility_date = "2024-12-18"

[ai]
binding = "AI"

[[durable_objects.bindings]]
name = "AGENT_FS"
class_name = "AgentFSDurableObject"

[[migrations]]
tag = "v1"
new_sqlite_classes = ["AgentFSDurableObject"]
4 changes: 4 additions & 0 deletions sdk/typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
"./just-bash": {
"import": "./dist/integrations/just-bash/index.js",
"types": "./dist/integrations/just-bash/index.d.ts"
},
"./cloudflare": {
"import": "./dist/integrations/cloudflare/index.js",
"types": "./dist/integrations/cloudflare/index.d.ts"
}
},
"keywords": [
Expand Down
Loading