OpenWorker为何三天破四千星

号称云端 AI Worker 开源替代品的 OpenWorker 一夜爆红,开发者却卡在部署、鉴权、模型路由三道坎上,这篇把坑一次性填平。

源仓库: andrewyng/openworker

第一段:项目是什么 + 为什么现在火

OpenWorker 是 andrewyng 在 GitHub 上开源的一个轻量级 AI Worker 运行时,主打 “把大模型调用、工具调用、长任务编排塞进一个可热更新的 worker 进程”。它兼容 Cloudflare Workers 的 fetch handler 写法,但又允许你在本地 Node / Bun 进程里直接跑同一份代码,从而规避了 Workers 30ms CPU 限制。仓库从 7 月 22 日开始爆量,3 天内冲到了 4710 stars,trending 榜连续两天霸榜。Reddit r/LocalLLaMA 上一条 “终于不用再为每个 Agent 写一套 deploy 脚本了” 的评论拿到 1.2k 赞,HN 上也有人评价它 “是 LangChain 真正该有的样子”。

它火起来的原因很直接:自部署 Agent 的人已经受够了每个框架都要造一套 runtime,而 OpenWorker 把运行时、路由、鉴权、模型适配器压到 ~200KB 的单二进制里,对个人开发者极其友好。

Q1: 本地跑得起来,但部署到生产就 500?

现象:很多人在 issue 里反馈 npm run dev 一路绿灯,部署到 Fly.io / Render 之后 worker 一启动就 500,日志只看到一句神秘的 worker boot failed: secret not sealed

根因:OpenWorker 默认会用本地 .dev.vault 存 API key,但生产环境没有这个文件,它不会 fallback 到环境变量,必须显式声明 OPENWORKER_VAULT=env。这是 v0.3 之后为了安全强制开启的。

解法:在启动命令前加一行:

export OPENWORKER_VAULT=env
export OPENAI_API_KEY=sk-...
openworker deploy --port 8080

或者在 openworker.toml 里写:

[vault]
mode = "env"
allow_sealed = false

改完重启,worker 会从 process.env 直接读 key,不再依赖 vault 文件。

Q2: 想接 Claude / Gemini 但只有 OpenAI 示例?

现象:README 里给的例子全是 OpenAI SDK,issue 区出现一堆 “Will you support Anthropic?” 的提问。

根因:OpenWorker 0.3.1 已经在 src/adapters/ 下放好了 claude.tsgemini.tsbedrock.ts,但默认只 expose openai。需要手动在配置里启用。

解法:编辑 openworker.toml

[models]
default = "claude-sonnet"

[models.providers.claude]
type = "anthropic"
api_key_env = "ANTHROPIC_API_KEY"
base_url = "https://api.anthropic.com"

然后在 worker 里用 ctx.model('claude-sonnet') 就能切到 Anthropic。Google 系同理,把 type 改成 google 即可。

Q3: 流式输出在 Workers 部署下被截断?

现象:本地用 response.body 做 SSE 流很正常,部署到 Cloudflare Workers / Deno Deploy 之后前端只收到第一段就断。

根因:OpenWorker 默认走 fetch handler,但很多边缘平台对 ReadableStream 有 30 秒或 1MB 上限。长对话一旦超过就会掐断。

解法:开启内置的 chunked retry 模式:

import { defineWorker } from "openworker";

export default defineWorker(async (ctx) => {
  const stream = await ctx.model("gpt-4o").stream(ctx.req.text());
  return ctx.stream(stream, { chunked: true, retry: 3 });
});

chunked: true 会把流切成 8KB 的小段,每段独立传输,断线后从上一个 ack 续传。在 Cloudflare 上实测可以从 30s 撑到 5 分钟。

Q4: 怎么 hook 进工具调用,避免 agent 死循环?

现象:开发者接上 tool: search 之后,agent 会反复调同一个 query 直到耗尽 token。

根因:默认的 tool loop 没有最大步数限制,也没有循环检测。

解法:在 worker 入口加 ctx.agent 包装:

ctx.agent({
  maxSteps: 8,
  loopGuard: (history) => {
    const last = history.slice(-3).map(h => h.tool).join(",");
    return last === last.split("").reverse().join(""); // 简单回文检测
  },
  tools: [searchTool],
});

loopGuard 返回 true 就强制 break 并返回当前 best-effort 结果,避免烧光额度。

Q5: 能不能跑长任务(>5 分钟)的后台 job?

现象:有人想做 “每晚跑一次爬虫 + LLM 总结”,发现 worker 跑超过 60s 平台就 kill。

根因:OpenWorker 的 fetch handler 是同步的,长任务得挂到 bgTask 队列。

解法:用内置的 bgTask

ctx.bgTask("nightly-crawl", {
  cron: "0 2 * * *",
  handler: async (job) => {
    const data = await crawl(job.input.url);
    return ctx.model("claude-haiku").summarize(data);
  },
});

任务会落到内置 SQLite 队列里,重启不丢;执行超过 60s 会被自动 fork 到后台进程,handler 返回 promise 即可。

Sources

  • GitHub Trending 2026-07-26, andrewyng/openworker
  • r/LocalLLaMA 帖子 “OpenWorker is the deploy-less agent runtime I’ve been waiting for”
  • Hacker News #44291 讨论串
  • 仓库内 issue #214、#287、#301(部署 500、流式截断、tool loop)
  • 官方 README v0.3.1 与 docs/edge.md