Building a Cloudflare Workers AI agent is the next step in moving from simple AI prompts to autonomous workflows. These systems, known as AI agents, use Large Language Models (LLMs) to call external tools, make decisions, and execute tasks on their own. While running agents traditionally required heavy servers, this tutorial demonstrates how to build and host serverless AI agents using Cloudflare Workers and LangChain.js .
TL;DR
- Understand AI agents; agents use LLMs to make decisions and call external APIs (tools) to solve user queries autonomously.
- Utilise LangChain.js on the edge; LangChain.js is fully compatible with Cloudflare Workers’ lightweight V8 runtime.
- Write custom tools to fetch data, read databases, or execute logic from your Worker fetch handler.
- Leverage serverless bindings; connect your agent to Cloudflare D1 for SQL state memory, or KV for session caching.
- Enforce guardrails and timeouts to prevent infinite execution loops and control token API costs.
What is an AI Agent?
A standard chatbot is a simple request-response loop: you send a prompt, and the model returns text. A Cloudflare Workers AI agent, by contrast, acts autonomously. You define the agent’s goal and provide it with a set of “tools” (custom JavaScript functions that fetch APIs, search databases, or execute arithmetic). The model decides which tools to call, inspects the tool output, and loops until it solves your request. This agentic logic is highly suited to complex customer support, background automation, and database management. For details on setting up basic edge APIs, see our guide on building a serverless API with Cloudflare Workers .
Prerequisites
Before you start, make sure you have the following in place:
- A Cloudflare account with Workers enabled (the free plan is enough to follow along).
- Node.js 18 or newer and the Wrangler CLI (
npm install -g wrangler). - An OpenAI API key, or credentials for another provider LangChain.js supports.
- Basic familiarity with JavaScript promises and the Workers
fetchhandler.
Install the LangChain packages you need. Import narrowly rather than pulling in the whole framework, because Workers enforce a compressed bundle-size limit:
1{
2 "dependencies": {
3 "@langchain/openai": "^0.3.0",
4 "@langchain/core": "^0.3.0",
5 "langchain": "^0.3.0"
6 },
7 "devDependencies": {
8 "wrangler": "^3.0.0"
9 }
10}
Integrating LangChain.js with Workers
LangChain is a popular framework for building LLM applications. The JavaScript version (LangChain.js) is designed to run on web-standard APIs, making it fully compatible with Cloudflare’s lightweight V8 runtime.
To start, you initialise the agent inside your Worker’s fetch handler:
1import { ChatOpenAI } from "@langchain/openai";
2import { initializeAgentExecutorWithOptions } from "langchain/agents";
3import { DynamicTool } from "@langchain/core/tools";
4
5export default {
6 async fetch(request, env) {
7 // 1. Define custom tools for the agent
8 const databaseTool = new DynamicTool({
9 name: "DatabaseQuery",
10 description: "Queries the customer database for billing status.",
11 func: async (input) => {
12 // Query database (e.g. Cloudflare D1)
13 return `Customer ${input} billing status is Active.`;
14 }
15 });
16
17 const tools = [databaseTool];
18
19 // 2. Initialize the reasoning model
20 const model = new ChatOpenAI({
21 apiKey: env.OPENAI_API_KEY,
22 modelName: "gpt-4o-mini"
23 });
24
25 // 3. Create the executor
26 const executor = await initializeAgentExecutorWithOptions(tools, model, {
27 agentType: "openai-functions",
28 });
29
30 // 4. Run the query
31 const result = await executor.call({ input: "Check status for Customer 101" });
32 return Response.json(result);
33 }
34};
This setup runs entirely at the edge, close to your users, with near-zero cold starts. If you want to configure local models serverless instead of calling OpenAI, explore our Cloudflare Workers AI tutorial .
Configuring the Worker Project
LangChain.js relies on a handful of Node.js built-ins, so your Worker will not compile until you enable the nodejs_compat flag. Set it in wrangler.toml, alongside any bindings your tools use:
1name = "ai-agent-worker"
2main = "src/index.js"
3compatibility_date = "2024-09-23"
4compatibility_flags = ["nodejs_compat"]
5
6[[d1_databases]]
7binding = "DB"
8database_name = "agent-memory"
9database_id = "<your-database-id>"
Never hard-code your API key. Store it as an encrypted secret instead:
1npx wrangler secret put OPENAI_API_KEY
For local development, place the same value in a .dev.vars file (added to .gitignore) so wrangler dev can read it without exposing the key in source control.
Managing State and Agent Memory
Because serverless Workers are stateless between requests, you must provide the agent with a memory system to store conversation histories.
You can connect your agent to a serverless SQL database like Cloudflare D1. When the agent receives a request, it queries D1 to retrieve the previous message thread, passes it to the reasoning model, and saves the new response back to the database. To learn how to set up relational tables, see the Cloudflare D1 edge database setup .
In practice, a minimal message store needs just two helpers: one to load the thread and one to append each new turn. Create the table with CREATE TABLE messages (id INTEGER PRIMARY KEY, session_id TEXT, role TEXT, content TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);, then wire it up:
1async function loadHistory(db, sessionId) {
2 const { results } = await db
3 .prepare(
4 "SELECT role, content FROM messages WHERE session_id = ? ORDER BY created_at ASC"
5 )
6 .bind(sessionId)
7 .all();
8 return results ?? [];
9}
10
11async function saveMessage(db, sessionId, role, content) {
12 await db
13 .prepare("INSERT INTO messages (session_id, role, content) VALUES (?, ?, ?)")
14 .bind(sessionId, role, content)
15 .run();
16}
Load the history at the start of each request, pass it to the model as prior context, then save both the user input and the agent’s final answer before returning the response. For short-lived sessions where durability does not matter, Cloudflare KV is a cheaper choice than D1.
Guardrails and Cost Control in Production
Because agents run in loops (reasoning → tool execution → reasoning), a poorly defined agent can enter an infinite loop, rapidly inflating your API billing.
- Set Max Iterations: Cap the maximum number of loops the agent can execute (e.g., limit to 5 turns).
- Configure Timeouts: Cloudflare Workers enforce CPU execution limits. Ensure your tools resolve quickly to prevent request cancellation.
- Implement Rate Limiting: Protect your edge endpoint from token abuse by applying rate limits.
In code, the executor options make the first two guardrails explicit:
1const executor = await initializeAgentExecutorWithOptions(tools, model, {
2 agentType: "openai-functions",
3 maxIterations: 5,
4 earlyStoppingMethod: "generate",
5 verbose: false,
6});
With maxIterations set, the loop stops after five reasoning cycles even if the model has not yet produced a final answer, which caps the worst-case token spend per request.
For a detailed look at context management, see our guide on building an OpenAI API chatbot .
Common Pitfalls and Troubleshooting
Most first deployments fail for a small set of predictable reasons. The table below maps the error you are likely to see to its cause and its fix:
| Symptom | Likely cause | Fix |
|---|---|---|
Cannot find module 'node:async_hooks' at build time | The nodejs_compat flag is missing | Add compatibility_flags = ["nodejs_compat"] and a recent compatibility_date |
| Bundle exceeds the size limit on deploy | Barrel imports pulling in the whole framework | Import from specific subpaths (@langchain/openai) and drop unused tools |
OPENAI_API_KEY is not defined | Secret not set, or missing .dev.vars locally | Run wrangler secret put; add the key to .dev.vars for wrangler dev |
| Request times out under load | A slow tool or a runaway loop | Lower maxIterations; add timeouts inside each tool’s func |
| Agent ignores a tool it should use | Vague tool description | Rewrite the description to state exactly when the model should call it |
Two subtleties are worth calling out. First, Workers separate wall-clock time from CPU time: waiting on an LLM or database response counts as I/O, not CPU, so long model calls rarely breach the CPU limit on their own, but heavy JSON parsing inside a tight loop can. Second, the quality of an agent’s decisions depends heavily on how you describe its tools. Treat each description field as a prompt in its own right and be specific about the input it expects, or the model will call the wrong tool.
Testing and Deploying to Production
Develop against a local runtime before you ship. wrangler dev runs your Worker in the same Workerd engine Cloudflare uses in production, so behaviour matches the edge closely:
1npx wrangler dev # local iteration with hot reload
2npx wrangler deploy # publish to the edge
Once live, you need visibility into the agent’s reasoning loops. Enable observability so tool calls and errors are captured, then stream logs in real time:
1[observability]
2enabled = true
Use npx wrangler tail to watch requests as they happen. Beyond logging, a few habits keep production agents healthy: validate and sanitise any user input before it reaches a tool that touches your database; return a graceful fallback message when the model exceeds its iteration cap rather than surfacing a raw error; and monitor token usage per session so a single abusive caller cannot run up your bill. For higher-throughput workloads, consider streaming the response so users see output as it is generated rather than waiting for the entire loop to finish.
Key Takeaways
- AI agents use reasoning models to decide which custom tools to call to solve complex queries.
- LangChain.js runs efficiently within Cloudflare Workers’ lightweight V8 isolate runtime.
- Define custom tools as JavaScript functions connecting to databases, APIs, or files.
- Persist agent memory across stateless requests by utilising Cloudflare D1 serverless SQL.
- Implement loop iteration caps and request timeouts to control API costs and prevent execution crashes.
Scale Your Agentic Workflows
Building production-ready AI agents requires expert knowledge of serverless architecture, database engineering, and prompt design. Mecanik provides professional AI integration services and dedicated development teams through the hire a web developer page. We build fast, secure agentic systems that automate operations and scale cleanly. Contact us today to discuss your next build.
Frequently Asked Questions (FAQ)
What is the difference between an AI chatbot and an AI agent? An AI chatbot only returns text answers to prompts. An AI agent is autonomous: it evaluates your request and decides which external APIs (tools) to run in a loop to complete the task.
Can I run LangChain on Cloudflare Workers? Yes. LangChain.js is designed using web-standard APIs, making it fully compatible with Cloudflare Workers’ V8 engine, which does not run full Node.js.
How do I give an AI agent access to my databases? You wrap database queries inside a LangChain custom tool. When the agent decides it needs database info, it calls the tool function, which executes the query.
How do I prevent an AI agent from looping forever?
You configure a maximum iteration limit in the agent executor (e.g., maxIterations: 5) and implement strict timeouts on your tool functions.
What is the best hosting for AI agents? Serverless edge hosting like Cloudflare Workers is ideal because it offers global distribution, near-zero cold starts, and binds directly to databases like D1 and R2.
Comments