> ## 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.

# Configuration

> Configure agents for local development and production deployment with wrangler.jsonc, types, and environment variables

This guide covers everything you need to configure agents for local development and production deployment, including wrangler.jsonc setup, type generation, environment variables, and the Cloudflare dashboard.

## wrangler.jsonc

The `wrangler.jsonc` file configures your Cloudflare Worker and its bindings. Here's a complete example for an agents project:

```jsonc wrangler.jsonc theme={null}
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "my-agent-app",
  "main": "src/server.ts",
  "compatibility_date": "2025-01-01",
  "compatibility_flags": ["nodejs_compat"],

  // Static assets (optional)
  "assets": {
    "directory": "public",
    "binding": "ASSETS"
  },

  // Durable Object bindings for agents
  "durable_objects": {
    "bindings": [
      {
        "name": "MyAgent",
        "class_name": "MyAgent"
      },
      {
        "name": "ChatAgent",
        "class_name": "ChatAgent"
      }
    ]
  },

  // Required: Enable SQLite storage for agents
  "migrations": [
    {
      "tag": "v1",
      "new_sqlite_classes": ["MyAgent", "ChatAgent"]
    }
  ],

  // AI binding (optional, for Workers AI)
  "ai": {
    "binding": "AI"
  }
}
```

### Key Fields

#### compatibility\_flags

The `nodejs_compat` flag is **required** for agents:

```jsonc theme={null}
"compatibility_flags": ["nodejs_compat"]
```

This enables Node.js compatibility mode, which agents depend on for crypto, streams, and other Node.js APIs.

#### durable\_objects.bindings

Each agent class needs a binding:

```jsonc theme={null}
"durable_objects": {
  "bindings": [
    {
      "name": "Counter",      // Property name on `env` (env.Counter)
      "class_name": "Counter" // Exported class name (must match exactly)
    }
  ]
}
```

| Field        | Description                                                 |
| ------------ | ----------------------------------------------------------- |
| `name`       | The property name on `env`. Use this in code: `env.Counter` |
| `class_name` | Must match the exported class name exactly                  |

**When name and class\_name differ:**

```jsonc theme={null}
{
  "name": "COUNTER_DO", // env.COUNTER_DO
  "class_name": "CounterAgent" // export class CounterAgent
}
```

This is useful when you want environment variable-style naming (`COUNTER_DO`) but more descriptive class names (`CounterAgent`).

#### migrations

Migrations tell Cloudflare how to set up storage for your Durable Objects:

```jsonc theme={null}
"migrations": [
  {
    "tag": "v1",
    "new_sqlite_classes": ["MyAgent"]
  }
]
```

| Field                | Description                                               |
| -------------------- | --------------------------------------------------------- |
| `tag`                | Version identifier (e.g., "v1", "v2"). Must be unique     |
| `new_sqlite_classes` | Agent classes that use SQLite storage (state persistence) |
| `deleted_classes`    | Classes being removed                                     |
| `renamed_classes`    | Classes being renamed                                     |

#### assets

For serving static files (HTML, CSS, JS):

```jsonc theme={null}
"assets": {
  "directory": "public",  // Folder containing static files
  "binding": "ASSETS"     // Optional: binding for programmatic access
}
```

With a binding, you can serve assets programmatically:

```typescript theme={null}
export default {
  async fetch(request: Request, env: Env) {
    // static assets are served by the worker automatically by default

    // route the request to the appropriate agent
    const agentResponse = await routeAgentRequest(request, env);
    if (agentResponse) return agentResponse;

    // add your own routing logic here if you want to handle requests that are not for agents
    return new Response("Not found", { status: 404 });
  }
};
```

#### ai

For Workers AI integration:

```jsonc theme={null}
"ai": {
  "binding": "AI",
  "remote": true  // Mandatory: use remote inference (for local dev)
}
```

Access in your agent:

```typescript theme={null}
const response = await this.env.AI.run("@cf/zai-org/glm-4.7-flash", {
  prompt: "Hello!"
});
```

## Generating Types

Wrangler can generate TypeScript types for your bindings.

### Automatic Generation

Run the types command:

```bash theme={null}
npx wrangler types
```

This creates or updates `worker-configuration.d.ts` with your `Env` type.

### Custom Output Path

Specify a custom path:

```bash theme={null}
npx wrangler types env.d.ts
```

### Without Runtime Types

For cleaner output (recommended for agents):

```bash theme={null}
npx wrangler types env.d.ts --include-runtime false
```

This generates just your bindings without Cloudflare runtime types.

### Example Generated Output

```typescript env.d.ts theme={null}
// Generated by wrangler
declare namespace Cloudflare {
  interface Env {
    OPENAI_API_KEY: string;
    Counter: DurableObjectNamespace<import("./src/server").Counter>;
    ChatAgent: DurableObjectNamespace<import("./src/server").ChatAgent>;
  }
}
interface Env extends Cloudflare.Env {}
```

### Adding to package.json

Add a script for easy regeneration:

```json package.json theme={null}
{
  "scripts": {
    "types": "wrangler types env.d.ts --include-runtime false"
  }
}
```

## Environment Variables and Secrets

### Local Development (.env)

Create a `.env` file for local secrets (add to `.gitignore`):

```bash .env theme={null}
OPENAI_API_KEY=sk-...
GITHUB_WEBHOOK_SECRET=whsec_...
DATABASE_URL=postgres://...
```

Access in your agent:

```typescript theme={null}
class MyAgent extends Agent<Env> {
  async onStart() {
    const apiKey = process.env.OPENAI_API_KEY;
  }
}
```

### Production Secrets

Use `wrangler secret` for production:

```bash theme={null}
# Add a secret
wrangler secret put OPENAI_API_KEY
# Enter value when prompted

# List secrets
wrangler secret list

# Delete a secret
wrangler secret delete OPENAI_API_KEY
```

### Non-Secret Variables

For non-sensitive configuration, use `vars` in wrangler.jsonc:

```jsonc theme={null}
{
  "vars": {
    "API_BASE_URL": "https://api.example.com",
    "MAX_RETRIES": "3",
    "DEBUG_MODE": "false"
  }
}
```

<Note>
  All values must be strings. Parse numbers/booleans in code:

  ```typescript theme={null}
  const maxRetries = parseInt(process.env.MAX_RETRIES, 10);
  const debugMode = process.env.DEBUG_MODE === "true";
  ```
</Note>

### Environment-Specific Variables

Use `env` sections for different environments (e.g. staging, production):

```jsonc theme={null}
{
  "name": "my-agent",
  "vars": {
    "API_URL": "https://api.example.com"
  },

  "env": {
    "staging": {
      "vars": {
        "API_URL": "https://staging-api.example.com"
      }
    },
    "production": {
      "vars": {
        "API_URL": "https://api.example.com"
      }
    }
  }
}
```

Deploy to specific environment:

```bash theme={null}
wrangler deploy --env staging
wrangler deploy --env production
```

## Local Development

### Starting the Dev Server

With Vite (recommended for full stack apps):

```bash theme={null}
npx vite dev
```

Without Vite:

```bash theme={null}
npx wrangler dev
```

### Local State Persistence

Durable Object state is persisted locally in `.wrangler/state/`:

```
.wrangler/
└── state/
    └── v3/
        └── d1/
            └── miniflare-D1DatabaseObject/
                └── ... (SQLite files)
```

### Clearing Local State

To reset all local Durable Object state:

```bash theme={null}
rm -rf .wrangler/state
```

Or restart with fresh state:

```bash theme={null}
npx wrangler dev --persist-to=""
```

### Inspecting Local SQLite

You can inspect agent state directly:

```bash theme={null}
# Find the SQLite file
ls .wrangler/state/v3/d1/

# Open with sqlite3
sqlite3 .wrangler/state/v3/d1/miniflare-D1DatabaseObject/*.sqlite
```

## Dashboard Setup

### Automatic Resources

When you deploy, Cloudflare automatically creates:

* **Worker** - Your deployed code
* **Durable Object namespaces** - One per agent class
* **SQLite storage** - Attached to each namespace

### Viewing Durable Objects

<Steps>
  <Step title="Go to Cloudflare Dashboard">
    Visit [dash.cloudflare.com](https://dash.cloudflare.com)
  </Step>

  <Step title="Select Workers and Pages">
    Select your account → Workers & Pages
  </Step>

  <Step title="Click your Worker">
    Click your Worker name
  </Step>

  <Step title="View Durable Objects">
    Go to **Durable Objects** tab
  </Step>
</Steps>

Here you can:

* See all Durable Object namespaces
* View individual object instances
* Inspect storage (keys and values)
* Delete objects

### Real-time Logs

View live logs from your agents:

```bash theme={null}
npx wrangler tail
```

Or in the dashboard:

1. Go to your Worker
2. Click **Logs** tab
3. Enable real-time logs

Filter by:

* Status (success, error)
* Search text
* Sampling rate

### Analytics

The dashboard shows:

* Request count
* Error rate
* CPU time
* Duration percentiles
* Durable Object metrics

## Production Deployment

### Basic Deploy

```bash theme={null}
npx wrangler deploy
```

This:

1. Bundles your code
2. Uploads to Cloudflare
3. Applies migrations
4. Makes it live on `*.workers.dev`

### Custom Domain

Add a route in wrangler.jsonc:

```jsonc theme={null}
{
  "routes": [
    {
      "pattern": "agents.example.com/*",
      "zone_name": "example.com"
    }
  ]
}
```

Or use a custom domain (simpler):

```jsonc theme={null}
{
  "routes": [
    {
      "pattern": "agents.example.com",
      "custom_domain": true
    }
  ]
}
```

### Preview Deployments

Deploy without affecting production:

```bash theme={null}
npx wrangler deploy --dry-run    # See what would be uploaded
npx wrangler versions upload     # Upload new version
npx wrangler versions deploy     # Gradually roll out
```

### Rollbacks

Roll back to a previous version:

```bash theme={null}
npx wrangler rollback
```

## Multi-Environment Setup

### Environment Configuration

Define environments in wrangler.jsonc:

```jsonc theme={null}
{
  "name": "my-agent",
  "main": "src/server.ts",

  // Base configuration (shared)
  "compatibility_date": "2025-01-01",
  "compatibility_flags": ["nodejs_compat"],
  "durable_objects": {
    "bindings": [{ "name": "MyAgent", "class_name": "MyAgent" }]
  },
  "migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyAgent"] }],

  // Environment overrides
  "env": {
    "staging": {
      "name": "my-agent-staging",
      "vars": {
        "ENVIRONMENT": "staging"
      }
    },
    "production": {
      "name": "my-agent-production",
      "vars": {
        "ENVIRONMENT": "production"
      }
    }
  }
}
```

### Deploying to Environments

```bash theme={null}
# Deploy to staging
npx wrangler deploy --env staging

# Deploy to production
npx wrangler deploy --env production

# Set secrets per environment
npx wrangler secret put OPENAI_API_KEY --env staging
npx wrangler secret put OPENAI_API_KEY --env production
```

### Separate Durable Objects

Each environment gets its own Durable Objects. Staging agents don't share state with production agents.

## Migrations

Migrations manage Durable Object storage schema changes.

### Adding a New Agent

Add to `new_sqlite_classes` in a new migration:

```jsonc theme={null}
"migrations": [
  {
    "tag": "v1",
    "new_sqlite_classes": ["ExistingAgent"]
  },
  {
    "tag": "v2",
    "new_sqlite_classes": ["NewAgent"]
  }
]
```

### Renaming an Agent Class

Use `renamed_classes`:

```jsonc theme={null}
"migrations": [
  {
    "tag": "v1",
    "new_sqlite_classes": ["OldName"]
  },
  {
    "tag": "v2",
    "renamed_classes": [
      {
        "from": "OldName",
        "to": "NewName"
      }
    ]
  }
]
```

<Warning>
  **Important:** Also update:

  1. The class name in code
  2. The `class_name` in bindings
  3. Export statements
</Warning>

### Deleting an Agent Class

Use `deleted_classes`:

```jsonc theme={null}
"migrations": [
  {
    "tag": "v1",
    "new_sqlite_classes": ["AgentToDelete", "AgentToKeep"]
  },
  {
    "tag": "v2",
    "deleted_classes": ["AgentToDelete"]
  }
]
```

<Warning>
  This permanently deletes all data for that class.
</Warning>

### Migration Best Practices

1. **Never modify existing migrations** - Always add new ones
2. **Use sequential tags** - v1, v2, v3 (or use dates: 2025-01-15)
3. **Test locally first** - Migrations run on deploy
4. **Back up production data** - Before renaming or deleting

## Troubleshooting

### "No such Durable Object class"

The class isn't in migrations:

```jsonc theme={null}
"migrations": [
  {
    "tag": "v1",
    "new_sqlite_classes": ["MissingClassName"]  // Add it here
  }
]
```

### "Cannot find module" in types

Regenerate types:

```bash theme={null}
npx wrangler types env.d.ts --include-runtime false
```

### Secrets not loading locally

Check that `.env` exists and contains the variable:

```bash theme={null}
cat .env
# Should show: MY_SECRET=value
```

### Migration tag conflict

Migration tags must be unique. If you see conflicts:

<CodeGroup>
  ```jsonc Wrong - Duplicate Tags theme={null}
  // Wrong - duplicate tags
  "migrations": [
    { "tag": "v1", "new_sqlite_classes": ["A"] },
    { "tag": "v1", "new_sqlite_classes": ["B"] }  // Error!
  ]
  ```

  ```jsonc Correct - Sequential Tags theme={null}
  // Correct - sequential tags
  "migrations": [
    { "tag": "v1", "new_sqlite_classes": ["A"] },
    { "tag": "v2", "new_sqlite_classes": ["B"] }
  ]
  ```
</CodeGroup>
