Agent AtlasAI Agent 知识库
05.08工程化 · Engineering

在 Cloudflare 上部署 Agent

Workers、Durable Objects、Agents SDK、Vectorize、AI Gateway 与 Sandbox 的组合方式。

Cloudflare 不是「另一个云」,它的原语很适合 Agent:边缘接入、无状态计算、有状态对象、队列、工作流、向量库、对象存储,都在一个平台里。

下面涉及 Agents SDK / Workflows 的代码是骨架,具体 API 可能随版本变化,请以 Cloudflare 官方文档为准。

为什么考虑 Cloudflare

需求Cloudflare 能力
全球低延迟接入Workers + CDN
短任务 APIWorkers(Serverless)
有状态会话Durable Objects
Agent 抽象Agents SDK
长任务/重试Workflows
异步解耦Queues
向量检索Vectorize
文件存储R2
关系库D1 / Hyperdrive
模型调用Workers AI / AI Gateway
代码执行Sandbox / Containers
浏览器自动化Browser Rendering
前端Pages

对于「前端 + API + 轻量 Agent + 知识库」的产品,这套组合能显著减少运维。

Agents SDK 的核心模型

一个 Agent 本质上是一个有名字的 Durable Object:

  • 每个实例有独立状态(this.state);
  • 支持 WebSocket 长连接;
  • 可以定时任务(this.schedule);
  • 内置 SQLite(this.sql);
  • 状态变更会持久化,重启后可恢复;
  • 通过名称路由到同一个实例。
text
/agents/support-agent/user_123
        └─ 固定路由到 user_123 这个实例

这让「同一个用户的对话状态」天然一致,不需要额外的会话存储。

快速开始

bash
npm create cloudflare@latest -- --template=cloudflare/agents-starter
cd my-agent
npm install
npm run dev

部署:

bash
npx wrangler deploy

一个最小 Agent

ts
import { Agent, routeAgentRequest } from "agents";

type State = {
  messages: Array<{ role: "user" | "assistant"; content: string }>;
};

export class SupportAgent extends Agent<Env, State> {
  initialState: State = { messages: [] };

  async onRequest(request: Request): Promise<Response> {
    const { message } = await request.json<{ message: string }>();

    const history = [...this.state.messages, { role: "user" as const, content: message }];
    const result = await this.env.AI.run("@cf/meta/llama-3.1-8b-instruct", {
      messages: history,
    });

    const reply = (result as { response?: string }).response ?? "";
    this.setState({
      messages: [...history, { role: "assistant", content: reply }],
    });

    return Response.json({ reply });
  }
}

export default {
  async fetch(request: Request, env: Env) {
    return (
      (await routeAgentRequest(request, env)) ??
      new Response("Not found", { status: 404 })
    );
  },
};

wrangler.jsonc:

jsonc
{
  "name": "support-agent",
  "main": "src/index.ts",
  "compatibility_date": "2026-01-01",
  "durable_objects": {
    "bindings": [{ "name": "SupportAgent", "class_name": "SupportAgent" }]
  },
  "migrations": [{ "tag": "v1", "new_sqlite_classes": ["SupportAgent"] }],
  "ai": { "binding": "AI" }
}

访问 https://<worker>.workers.dev/agents/support-agent/user_123,同一 user_123 会命中同一个实例。

状态与持久化

ts
// 读取
const count = this.state.count ?? 0;

// 写入(会持久化)
this.setState({ ...this.state, count: count + 1 });

// SQLite,适合结构化数据
this.sql`CREATE TABLE IF NOT EXISTS events (id TEXT PRIMARY KEY, payload TEXT)`;
this.sql`INSERT INTO events (id, payload) VALUES (${id}, ${JSON.stringify(payload)})`;

原则:

  • 状态要小,别把大文件塞进 state;
  • 大对象放 R2,状态里存 key;
  • 结构化查询用 SQL,不要全量加载到内存;
  • 状态结构变更要考虑迁移。

长任务:Workflows

Workers 单次请求有 CPU/时间限制,不适合跑几分钟的循环。长任务用 Workflows:

ts
import { WorkflowEntrypoint, WorkflowStep } from "cloudflare:workers";

export class ResearchWorkflow extends WorkflowEntrypoint<Env, { topic: string }> {
  async run(event: WorkflowEvent<{ topic: string }>, step: WorkflowStep) {
    const plan = await step.do("plan", async () => {
      return await makePlan(event.payload.topic);
    });

    const docs = await step.do(
      "retrieve",
      { retries: { limit: 3, delay: "10 seconds", backoff: "exponential" } },
      async () => await retrieve(plan.queries)
    );

    const report = await step.do("write", async () => {
      return await writeReport(plan, docs);
    });

    await step.do("save", async () => {
      await this.env.BUCKET.put(`reports/${event.instanceId}.md`, report);
    });

    return { report };
  }
}

Workflows 提供:

  • 每一步的持久化与重试;
  • 可等待数天(例如人工审批);
  • 实例可查询、可恢复;
  • 适合「研究 → 写作 → 审核 → 发布」这类流程。

RAG:Vectorize + Workers AI + R2

ts
// 写入
const embedding = await this.env.AI.run("@cf/baai/bge-m3", { text: chunks });
await this.env.VECTORIZE.upsert(
  chunks.map((text, i) => ({
    id: `${docId}-${i}`,
    values: embedding.data[i],
    metadata: { docId, title, page: i },
  }))
);

// 查询
const q = await this.env.AI.run("@cf/baai/bge-m3", { text: [question] });
const matches = await this.env.VECTORIZE.query(q.data[0], {
  topK: 8,
  returnMetadata: "all",
});

要点:

  • 向量维度必须与索引一致;
  • metadata 放 tenant_id、doc_id、version,便于过滤;
  • 原文放 R2,按 doc_id 取;
  • 更新文档时先删旧向量,再写新向量;
  • 大规模导入用 Queue 分批,避免请求超时。

模型接入

三条路:

  1. Workers AI:平台托管模型,绑定即用,适合中小模型、Embedding、分类;
  2. AI Gateway:统一代理外部模型(OpenAI、Anthropic、Gemini 等),提供缓存、限流、重试、日志、成本分析;
  3. 直接 fetch:自己处理鉴权与重试,最灵活。

AI Gateway 的价值在于可观测与治理:

  • 按项目/用户统计 token 与成本;
  • 缓存相同请求;
  • 限流与回退;
  • 不把供应商密钥散落在各处。

代码执行与浏览器

  • Sandbox / Containers:在隔离环境运行模型生成的代码;
  • Browser Rendering:托管无头浏览器,适合抓取与自动化;
  • Queues:异步分发耗时任务;
  • Cron Triggers:定时任务。

不要让模型生成的代码直接跑在 Worker 主隔离里。用沙箱,限制文件、网络、CPU。

限制与坑

限制影响应对
单请求时间/CPU 限制长循环会超时用 Workflows / Queues
Durable Object 单线程同一实例串行按用户/会话分片
DO 有位置跨区域访问有延迟选择 locationHint,接受一致性权衡
冷启动首次请求变慢预热、减少依赖
存储计费状态/向量/请求都可能计费估算用量,设置预算
平台锁定迁移成本业务逻辑与平台 API 解耦
SDK 迭代API 变化锁定版本,关注变更

观测与运维

  • wrangler tail 看实时日志;
  • Workers Analytics 看请求、错误、CPU;
  • AI Gateway 看模型调用、成本、缓存命中;
  • Workflows 看实例状态与失败步骤;
  • 自建 trace:把 task_id 贯穿 Worker、Workflow、模型调用。

适合与不适合

适合:

  • 前端 + API + 轻量 Agent 一体;
  • 按用户/会话的有状态对话;
  • 全球低延迟接入;
  • 事件驱动、短任务;
  • 想减少运维的团队。

不适合:

  • 需要长时间 CPU 密集计算;
  • 需要复杂的事务与强一致;
  • 依赖特定 GPU/大模型自托管;
  • 已有成熟 Kubernetes 体系且不想迁移。

检查清单

  • Agent 实例按用户/会话正确分片
  • 状态小、可序列化、有迁移方案
  • 长任务放 Workflows/Queues,不阻塞请求
  • 模型调用经 AI Gateway 或统一封装
  • 向量索引维度、metadata、更新策略正确
  • 代码执行在沙箱
  • 有预算与用量告警
  • 锁定 SDK/兼容日期版本
  • trace 贯穿 Worker/Workflow/模型

小结

  • Cloudflare 的原语覆盖接入、计算、状态、队列、工作流、向量与存储。
  • Agents SDK 把「有名字的 Durable Object」包装成 Agent,天然支持会话状态。
  • 长任务用 Workflows,异步用 Queues,不要硬扛请求时限。
  • RAG 用 Vectorize + Workers AI + R2 组合。
  • 注意单线程、时间限制、位置与锁定风险。

下一篇是一份可以逐条打勾的上线清单。

读完了?进度会保存在本地浏览器。
内容会持续修订。发现错误或想补充,欢迎反馈。 遇到问题?查排查手册 →