> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/cloudflare/agents/llms.txt
> Use this file to discover all available pages before exploring further.

# Codemode Example

> Project management chat app where LLMs write and execute TypeScript code to orchestrate tools instead of calling them one at a time

A project management chat app where the LLM writes and executes code to orchestrate tools, instead of calling them one at a time. Built with `@cloudflare/codemode` and `@cloudflare/ai-chat`.

## What it demonstrates

**Server (`src/server.ts`):**

* `AIChatAgent` with `createCodeTool` - the LLM gets a single "write code" tool
* `DynamicWorkerExecutor` - runs LLM-generated code in isolated Worker sandboxes
* `NodeServerExecutor` - alternative executor using a Node.js VM (for local dev)
* SQLite-backed tools (projects, tasks, sprints, comments) via `SqlStorage`
* Switchable executor at runtime via HTTP endpoint

**Client (`src/client.tsx`):**

* `useAgentChat` for streaming chat with message persistence
* Collapsible tool cards showing generated code, results, and console output
* Settings panel to switch between Dynamic Worker and Node Server executors
* Kumo design system components with dark/light mode

**Tools (`src/tools.ts`):**

* 10 project management tools: `createProject`, `listProjects`, `createTask`, `listTasks`, `updateTask`, `deleteTask`, `createSprint`, `listSprints`, `addComment`, `listComments`
* All backed by SQLite - data persists across conversations

## Why Codemode?

Traditional tool calling requires the LLM to call tools one at a time:

```
User: "Create a project Alpha with 3 tasks"

LLM: → Call createProject("Alpha")
← Returns projectId
LLM: → Call createTask(projectId, "Task 1")
← Returns taskId
LLM: → Call createTask(projectId, "Task 2")
← Returns taskId
LLM: → Call createTask(projectId, "Task 3")
← Returns taskId
LLM: "Done!"
```

With Codemode, the LLM writes code to orchestrate multiple operations:

````
User: "Create a project Alpha with 3 tasks"

LLM: → Writes and executes code:
```typescript
const projectId = await codemode.createProject("Alpha");
await Promise.all([
  codemode.createTask(projectId, "Task 1"),
  codemode.createTask(projectId, "Task 2"),
  codemode.createTask(projectId, "Task 3")
]);
return "Created project Alpha with 3 tasks";
````

← Returns result
LLM: "Done!"

````

Benefits:
- **Fewer round-trips** - complex operations complete in one step
- **Better composition** - LLM can use loops, conditionals, async/await
- **More control** - LLM can handle errors, retry, format results

## Server Implementation

```typescript src/server.ts
import { createWorkersAI } from "workers-ai-provider";
import { routeAgentRequest } from "agents";
import { AIChatAgent } from "@cloudflare/ai-chat";
import { createCodeTool } from "@cloudflare/codemode";
import { DynamicWorkerExecutor } from "@cloudflare/codemode/executors/dynamic-worker";
import { streamText } from "ai";
import { tools } from "./tools";

export class CodeModeAgent extends AIChatAgent {
  async onChatMessage() {
    const workersai = createWorkersAI({ binding: this.env.AI });
    
    // Create executor for running LLM-generated code
    const executor = new DynamicWorkerExecutor();

    const result = streamText({
      model: workersai("@cf/zai-org/glm-4.7-flash"),
      system:
        "You are a project management assistant. You can create projects, tasks, " +
        "sprints, and comments. Use the codemode tool to write TypeScript code " +
        "that orchestrates multiple operations efficiently.",
      messages: await convertToModelMessages(this.messages),
      tools: {
        // Single "write code" tool instead of individual tools
        ...createCodeTool({
          executor,
          tools,  // Tools available to the LLM's code
          storage: new SqlStorage(this.sql)  // SQLite backend
        })
      }
    });

    return result.toUIMessageStreamResponse();
  }
}
````

## Tool Definitions

```typescript src/tools.ts theme={null}
import { z } from "zod";
import type { ToolDefinition } from "@cloudflare/codemode";

export const tools: Record<string, ToolDefinition> = {
  createProject: {
    description: "Create a new project",
    parameters: z.object({
      name: z.string().describe("Project name")
    }),
    returns: z.object({
      projectId: z.string(),
      name: z.string()
    })
  },

  listProjects: {
    description: "List all projects",
    parameters: z.object({}),
    returns: z.array(z.object({
      projectId: z.string(),
      name: z.string(),
      createdAt: z.string()
    }))
  },

  createTask: {
    description: "Create a new task in a project",
    parameters: z.object({
      projectId: z.string(),
      title: z.string(),
      description: z.string().optional()
    }),
    returns: z.object({
      taskId: z.string(),
      projectId: z.string(),
      title: z.string()
    })
  },

  listTasks: {
    description: "List tasks in a project",
    parameters: z.object({
      projectId: z.string()
    }),
    returns: z.array(z.object({
      taskId: z.string(),
      title: z.string(),
      status: z.enum(["todo", "in_progress", "done"])
    }))
  },

  updateTask: {
    description: "Update a task's status or details",
    parameters: z.object({
      taskId: z.string(),
      status: z.enum(["todo", "in_progress", "done"]).optional(),
      title: z.string().optional()
    }),
    returns: z.object({
      taskId: z.string(),
      updated: z.boolean()
    })
  }
};
```

## Example Conversations

**Simple creation:**

```text theme={null}
User: Create a project called Alpha

LLM generates code:
const project = await codemode.createProject("Alpha");
return `Created project ${project.name} with ID ${project.projectId}`;

Result: "Created project Alpha with ID abc-123"
```

**Batch operations:**

```text theme={null}
User: Add 5 tasks to project xyz-789

LLM generates code:
const tasks = await Promise.all([
  codemode.createTask("xyz-789", "Task 1"),
  codemode.createTask("xyz-789", "Task 2"),
  codemode.createTask("xyz-789", "Task 3"),
  codemode.createTask("xyz-789", "Task 4"),
  codemode.createTask("xyz-789", "Task 5")
]);
return `Created ${tasks.length} tasks`;

Result: "Created 5 tasks"
```

**Complex query:**

```text theme={null}
User: List all projects and their task counts

LLM generates code:
const projects = await codemode.listProjects();
const results = await Promise.all(
  projects.map(async (p) => {
    const tasks = await codemode.listTasks(p.projectId);
    return { name: p.name, taskCount: tasks.length };
  })
);
return JSON.stringify(results, null, 2);

Result: JSON with project names and task counts
```

## Executors

Codemode supports two execution modes:

### Dynamic Worker Executor (Production)

Runs code in isolated Cloudflare Workers:

```typescript theme={null}
import { DynamicWorkerExecutor } from "@cloudflare/codemode/executors/dynamic-worker";

const executor = new DynamicWorkerExecutor();
```

* **Secure** - Full sandbox isolation
* **Fast** - V8 isolates, no cold starts
* **Scalable** - Runs on Cloudflare's edge

### Node Server Executor (Development)

Runs code in a Node.js VM:

```typescript theme={null}
import { NodeServerExecutor } from "@cloudflare/codemode/executors/node-server";

const executor = new NodeServerExecutor({
  url: "http://localhost:3001"
});
```

* **Debugging** - Full Node.js inspector support
* **Local** - No network latency
* **Quick iteration** - Hot reload

Start the Node executor:

```bash theme={null}
npm run start:node-executor
```

## Running the Example

<Steps>
  <Step title="Install dependencies">
    ```bash theme={null}
    npm install   # from repo root
    npm run build # from repo root
    ```
  </Step>

  <Step title="Start the example">
    ```bash theme={null}
    cd examples/codemode
    npm start
    ```
  </Step>

  <Step title="Try it out">
    Visit [http://localhost:5173](http://localhost:5173) and try:

    * "Create a project called Alpha"
    * "Add 3 tasks to Alpha"
    * "What is 17 + 25?" (simple calculation)
    * "List all projects and their tasks"
  </Step>

  <Step title="(Optional) Start Node executor">
    For local debugging:

    ```bash theme={null}
    npm run start:node-executor
    ```

    Then switch to Node executor in the Settings panel.
  </Step>
</Steps>

<Note>
  This example uses Workers AI (no API key needed) with `@cf/zai-org/glm-4.7-flash`.
</Note>

## Key Concepts

### Code Generation

The LLM receives a special "write code" tool:

```typescript theme={null}
{
  name: "codemode",
  description: "Execute TypeScript code with access to these tools: createProject, listProjects, createTask, ...",
  inputSchema: z.object({
    code: z.string().describe("TypeScript code to execute")
  })
}
```

When called, the code is:

1. Validated and transpiled
2. Executed in a secure sandbox
3. Results returned to the LLM

### Tool Access

Generated code has access to tools via the `codemode` object:

```typescript theme={null}
// LLM-generated code
const project = await codemode.createProject("My Project");
const tasks = await codemode.listTasks(project.projectId);
return `Found ${tasks.length} tasks`;
```

### Error Handling

The LLM can handle errors in its code:

```typescript theme={null}
try {
  const project = await codemode.createProject(name);
  return `Created project ${project.projectId}`;
} catch (error) {
  return `Failed to create project: ${error.message}`;
}
```

## Security

Codemode is safe because:

* **Sandboxed execution** - Code runs in isolated Workers/VMs
* **No file system access** - Can't read/write files
* **No network access** - Can't make arbitrary HTTP requests
* **Limited APIs** - Only approved tools are available
* **Timeout enforcement** - Code execution is time-limited

## Related Examples

<CardGroup cols={2}>
  <Card title="AI Chat" icon="comments" href="/examples/ai-chat">
    Traditional tool calling with streaming
  </Card>

  <Card title="Dynamic Tools" icon="wrench" href="/examples/dynamic-tools">
    Client-defined tools at runtime
  </Card>

  <Card title="Workflows" icon="diagram-project" href="/examples/workflows">
    Multi-step workflows with approval gates
  </Card>

  <Card title="Codemode Package" icon="book" href="/packages/codemode">
    Full Codemode package documentation
  </Card>
</CardGroup>
