Introduction: Taking Your Flue Agent to the Edge

So far, we’ve focused on building powerful, sandboxed AI agents locally with Flue. But what happens when you’re ready to share your intelligent creations with the world? How do you move from a local npm run dev to a globally available, scalable, and reliable service?

This chapter is your guide to deploying Flue agents to Cloudflare Workers, a powerful serverless platform designed for edge computing. We’ll explore why Workers are an excellent fit for Flue’s agent harness architecture, walk through the setup, and tackle the critical considerations for production environments, especially around state management.

By the end of this chapter, you’ll be able to confidently deploy your Flue agents, making them accessible and performant for users across the globe. You’ll need a basic Flue agent from previous chapters, a Cloudflare account, and the wrangler CLI installed.

Why Cloudflare Workers for Flue Agents?

Cloudflare Workers offer a compelling platform for deploying AI agents due to their unique characteristics that align well with Flue’s design principles.

Edge Computing for Low Latency

Cloudflare’s global network is vast, with data centers in hundreds of cities worldwide. When you deploy a Worker, your code runs on servers geographically close to your users.

📌 Key Idea: Edge computing brings your agent closer to the user, significantly reducing network latency.

For AI agents that might involve multiple turns or tool calls, minimizing latency is crucial for a responsive user experience. Instead of a request traveling halfway across the world to a central server, it hits an “edge” server nearby, processes the agent’s logic, and returns a response rapidly.

Serverless Architecture and Scalability

Cloudflare Workers operate as a serverless platform. This means:

  • No Server Management: You write code; Cloudflare handles the underlying infrastructure, patching, and scaling.
  • Automatic Scaling: As traffic to your agent increases, Cloudflare automatically scales up your Worker instances to handle the load, and scales down when demand subsides. This is ideal for unpredictable AI agent traffic patterns.
  • Cost-Effective: You typically pay only for the compute time and requests your Worker consumes, making it highly efficient for intermittent or variable workloads.

Flue’s AgentRouteHandler and the Worker fetch API

Flue’s AgentRouteHandler is designed to expose your agents over HTTP or WebSockets. Cloudflare Workers are primarily event-driven, with the core entry point being the fetch handler that processes incoming HTTP requests. This is a perfect match.

When a request arrives at a Cloudflare Worker, it invokes a fetch event listener. Your Flue AgentRouteHandler can seamlessly integrate into this, processing the request and generating a response, just as it would in a Node.js environment.

flowchart TD User_Request[User Request] --> Cloudflare_Edge[Cloudflare Edge Network]; Cloudflare_Edge --> Worker_Instance[Cloudflare Worker Instance]; Worker_Instance --> Flue_Handler[Flue Handler]; Flue_Handler --> LLM_API[LLM Provider API]; LLM_API --> Flue_Handler; Flue_Handler --> Worker_Instance; Worker_Instance --> Cloudflare_Edge; Cloudflare_Edge --> Agent_Response[Agent Response];

The diagram above illustrates how a user request flows through Cloudflare’s edge network to your Flue agent running within a Worker. The AgentRouteHandler acts as the bridge, processing requests and interacting with external services like LLM providers.

Setting Up Your Cloudflare Environment

Before deploying, you need to prepare your Cloudflare account and local development environment.

1. Create a Cloudflare Account

If you don’t have one, sign up for a free Cloudflare account at https://www.cloudflare.com/. Many of the Worker features, including a generous free tier, are available without a paid plan.

2. Install the wrangler CLI

wrangler is Cloudflare’s command-line interface for developing, testing, and deploying Workers.

Open your terminal and install wrangler globally:

npm install -g wrangler@latest

⚡ Quick Note: As of 2026-06-03, wrangler is consistently updated. Always use @latest or check the official Cloudflare Workers documentation for the most current stable version to ensure compatibility.

3. Authenticate wrangler

Once installed, you need to link wrangler to your Cloudflare account:

wrangler login

This command will open a browser window, prompt you to log in to Cloudflare, and authorize wrangler. Follow the on-screen instructions. Once complete, your terminal will confirm successful authentication.

4. Configure Your Project with wrangler.toml

Every Cloudflare Worker project uses a wrangler.toml file for configuration. This file tells wrangler how to build and deploy your Worker.

You’ll create this file in the root of your Flue project. It specifies your Worker’s name, type, entry point, and any environment variables or bindings (like KV stores).

Adapting Your Flue Agent for Cloudflare Workers

Flue’s AgentRouteHandler is designed for flexibility. To run it inside a Cloudflare Worker, you simply need to expose it as the Worker’s fetch handler.

Let’s assume you have a basic Flue agent, perhaps from a previous chapter, located in src/agent.ts or similar.

// src/agent.ts
import { Agent, AgentFunction } from "@flue/core";

const helloFunction: AgentFunction = {
  name: "hello",
  description: "Says hello to a given name.",
  parameters: {
    type: "object",
    properties: {
      name: { type: "string", description: "The name to say hello to." },
    },
    required: ["name"],
  },
  async execute({ name }: { name: string }) {
    return `Hello, ${name}! Welcome to the Flue agent.`;
  },
};

export const myAgent = new Agent({
  name: "GreeterAgent",
  description: "An agent that greets people.",
  functions: [helloFunction],
  llmConfig: {
    model: "claude-3-opus-20240229", // Or your preferred LLM
  },
});

Now, let’s create the entry point for your Cloudflare Worker. This will typically be src/index.ts.

// src/index.ts
import { AgentRouteHandler } from "@flue/server";
import { myAgent } from "./agent"; // Import your agent

// Create an AgentRouteHandler instance
const agentHandler = new AgentRouteHandler({
  agent: myAgent,
  // Optional: Configure a base path if you want to serve the agent under a specific URL segment
  // basePath: "/api/greeter",
});

// Cloudflare Worker's entry point: the fetch handler
export default {
  async fetch(
    request: Request,
    env: Env, // Env contains bindings like KV, D1, etc.
    ctx: ExecutionContext
  ): Promise<Response> {
    // Pass the request to the Flue AgentRouteHandler
    // The handler will process the request (e.g., /chat, /invoke, /socket)
    // and return a standard Response object.
    return agentHandler.fetch(request);
  },
};

interface Env {
  // Define any Cloudflare bindings here, e.g.,
  // MY_KV_NAMESPACE: KVNamespace;
  // MY_D1_DATABASE: D1Database;
}

In this index.ts, we import our myAgent and create an AgentRouteHandler. The fetch function, which is the standard entry point for a Cloudflare Worker, then simply delegates the incoming request to agentHandler.fetch(). This makes the integration incredibly straightforward.

Step-by-Step Deployment

Let’s walk through the process of setting up a new Flue project and deploying it.

1. Initialize a New Flue Project

If you don’t have one, create a new Flue project.

mkdir flue-worker-agent
cd flue-worker-agent
npm init -y
npm install @flue/core @flue/server typescript @types/node
npx tsc --init

Update tsconfig.json to include "moduleResolution": "bundler" and "target": "ES2022", and ensure outDir is set to ./dist.

2. Create Your Agent and Worker Entry Point

Create src/agent.ts and src/index.ts as shown in the “Adapting Your Flue Agent” section above.

3. Configure wrangler.toml

Create a wrangler.toml file in the root of your project:

# wrangler.toml
name = "flue-greeter-agent" # Your unique worker name
main = "src/index.ts"      # The entry point for your Worker
compatibility_date = "2024-01-01" # Required for modern Workers, pick a recent date
compatibility_flags = ["nodejs_compat"] # Enables Node.js polyfills for better compatibility

# Optional: Add environment variables for your LLM API Key
# You should set these securely via `wrangler secret put` in production.
# For local development, you can use .dev.vars
[vars]
OPENAI_API_KEY = "YOUR_OPENAI_KEY" # Replace with your LLM's API key variable name

🧠 Important: The compatibility_date and compatibility_flags = ["nodejs_compat"] are crucial. nodejs_compat provides polyfills for Node.js APIs that Flue might rely on, making deployment smoother. Always set compatibility_date to a recent date to opt into the latest Worker features and bug fixes.

4. Set Environment Variables Securely

For sensitive information like LLM API keys, you should use wrangler secret put. This encrypts the variable and makes it available to your Worker at runtime without being committed to your repository.

wrangler secret put OPENAI_API_KEY
# It will prompt you to enter the value for OPENAI_API_KEY

For local development, you can create a .dev.vars file (which should be .gitignored) at the root of your project:

# .dev.vars
OPENAI_API_KEY="sk-YOUR_TEST_KEY"

Then, in your Flue agent, you would access this variable via process.env:

// src/agent.ts (modified LLM config)
// ...
export const myAgent = new Agent({
  // ...
  llmConfig: {
    model: "claude-3-opus-20240229",
    apiKey: process.env.OPENAI_API_KEY, // Access from env
  },
});

5. Add Deployment Scripts to package.json

Add a deploy script to your package.json:

{
  "name": "flue-worker-agent",
  "version": "1.0.0",
  "description": "",
  "main": "dist/index.js",
  "scripts": {
    "build": "tsc",
    "deploy": "wrangler deploy",
    "start": "wrangler dev"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@flue/core": "latest",
    "@flue/server": "latest"
  },
  "devDependencies": {
    "@types/node": "latest",
    "typescript": "latest",
    "wrangler": "latest"
  }
}

6. Deploy Your Agent!

First, ensure your TypeScript compiles:

npm run build

Then, deploy your Worker:

npm run deploy

wrangler will compile your Worker (if not already done), upload it to Cloudflare, and provide you with the public URL where your agent is accessible. It might also prompt you to confirm the deployment.

7. Test Your Deployed Agent

Once deployed, you can test it using curl or a browser. If your AgentRouteHandler is configured for a default /chat endpoint, you might try:

curl -X POST "https://YOUR_WORKER_URL/chat" \
     -H "Content-Type: application/json" \
     -d '{
           "messages": [
             {"role": "user", "content": "Say hello to Alice using the hello function."}
           ]
         }'

Replace YOUR_WORKER_URL with the URL provided by wrangler deploy. You should receive a JSON response containing your agent’s reply.

Persistent State in a Serverless Environment: Production Considerations

One of the biggest challenges with serverless functions like Cloudflare Workers is their stateless nature. Each invocation of your Worker might run on a different instance, meaning local memory or filesystem changes are not persistent across requests or sessions.

For Flue agents, especially those designed for complex coding tasks or multi-turn interactions, maintaining state (e.g., session history, tool output, sandboxed filesystem changes) is critical.

⚠️ What can go wrong: Relying on in-memory state for a Flue agent deployed to Workers will lead to lost context, broken sessions, and unpredictable behavior.

Solutions for Persistent State: Cloudflare Offerings

Cloudflare provides several services to address state management for Workers:

  1. Cloudflare KV (Key-Value Store):

    • What it is: A globally distributed, eventually consistent key-value store.
    • Why it exists: Ideal for storing simple session data, configuration, or cached responses.
    • How it works: You bind a KV namespace to your Worker, then use its API (env.MY_KV_NAMESPACE.put("key", "value")) to store and retrieve data.
    • ⚡ Real-world insight: Excellent for storing user session IDs mapped to serialized agent states or chat histories.
  2. Cloudflare D1 (Serverless Database):

    • What it is: A serverless SQL database built on SQLite, running at the edge.
    • Why it exists: For more structured data, complex queries, or relational needs.
    • How it works: Bind a D1 database to your Worker, then use its API (env.MY_D1_DATABASE.prepare("SELECT * FROM users").all()) to interact with it.
    • ⚡ Real-world insight: Perfect for storing agent knowledge bases, user profiles, or detailed interaction logs.
  3. Cloudflare R2 (Object Storage):

    • What it is: S3-compatible object storage.
    • Why it exists: For large files, media, or agent-generated assets.
    • How it works: Bind an R2 bucket to your Worker, then use its API to put and get objects.
    • ⚡ Real-world insight: Useful if your coding agent generates large code files, images, or documentation that needs to be stored and retrieved.

Integrating Persistent State with Flue

Flue’s Agent constructor can accept a stateStore option. For Workers, you would implement a custom StateStore that interacts with one of Cloudflare’s persistent storage solutions.

// Example: A simplified custom KV-backed state store interface
import { AgentState, StateStore } from "@flue/core";

class CloudflareKVStateStore implements StateStore {
  private kv: KVNamespace;

  constructor(kvNamespace: KVNamespace) {
    this.kv = kvNamespace;
  }

  async get(key: string): Promise<AgentState | undefined> {
    const stateJson = await this.kv.get(key);
    return stateJson ? JSON.parse(stateJson) : undefined;
  }

  async set(key: string, state: AgentState): Promise<void> {
    await this.kv.put(key, JSON.stringify(state));
  }

  async delete(key: string): Promise<void> {
    await this.kv.delete(key);
  }
}

// In src/index.ts or where your agent is defined:
// Make sure to configure the KV binding in wrangler.toml and Env interface
// const kvStore = new CloudflareKVStateStore(env.MY_KV_NAMESPACE);
// const myAgent = new Agent({ /* ..., */ stateStore: kvStore });

This conceptual example demonstrates how you’d wrap Cloudflare’s KV API with Flue’s StateStore interface. In a real application, you’d ensure proper error handling, serialization, and potentially caching.

Mini-Challenge: Deploy a Stateful Agent

Let’s enhance our previous agent to conceptually use state, and ensure it deploys correctly.

Challenge: Modify your flue-worker-agent project to include a simple “counter” agent. This agent won’t persist its count yet (as that requires actual KV setup), but it will demonstrate how an agent would manage a session-scoped counter if a StateStore were provided. Deploy this updated agent to Cloudflare Workers.

  1. Update src/agent.ts: Add a new function to your GreeterAgent that increments a counter. This counter will be in-memory for now, but imagine it being part of the AgentState.
    // src/agent.ts
    import { Agent, AgentFunction } from "@flue/core";
    
    interface MyAgentState {
      count: number;
    }
    
    const helloFunction: AgentFunction = {
      name: "hello",
      description: "Says hello to a given name.",
      parameters: {
        type: "object",
        properties: {
          name: { type: "string", description: "The name to say hello to." },
        },
        required: ["name"],
      },
      async execute({ name }: { name: string }) {
        return `Hello, ${name}! Welcome to the Flue agent.`;
      },
    };
    
    const incrementCounterFunction: AgentFunction<MyAgentState> = {
      name: "incrementCounter",
      description: "Increments a session counter and returns its new value.",
      parameters: { type: "object", properties: {} }, // No parameters for simplicity
      async execute(_params, { state }) {
        state.count = (state.count || 0) + 1;
        return `Counter incremented to ${state.count}.`;
      },
    };
    
    export const myAgent = new Agent<MyAgentState>({
      name: "GreeterAgent",
      description: "An agent that greets people and counts.",
      functions: [helloFunction, incrementCounterFunction],
      llmConfig: {
        model: "claude-3-opus-20240229", // Or your preferred LLM
        apiKey: process.env.OPENAI_API_KEY,
      },
      // Initialize default state for new sessions
      initialState: { count: 0 },
    });
  2. Ensure src/index.ts and wrangler.toml are correctly configured from previous steps.
  3. Run npm run build and npm run deploy.
  4. Test the deployed agent:
    # First call
    curl -X POST "https://YOUR_WORKER_URL/chat" \
         -H "Content-Type: application/json" \
         -d '{
               "messages": [
                 {"role": "user", "content": "Increment the counter."}
               ]
             }'
    
    # Second call (expect count 1, then 2, etc. if session is maintained,
    # but due to stateless Workers, it will likely reset to 1 each time without KV)
    curl -X POST "https://YOUR_WORKER_URL/chat" \
         -H "Content-Type: application/json" \
         -d '{
               "messages": [
                 {"role": "user", "content": "Increment the counter again."}
               ]
             }'

What to observe/learn: Without an external StateStore (like KV), each call to “increment the counter” will likely result in “Counter incremented to 1.” This highlights the stateless nature of Workers and the critical need for external persistence for stateful agents. If you were using wrangler dev locally, the count might persist across calls from the same client due to local session handling, but this won’t happen on a deployed Worker.

Common Pitfalls & Troubleshooting

Deploying to serverless environments can have its quirks. Here are a few common issues and how to approach them:

  1. wrangler Authentication Issues:

    • Problem: wrangler reports “Not authorized” or fails to deploy.
    • Solution: Re-run wrangler login to refresh your authentication token. Ensure your Cloudflare account has the necessary permissions for Workers.
  2. Environment Variable Management:

    • Problem: Agent fails because process.env.OPENAI_API_KEY is undefined.
    • Solution: Verify you’ve set secrets using wrangler secret put for production deployments. For local testing with wrangler dev, ensure your .dev.vars file is correctly formatted and present. Remember, variables set in wrangler.toml are for build-time or non-sensitive configurations.
  3. Cold Starts:

    • Problem: The first request to your Worker after a period of inactivity is slow.
    • Solution: This is inherent to serverless. Cloudflare Workers are generally very fast at cold starts (often <50ms), but for extremely latency-sensitive applications, consider strategies like “warming” (sending periodic dummy requests) or Cloudflare’s “Always On” feature (if available and suitable for your budget/plan).
  4. Resource Limits:

    • Problem: Worker crashes with “Exceeded CPU limit” or “Memory limit exceeded.”
    • Solution: Cloudflare Workers have limits on CPU time (e.g., 50ms for free tier, 30s for paid) and memory. Complex agent operations, very long LLM interactions, or large tool outputs can hit these.
      • Optimize agent logic: Streamline tool calls, reduce unnecessary processing.
      • Chunk large inputs/outputs: Process data in smaller batches.
      • Offload heavy computation: If an agent task is truly compute-intensive, consider offloading parts to a dedicated compute service, and using the Worker as an orchestrator.
  5. nodejs_compat issues:

    • Problem: Some Node.js APIs used by Flue or its dependencies don’t work as expected.
    • Solution: Ensure compatibility_flags = ["nodejs_compat"] is set in wrangler.toml. If specific Node.js modules are still problematic, you might need to find Worker-compatible alternatives or polyfills, or abstract those parts of your agent.

Summary: Agents Live at the Edge

In this chapter, we’ve taken a significant step from local development to global deployment.

Here are the key takeaways:

  • Cloudflare Workers are an excellent fit for Flue agents due to their edge computing capabilities, serverless scalability, and direct integration with Flue’s AgentRouteHandler.
  • wrangler is your essential tool for managing and deploying Workers, handling authentication, and configuring your project via wrangler.toml.
  • Adapting your Flue agent is straightforward, primarily involving exposing the AgentRouteHandler through the Worker’s fetch API.
  • Persistent state is a critical consideration for production Flue agents on Workers. Cloudflare KV, D1, and R2 offer robust solutions for managing session data, structured information, and large assets.
  • Troubleshooting involves checking wrangler config, environment variables, and understanding serverless constraints like cold starts and resource limits.

You now have the knowledge to deploy your Flue agents to a powerful, globally distributed platform. This opens up immense possibilities for building responsive, scalable AI products.

References

This page is AI-assisted and reviewed. It references official documentation and recognized resources where relevant.