Anthropic 的 Claude 不只是聊天模型——它正在变成一个能自主调用工具、编排多步骤任务的 Agent。但 Agent 要落地,最难的不是模型本身,而是运行环境:它需要访问你的内部 API、需要稳定的执行沙箱、还需要有人盯着它到底干了什么。Cloudflare 最近上线了 Claude Managed Agents 支持,把这三件事一起搬到了边缘网络上。
Agent 托管,为什么要在 Cloudflare 上做?
传统做法是自己在 VPS 或 Kubernetes 里跑一个 Agent 服务:写一个长驻进程,调 Anthropic API,处理工具调用循环,再挂上日志和监控。这套东西能跑,但维护成本不低——尤其是 Agent 本质上是"有状态的长连接服务",和典型无状态 Web 服务的运维模式不一样。
Cloudflare 的方案把 Agent 的生命周期管理塞进了 Workers 运行时:
- 冷启动快:Workers 的启动延迟在毫秒级,Agent 不用等一个笨重的容器拉起来。
- 全球分布:Agent 可以跑在离用户或离数据源最近的节点,减少往返延迟。
- 天然集成 Cloudflare 生态:D1 数据库、R2 存储、KV 缓存、Queue 消息队列,Agent 的工具调用可以直接用这些绑定,不需要自己搭基础设施。
连接私有系统:Agent 不再是"外网孤岛"
Agent 最常见的落地障碍是——它够不到你的内部服务。数据库在内网、ERP 系统在 VPN 后面、CI/CD 管道只在公司机房里暴露。让 Agent 直接访问这些资源,要么开公网端口(安全团队摇头),要么搞反向隧道(运维团队叹气)。
Cloudflare 的做法是利用已有的 Tunnel 和 Zero Trust 能力:
- 在内网机器上跑
cloudflared tunnel,把内部服务暴露到 Cloudflare 边缘。 - Agent 通过 Workers 环境内的私有域名(不经过公网 DNS)访问这些服务。
- 访问策略由 Cloudflare Access 控制,可以按身份、设备、IP 限流。
这意味着 Agent 的工具调用可以直达你的 PostgreSQL、Jira API、内部 Git 服务——而这些服务完全不需要对互联网开放。
运行时选择:Workers 还是 Containers?
不是所有 Agent 都能塞进 Workers。有些任务需要长时间运行(比如批量处理十万条记录),有些需要装自定义二进制(比如调用本地 OCR 引擎)。Cloudflare 提供了两种运行时:
| 运行时 | 适合场景 | 限制 |
|---|---|---|
| Workers | 短任务、工具调用少、响应快 | CPU 时间 30s(付费版可更长),无本地文件系统 |
| Containers(Cloudflare Containers) | 长任务、需要自定义环境 | 启动稍慢,但可持久运行 |
对于典型的 Claude Agent——接收用户指令、调几个 API、返回结果——Workers 绝大多数情况下够用。如果你要跑"持续监控 + 定时巡检"类 Agent,Containers 更合适。
实战:用 Workers 跑一个 Claude Agent
下面是一个最小可运行的示例:一个 Cloudflare Worker 接收用户消息,调用 Claude 的 Agent 模式(带工具使用),并把工具调用结果返回给用户。
1. 项目结构
claude-agent-worker/
├── wrangler.toml
├── src/
│ └── index.ts
└── package.json
2. Wrangler 配置
name = "claude-agent-worker"
main = "src/index.ts"
compatibility_date = "2024-12-01"
# Anthropic API 密钥,用 secret 管理——不要硬编码
# 部署后执行: wrangler secret put ANTHROPIC_API_KEY
[vars]
CLAUDE_MODEL = "claude-sonnet-4-20250514"
3. Worker 代码
// src/index.ts
export interface Env {
ANTHROPIC_API_KEY: string;
CLAUDE_MODEL: string;
}
// 定义 Agent 可用的工具——这里给一个查天气的示例
const tools = [
{
name: "get_weather",
description: "获取指定城市的当前天气信息",
input_schema: {
type: "object",
properties: {
city: { type: "string", description: "城市名称,如 Beijing" },
},
required: ["city"],
},
},
];
// 工具执行函数——实际项目中可替换为内部 API 调用
async function executeTool(name: string, input: Record<string, unknown>): Promise<string> {
if (name === "get_weather") {
// 示例:调用公开天气 API
// 生产环境可替换为通过 Tunnel 访问的内部气象服务
const city = input.city as string;
const resp = await fetch(
`https://wttr.in/${encodeURIComponent(city)}?format=j1`
);
const data = await resp.json() as any;
const current = data.current_condition?.[0];
return `${city} 当前温度 ${current?.temp_C}°C,湿度 ${current?.humidity}%,天气 ${current?.weatherDesc?.[0]?.value}`;
}
return `未知工具: ${name}`;
}
// Agent 循环:消息 → Claude → 工具调用 → 结果 → 再送回 Claude → 最终回复
async function runAgent(userMessage: string, env: Env): Promise<string> {
const messages: any[] = [{ role: "user", content: userMessage }];
// 最多循环 5 次,防止无限工具调用
for (let i = 0; i < 5; i++) {
const response = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: {
"x-api-key": env.ANTHROPIC_API_KEY,
"anthropic-version": "2023-06-01",
"content-type": "application/json",
},
body: JSON.stringify({
model: env.CLAUDE_MODEL,
max_tokens: 4096,
tools,
messages,
}),
});
const result = await response.json() as any;
// 收集 Claude 的输出内容块
const contentBlocks = result.content as any[];
messages.push({ role: "assistant", content: contentBlocks });
// 检查是否包含工具调用
const toolUseBlocks = contentBlocks.filter((b: any) => b.type === "tool_use");
if (toolUseBlocks.length === 0) {
// 没有工具调用,提取文本回复并返回
const textBlocks = contentBlocks.filter((b: any) => b.type === "text");
return textBlocks.map((b: any) => b.text).join("\n");
}
// 执行所有工具调用,构造 tool_result 消息
const toolResults = await Promise.all(
toolUseBlocks.map(async (block: any) => {
const output = await executeTool(block.name, block.input);
return {
type: "tool_result",
tool_use_id: block.id,
content: output,
};
})
);
messages.push({ role: "user", content: toolResults });
}
return "Agent 达到最大循环次数,请简化你的请求。";
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
if (request.method !== "POST") {
return new Response("Send POST with { message: '...' }", { status: 405 });
}
const body = await request.json() as { message?: string };
if (!body.message) {
return new Response("Missing 'message' field", { status: 400 });
}
try {
const reply = await runAgent(body.message, env);
return Response.json({ reply });
} catch (err: any) {
return Response.json({ error: err.message }, { status: 500 });
}
},
};
4. 部署与测试
# 安装依赖
npm install -g wrangler
npm init -y
npm install @cloudflare/workers-types
# 登录 Cloudflare
wrangler login
# 设置 Anthropic API Key(不会出现在代码或 wrangler.toml 里)
wrangler secret put ANTHROPIC_API_KEY
# 粘贴你的密钥,回车
# 部署
wrangler deploy
# 测试
curl -X POST https://claude-agent-worker.<your-subdomain>.workers.dev \
-H "Content-Type: application/json" \
-d '{"message": "北京今天天气怎么样?"}'
预期返回类似:
{
"reply": "根据查询结果,北京当前温度 28°C,湿度 45%,天气晴。适合户外活动。"
}
5. 接入内部服务(进阶)
如果你想让 Agent 调用内网 API,只需在目标机器上跑一条 Tunnel:
# 在内网服务器上安装并启动 cloudflared
cloudflared tunnel create my-agent-tunnel
cloudflared tunnel route dns internal-api.your-team.com my-agent-tunnel
cloudflared tunnel --url http://localhost:8080 run my-agent-tunnel
然后在 Worker 的 executeTool 里,把 fetch 地址换成 https://internal-api.your-team.com/...——这个域名在 Cloudflare 边缘网络内可解析,外部完全看不到。
可观测:盯着 Agent 别跑偏
Agent 自主执行任务,意味着它可能调错 API、传错参数、甚至陷入死循环。Cloudflare 提供了几层监控手段:
- Workers Logs:
wrangler tail实时看 Agent 每次请求的日志输出。 - Workers Analytics:按时间维度看调用次数、错误率、CPU 耗时。
- Cloudflare Observability(Logpush):把 Workers 日志推到你的 SIEM 或数据平台,做长期审计。
建议在 Agent 循环里加结构化日志,记录每次工具调用的输入输出:
// 在 executeTool 函数内加入日志
console.log(JSON.stringify({
event: "tool_call",
tool: name,
input: input,
output_preview: output.slice(0, 200),
timestamp: Date.now(),
}));
部署后用 wrangler tail --format json 实时消费这些日志,或者通过 Logpush 写到 R2 / 外部分析平台。
上线前的 Checklist
| 检查项 | 说明 |
|---|---|
| API Key 用 Secret 管理 | 不要写在 wrangler.toml 或代码里 |
| 工具调用加循环上限 | 防止 Agent 陷入无限工具调用 |
| 内网服务走 Tunnel + Access | 不开公网端口,按身份限流 |
| 结构化日志 | 每次工具调用记录输入输出摘要 |
| 错误兜底 | executeTool 捕获异常,返回友好错误而非让 Agent 崩溃 |
| 模型选择 | 简单任务用 Haiku 省成本,复杂编排用 Sonnet 或 Opus |
Cloudflare 把 Agent 的运行、联网、观测打包进同一套边缘基础设施,省掉了自建运维的不少麻烦。但 Agent 的可靠性仍然取决于你的工具定义质量和错误处理——基础设施托底,逻辑层还得自己把关。