我用 Cloudflare Worker 搭了个 AI 网关,白嫖 Agnes + DeepSeek 双模型,还能给 Hermes 用
关键词:Cloudflare Worker、AI 网关、Agnes、DeepSeek、Hermes Agent、智能路由、故障转移
一、为什么要自己搭 AI 网关
最近在用 Hermes Agent 做自动化任务,但遇到几个痛点:
- 单一 API 不稳定:Agnes 便宜但偶尔限流,DeepSeek 稳定但贵
- 切换麻烦:每次换个模型都要改客户端配置
- Key 暴露风险:把上游 Key 直接写在客户端里,泄露了很危险
- workers.dev 被墙:想用 Cloudflare Worker 做中转,但默认域名国内访问不了
于是花了半天时间,用 Cloudflare Worker 搭了个智能路由网关,实现:
- ✅ Agnes 优先,DeepSeek 兜底:Agnes 限流/异常时自动降级
- ✅ 统一鉴权:客户端只拿一个 ACCESS_TOKEN,上游 Key 完全隐藏
- ✅ 自定义域名:绑定自己的域名,国内直连
- ✅ 支持流式输出:SSE 逐字返回,体验和官方一致
- ✅ 完全免费:Cloudflare Workers 免费额度每天 10 万请求
二、最终效果
先看结果。用 curl 测试:
bash
curl -X POST "https://api.061420.xyz/v1/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer 你的ACCESS_TOKEN" \
-d '{"model":"deepseek-flash","messages":[{"role":"user","content":"你好"}],"stream":false}'
返回:
json
{
"id": "a14aac65-...",
"model": "deepseek-flash",
"choices": [{
"message": {
"role": "assistant",
"content": "你好!有什么可以帮你的吗?"
}
}],
"usage": {"total_tokens": 85}
}
流式输出也完美:
《秋思》
霜枫染半秋,雁字过西楼。
暮色寒烟起,孤灯照客愁。
三、核心架构
scss
客户端 (Hermes/curl/ChatBox)
↓
api.061420.xyz (自定义域名)
↓
Cloudflare Worker (智能路由)
↓
┌─────────┐ ┌──────────┐
│ Agnes │ ──→ │ DeepSeek │
│ (优先) │ 降级 │ (兜底) │
└─────────┘ └──────────┘
降级触发条件:
- 401/403 鉴权失败
- 429 限流
- 5xx 服务端错误
- fetch 网络异常
不触发降级:
- 400 参数错误(客户端问题,换后端也没用)
四、完整代码(可直接部署)
1. Worker 核心代码
javascript
const AGNES_BASE_URL = "https://apihub.agnes-ai.com/v1";
const DEEPSEEK_BASE_URL = "https://api.deepseek.com/v1";
export default {
async fetch(request, env) {
const url = new URL(request.url);
// 权限验证
const clientAuth = request.headers.get("Authorization");
const expectedToken = `Bearer ${env.ACCESS_TOKEN}`;
if (!env.ACCESS_TOKEN) {
return new Response(
JSON.stringify({ error: "Server misconfigured" }),
{ status: 500, headers: { "Content-Type": "application/json" } }
);
}
if (clientAuth !== expectedToken) {
return new Response(
JSON.stringify({ error: "Unauthorized" }),
{ status: 401, headers: { "Content-Type": "application/json" } }
);
}
// 健康检查
if (url.pathname === "/" || url.pathname === "") {
return new Response(
JSON.stringify({ service: "router", status: "running" }),
{ status: 200, headers: { "Content-Type": "application/json" } }
);
}
if (!url.pathname.startsWith("/v1")) {
return new Response(
JSON.stringify({ error: "Not Found" }),
{ status: 404, headers: { "Content-Type": "application/json" } }
);
}
// 读取请求体
let body = undefined;
if (request.method === "POST") {
body = await request.text();
}
const upstreamPath = url.pathname.replace(/^\/v1/, "");
const agnesUrl = AGNES_BASE_URL + upstreamPath;
try {
const agnesRequest = new Request(agnesUrl, {
method: request.method,
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${env.AGNES_API_KEY}`,
},
body: body,
});
const agnesResponse = await fetch(agnesRequest);
if (
agnesResponse.status === 401 ||
agnesResponse.status === 403 ||
agnesResponse.status === 429 ||
agnesResponse.status >= 500
) {
throw new Error(`Agnes failed: ${agnesResponse.status}`);
}
return new Response(agnesResponse.body, {
status: agnesResponse.status,
headers: {
"Content-Type": agnesResponse.headers.get("Content-Type") || "application/json",
"X-Upstream": "Agnes",
},
});
} catch (error) {
console.warn("Agnes 不可用,切换到 DeepSeek:", error.message);
const deepseekUrl = DEEPSEEK_BASE_URL + upstreamPath;
try {
const deepseekRequest = new Request(deepseekUrl, {
method: request.method,
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${env.DEEPSEEK_API_KEY}`,
},
body: body,
});
const deepseekResponse = await fetch(deepseekRequest);
return new Response(deepseekResponse.body, {
status: deepseekResponse.status,
headers: {
"Content-Type": deepseekResponse.headers.get("Content-Type") || "application/json",
"X-Upstream": "DeepSeek",
},
});
} catch (deepseekError) {
return new Response(
JSON.stringify({ error: "Both upstreams unavailable" }),
{ status: 502, headers: { "Content-Type": "application/json" } }
);
}
}
},
};
2. Cloudflare 图形化部署步骤
第一步:创建 Worker
- 登录 Cloudflare Dashboard
- Workers & Pages → Create Worker → 命名
agnes-deepseek-router - 粘贴上面的代码,Deploy
第二步:配置环境变量
- Worker → Settings → Variables and Secrets
- 添加三个 Secret 类型变量:
AGNES_API_KEY:Agnes 平台的 KeyDEEPSEEK_API_KEY:DeepSeek 官方的 KeyACCESS_TOKEN:你自己生成的随机令牌(客户端用它鉴权)
第三步:绑定自定义域名(关键!)
- Worker → Settings → Domains & Routes → Add Custom Domain
- 输入
api.你的域名.com - 不要用 Route,用 Custom Domain,Cloudflare 会自动处理 DNS 和 SSL
⚠️ 避坑:
workers.dev域名在国内被 SNI 阻断,必须绑定自定义域名才能用。
五、配置 Hermes Agent
Hermes 支持自定义 OpenAI 兼容端点。最可靠的配置方式:
编辑 ~/.hermes/config.yaml:
yaml
model:
provider: custom:myrouter
default: deepseek-flash
custom_providers:
- name: myrouter
base_url: https://api.061420.xyz/v1
key_env: HERMES_ROUTER_KEY
model: deepseek-flash
api_mode: chat_completions
编辑 ~/.hermes/.env:
ini
HERMES_ROUTER_KEY=你的ACCESS_TOKEN值
验证:
bash
hermes chat -q "Reply with exactly: provider ok"
如果报 Provider authentication failed,去 ~/.hermes/logs/gateway.log 看 401 还是 404。401 是 Token 不匹配,404 是路径问题。
六、踩坑记录
坑 1:workers.dev 国内连不上 curl: (28) Failed to connect,不是代码问题,是域名被墙。必须绑自定义域名。
坑 2:自定义域名返回空 404 Content-Length: 0 的 404 是 Cloudflare 边缘返回的,说明请求没到 Worker。原因是用了 Route 通配符 *.域名/*,被其他路由吃掉了。改用 Custom Domain 解决。
坑 3:Agnes 返回 429 限流 免费额度用尽会限流。你的降级逻辑会自动切到 DeepSeek,但想用 Agnes 优先就得升级套餐或降低频率。
坑 4:模型名不匹配 Agnes 支持的模型是 deepseek-flash 和 deepseek-v4-pro,不是 agnes-3.0-flash。传错会返回 400。
七、总结
整套方案成本:
| 项目 | 成本 |
|---|---|
| Cloudflare Workers | 免费(10 万请求/天) |
| 自定义域名 | 已有域名即可 |
| Agnes 免费额度 | 免费(有限流) |
| DeepSeek 兜底 | 按量付费 |
核心价值:
- 一个域名统一入口,客户端零配置切换
- Agnes 优先,成本最低
- DeepSeek 兜底,可用性最高
- Token 统一鉴权,上游 Key 不暴露
如果你也在用 Hermes、ChatBox、NextChat 这类工具,强烈建议搭一个。半天时间,一劳永逸。
相关资源:
- Cloudflare Workers 文档:developers.cloudflare.com/workers/
- Hermes Agent 配置:hermes-agent.dev
如果这篇对你有帮助,点个赞再走~有问题评论区见!