我用 Cloudflare Worker 搭了个 AI 网关,白嫖 Agnes + DeepSeek 双模型,还能给 Hermes 用

0 阅读4分钟

我用 Cloudflare Worker 搭了个 AI 网关,白嫖 Agnes + DeepSeek 双模型,还能给 Hermes 用

关键词:Cloudflare Worker、AI 网关、Agnes、DeepSeek、Hermes Agent、智能路由、故障转移

一、为什么要自己搭 AI 网关

最近在用 Hermes Agent 做自动化任务,但遇到几个痛点:

  1. 单一 API 不稳定:Agnes 便宜但偶尔限流,DeepSeek 稳定但贵
  2. 切换麻烦:每次换个模型都要改客户端配置
  3. Key 暴露风险:把上游 Key 直接写在客户端里,泄露了很危险
  4. workers.dev 被墙:想用 Cloudflare Worker 做中转,但默认域名国内访问不了

于是花了半天时间,用 Cloudflare Worker 搭了个智能路由网关,实现:

  • ✅ Agnes 优先,DeepSeek 兜底:Agnes 限流/异常时自动降级
  • ✅ 统一鉴权:客户端只拿一个 ACCESS_TOKEN,上游 Key 完全隐藏
  • ✅ 自定义域名:绑定自己的域名,国内直连
  • ✅ 支持流式输出:SSE 逐字返回,体验和官方一致
  • ✅ 完全免费:Cloudflare Workers 免费额度每天 10 万请求

二、最终效果

先看结果。用 curl 测试:

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}'

返回:

{
  "id": "a14aac65-...",
  "model": "deepseek-flash",
  "choices": [{
    "message": {
      "role": "assistant",
      "content": "你好!有什么可以帮你的吗?"
    }
  }],
  "usage": {"total_tokens": 85}
}

流式输出也完美:

《秋思》
霜枫染半秋,雁字过西楼。
暮色寒烟起,孤灯照客愁。

三、核心架构

客户端 (Hermes/curl/ChatBox)
        ↓
   api.061420.xyz (自定义域名)
        ↓
   Cloudflare Worker (智能路由)
        ↓
   ┌─────────┐         ┌──────────┐
   │  Agnes  │  ──→    │ DeepSeek │
   │ (优先)  │  降级    │  (兜底)  │
   └─────────┘         └──────────┘

降级触发条件:

  • 401/403 鉴权失败
  • 429 限流
  • 5xx 服务端错误
  • fetch 网络异常

不触发降级:

  • 400 参数错误(客户端问题,换后端也没用)

四、完整代码(可直接部署)

1. Worker 核心代码

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 平台的 Key
    • DEEPSEEK_API_KEY:DeepSeek 官方的 Key
    • ACCESS_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:

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:

HERMES_ROUTER_KEY=你的ACCESS_TOKEN值

验证:

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 这类工具,强烈建议搭一个。半天时间,一劳永逸。


相关资源:

如果这篇对你有帮助,点个赞再走~有问题评论区见!