你说"帮我把上周的会议纪要整理成文档发给团队"。OpenWorker 不回你一段文字------它进入一个循环:调模型读日历、找到上周的会议、提取纪要、写成文件、打开发件箱、填好收件人、等你点头,然后发出。你得到的不是一份待办清单,是一份完成的交付物。
这就是 2026 年 7 月 24 日吴恩达和 Rohit Prasad 通过 LinkedIn 官宣的开源项目 OpenWorker。MIT 协议,上线即约 3.7k stars。正值 2026 年桌面 Agent 赛道爆发------Claude Code、OpenClaw、Claude Cowork 前后脚冒头,OpenWorker 是其中唯一"吴恩达 aisuite 基因 + 产品级安全设计"的组合。
导航仪告诉你前方右转,方向盘还在你手里。出租车你说目的地,它把你送到。ChatGPT 建议你"发一封邮件给房东说明水管问题",邮件还是你自己写自己发。OpenWorker 替你发。一个只会聊天的 bot 和一个能写你文件、跑你命令的 agent 之间,差的不止一个银河系------差的是一整套让"敢让它干活"成立的工程决策。
这套决策的核心可以浓缩成一个概念------缰绳悖论:给 agent 套的缰绳越多,你能放心交给它的活就越多。约束不削减能力,约束换信任,信任换授权。OpenWorker 三个支点------迭代交付的引擎循环、审批门控的安全纵深、模型中立的集成层------每一层都在加缰绳,每一层加完都能多放开一档。

先看引擎怎么转。每一轮用户输入背后是多次模型与工具的交替调用,引擎硬编码了 max_iterations=12 的护栏,不会无限转圈。低风险操作(读文件、搜索)并行执行,写文件和跑命令严格串行------风险决定并发度。引擎是异步生成器,每走一步就 yield 一个事件------文本在流式输出、工具在执行、审批在等待------前端据此渲染"agent 正在做什么"。同一套 23 种事件,TUI、GUI、IDE 三个界面消费同一份合同。引擎不在乎谁在看,界面不在乎引擎内部怎么转。
但如果它能写你的文件、跑你的命令、发你的邮件------你怎么敢让它动手?
敢让它干活:审批与安全的工程学
假设你来给这个 agent 设计安全机制,最直觉的做法是什么?给每个操作列一个"允许/拒绝"的开关。但你很快会发现不够用:读一个文件和删一个文件的风险不是一个量级,跑 git status 和跑 rm -rf ~ 也不是。风险不是布尔值,是光谱。
OpenWorker 把这个光谱分成四档:READ、WRITE_LOCAL、EXEC、EXTERNAL。像机场的安检通道------只带随身行李的走快检,要托运的过常规通道,带电池的进特殊检查,要出境的过海关。风险分类只负责贴标签,不负责做决定。

做决定的是权限引擎。它像一个只宣判不执行的法官:收到一个操作,返回一个裁决------允许、需要问用户、按规则放行、还是拒绝。五种权限模式覆盖了从"只读讨论"到"全自动"的光谱:discuss 纯读、plan 只读加计划契约、interactive 是默认(每个写操作都问)、auto 全放行、custom 按配置自动放行。但有一条铁律永远不可豁免:写文件必须落在可写目录内,AUTO 模式也查,路径越界永远拒。
最考究的是命令白名单。你想让 git status 免审批直跑------合理,它是只读的。但怎么做匹配?最直觉的办法是前缀匹配:以 git 开头的命令放行。你马上会发现问题:git status && rm -rf ~ 也以 git 开头。
OpenWorker 的解法是两道门。第一道门:整条命令里出现任何 shell 元字符------分号、与号、管道符、重定向符、反引号、$(、换行------直接拒绝,不进入匹配。第二道门:把命令按 argv token 拆开,精确前缀匹配。git status 放行 git status -s,因为多出来的 -s 是同一个 token 的延续;但 git status && rm -rf ~ 在第一道门就被拦住了------&& 是元字符。两道门缺一不可:只做 token 匹配会被 git status;rm 绕过,只拦元字符又拦不住 git push --force 这种合法但危险的操作。先拆暗器,再验身份。

裁决如果返回"需要问用户",引擎不自己弹窗------它发一个 PERMISSION_REQUIRED 事件,然后等。等审批器返回四种结果之一:这次允许、这个工具以后都允许、这条命令以后都允许、拒绝。
这里出现了全项目最精巧的设计:Inbox。
你可能会想,"问用户"不就是弹个对话框吗?在桌面端确实如此------但 OpenWorker 不只是桌面 App。你可能不在电脑前,你的 agent 可能在 Slack 里被 @ 到,你可能重启了电脑。Inbox 把"人的注意力"做成了持久化队列。四种人机交互------审批、提问、要目录、交计划------全部作为条目落盘。你在不在屏幕前,只决定消息显示在哪:在屏幕前是桌面内联卡片,不在屏幕前进跨会话队列,镜像到 Slack 或 Telegram。
关键是幂等。每个条目用一个复合键标记:(session_id, tool_call_id)。断线重连后重发?安全,已回答的跳过。重启 App 后重连?安全,从落盘历史重建引擎,重放未应答的 tool call,已回答的跳过。你在 Slack 里点了个按钮、回到桌面又点了一次?安全,first-responder-wins,谁先到谁算数。一次审批能扛住一次 App 重启。
你可能会想:那 unattended 模式不就是给 agent 全权委托了吗?恰恰相反。无人看守只改变"去哪里找到人"------从桌面内联卡片变成跨平台队列------不改变自主权限上限。权限上限始终由 permission mode 决定。即使在 Slack 里审批,也只有 OAuth 安装者或显式配置的 owner 能批复,且必须在正确的 team 和 channel------防的是"群里任何人点一下 Allow"。
安全纵深不止审批。OpenWorker 的威胁模型很明确:loopback 不等于安全------你机器上的 127.0.0.1,浏览器里任意网页都能访问,CORS 管不了 WebSocket。所以 token 走 WebSocket subprotocol 鉴权,加 Origin 白名单,加帧限流(30 帧/10 秒),加 16MiB 帧上限。凭据永远不进模型上下文:调用时才从 SecretStore 读,status() 只回元数据,审计日志里参数自动脱敏。还有一道供应链门:克隆一个仓库不等于信任它------仓库里 .coworker/config.toml 声明的免审批命令,在用户显式信任这个路径之前完全无效;未受信仓库的 .coworker/mcp.json(可以 spawn 进程的配置)永不读取。陌生人的 U 盘,你不会自动运行上面的程序。
这是缰绳悖论的第一次验证:审批门控加得越细,敢放 auto 模式的场景就越多。
但即便是最安全的 agent,也面临一个内部问题:它聊得越久,记得越多,也就越装不下。
对话减肥:上下文压缩
假设你来设计上下文管理,最笨的办法是什么?对话太长,删掉最老的消息就行。但你马上会发现不对劲:删掉的恰好是用户说过的话。用户上周说"用 Slack 不用 Email",你把它删了,这周 agent 就可能又开始发邮件。
OpenWorker 确立了一条铁律:持久化的对话原文永不被修改。压缩的是"发给模型的那份视图",不是历史记录本身。这就像法庭的庭审笔录永远存档,给陪审团看的是一份整理过的摘要------原档和摘要各走各的路。

压缩后的出站视图由三部分拼成。第一部分是 LLM 写的摘要,强制覆盖八个维度:意图、关键决策、产物、错误修复、全部用户消息、待办、当前工作、下一步。摘要 prompt 里有一句话值得记住:"带有原因的决定才不会被重新讨论。"不是记结论,是记结论加理由------否则压缩完模型又重新纠结已经定好的事。第二部分是机械抽取的工作状态:不靠 LLM,直接从 tool_calls 里扫描,哪个文件被创建了、哪个命令跑过了。第三部分是最新的 40 条用户消息,逐字保留------用户说的话一个字都不让模型改写。
什么时候触发压缩?当对话占用达到上下文窗口的 80%,或者 25 万 token------哪个先到先触发:
trigger=min(0.8×Wcontext,250,000)
翻译成人话:哪怕模型声称支持 100 万 token,也在远未到顶时就动手压缩------上下文质量在名义上限之前就退化,等模型开始返 400 错误再压缩已经晚了。
压缩是递归的:上一份摘要成为下一轮压缩的第 0 条消息。如果 LLM 摘要这步本身挂了,兜底是 trim------直接丢最老的 10%,不靠模型。真正的 400 错误也能路由回压缩策略强制再压。还有一个细节讲究:压缩时特意保持尾部消息字节稳定,因为模型的 prompt cache 依赖尾部不变------不想每次压缩都让缓存失效。
你可能会问:attended 和 unattended 时压缩失败怎么办?在屏幕前弹一个 Retry/Trim 让你选。不在屏幕前直接 trim,绝不把任务 park 住等一个不知道什么时候回来的人。
安全和记忆都是 agent 的内部事务。但一个同事还得能跟外面的世界打交道。
不锁定:集成层与模型中立
假设你要支持 18 家模型提供商,最直觉的做法是什么?给每家写一套独立的对话管理。但你马上会发现:改一家要动一个地方,18 份代码各自腐烂,换模型的成本越来越高------你被绑死了。
OpenWorker 的工程答案是 canonical 中间表示。引擎持久化的对话历史永远是 OpenAI 的消息格式------各方都能理解的最大公约数。每家 provider 配一对纯转换函数:convert_messages 转消息、convert_tools 转工具定义。切换模型不是迁移,是一次字段写入。历史存的是通用格式,调用哪家就临时转成哪家的方言。

不想花钱?接 Ollama 跑本地模型,零 API 费用。想控成本?18 家 provider 任选,自己的 key 自己的账。这是模型中立最实际的红利------不锁定意味着你随时能换到更便宜的或者更聪明的,代码一行不改。
这个设计之所以成立,是因为每家 provider 的差异被精确吸收了。Anthropic 的 system 是顶层参数,不是消息列表里的一条;思考块必须原样回放含签名------签名是 Anthropic 防篡改的机制,丢了就接不上。Gemini 的 function call 没有 id,要按名字回填。GPT-5.6+(2026-07 发布)在 Chat Completions 上拒绝 function tools 与非 none 的 reasoning_effort 组合(报错提示走 /v1/responses),一度把原生 OpenAI 模型推理钉死在 OFF------解法是新增 Responses provider 作原生默认路径,Chat Completions 留作兜底(钉 effort=none,遇错重试一次)。Bedrock 和 Vertex 是一个入口底下挂多条线。这些差异不是 bug,是各家产品路线图的分歧------canonical shape 加转换函数对,就是工程上对抗这种熵增的武器。
能力差异走同一条路。一张故意做得很小、不可编辑的能力矩阵记录每个模型族能做什么不能做什么,前面缀一个启发式兜底(ollama 保守、推理模型并行受限)。PDF 和图片的处理不是写死的:能原生吃 PDF 的模型直接发真文档,不能的本地用 pypdf 或 pypdfium2 转成文本或图片------而且每次调用时实时判断,历史从不改写。中途从 Gemini 换到不支持图片的模型,OpenWorker 不会回溯改写历史,而是重新决定下一轮怎么适配。
连接器的哲学更直接:加一个集成应该是加数据,不是加代码。40 条 descriptor、159 条工具定义,大部分是结构化数据配一个工具函数。tool_defs.py 是权限和能力的单一真相源:工具的 kind 不是 read 就要审批------用户显式连接的服务,读操作永不询问,写操作永远询问。多账号是参数化的:descriptor 设了 account_field 就自动获得多账号支持。出站集成是无状态的一次 HTTP POST,不用 SDK 不长连接;入站 gateway 默认空 allowlist------空名单等于全拒。
MCP 是开放式工具生态的入口。标准 mcpServers JSON,跟 Claude Desktop 和 Cursor 粘贴兼容。完整 OAuth 2.1 加 PKCE 加动态客户端注册------没有预注册的 client id 和 secret,整个流程在本地完成。控制分三层:server 级审批开关、include/exclude 白名单、connector-backed server 的 pin 集与用户开关的交集。drift 只能缩小暴露面不能放大------fail-closed 是默认姿势。
但有一个教训写进了代码注释:turn 里绝不启动交互式 OAuth。一次一键配置在会话中途触发 OAuth 流程,冻结了所有新 session,直到 300 秒超时。这种事故不靠事后补丁,靠写进流程------turn 执行期间的所有交互式认证一律延后到 turn 外。
你可能会想:吴恩达的 aisuite 不是已经做了模型抽象吗?OpenWorker 偏偏不用它做这件事。aisuite 的真正角色只有三个:schema 生成、ToolMetadata 载体、现成的 files 和 git toolkit。模型抽象自研 ProviderClient------因为一个产品级 agent 需要控制转换的每一个细节,这不是一个库能外包的。
一个能干活、能记住、不锁定的同事,还差什么?人格、记忆、和能自己定闹钟。
其余的缺口
这几样不必深讲,但值得知道它们被补上了。
人格(Persona)是声明式的:YAML frontmatter 加 markdown 正文,内置 Cowork(默认)、Code、Chat、Ops 四种。安装一个人格只是引用已经审核过的能力目录------人格自己不能带风险 override,no-self-grant 规则。技能(Skills)用 Anthropic 的 SKILL.md 格式,关键设计叫渐进式披露:会话开始只注入一张目录(名字加一句话),正文靠 load_skill 按需拉取。像图书馆的目录卡------你先查到书在哪一层哪个架,需要时才去取。目录每轮重算:设置里禁用一条技能,下一条消息就生效。
自动化(Automation)用 croniter 调度,带两个保护:宕机后补跑、重叠时跳过。每次定时触发是一次真实的持久化会话,不是无状态函数调用------你可以追问它上次干了什么。没授权的自动化也能跑,只是审批会 park 进 Inbox 挂起------优雅降级,不是直接拒绝。这是缰绳悖论的又一次验证:没给 standing rules 的任务仍然能跑,只是每步都问------约束在,所以敢让它无人值守地启动。
记忆(Memory)有三个 scope:GLOBAL、WORKSPACE、SESSION。存 SQLite,没有向量没有 embedding------一个反直觉但诚实的取舍:记忆不是检索,是全量注入。写进 system prompt 静态块,行为规范三条:别存仓库已经记录的东西、用绝对日期、先查再写。
桌面工程是血泪史。公证被拒了三次------Python 框架的符号链接被 Tauri 打包流程摊平了,框架签名验证失败。解法是打包时就 dereference 符号链接、删掉框架、每个 Mach-O 单独签、spctl 自检过了才发版。Windows 上控制台子进程继承无效 std handle 会崩,CREATE_NO_WINDOW 解决;PyInstaller onefile 打包导致 Python 是孙进程,getppid 永远不对,所以显式传 COWORKER_PARENT_PID------桌面 App 的进程管理比你想的难。自更新是提示而非静默安装:中途换掉 App 会杀掉正在跑的 turn,安静的自我变异与本地优先的信任姿态冲突。
还有一个诚实的半成品:self-wake 的触发器只登记了没有生产者。beta 项目的坦白也是信任的一部分。
问题、办法与名字
从头到尾,OpenWorker 补上的缺口可以这样串起来:
| 问题 | 办法 | 名字 |
|---|---|---|
| 聊天机器人只给建议不交付成品 | 迭代循环加工具调用 | TurnEngine |
| 能干活的 agent 怎么才敢用 | 风险分档加权限裁决加审批 | Risk / PermissionEngine / Approver |
| 审批会丢会卡会重复 | 人类注意力做成持久化队列 | Inbox |
| 重启后审批还有效吗 | 落盘重放未应答的 tool call | Durable Resume |
| 克隆的仓库可能带毒 | 显式信任路径才生效 | Workspace Trust |
| 长会话撑爆上下文 | 压缩出站视图原文不动 | Compaction |
| 绑死一个模型是陷阱 | canonical shape 加转换函数对 | ProviderClient |
| 加集成不该加代码 | descriptor 加 tool_defs 数据 | Connectors |
| 工具生态开放但不失控 | 三层控制加 fail-closed | MCP |
| 同事该有人格和记忆 | 声明式人格加全量注入记忆 | Persona / Memory |
| 同事该能自己定闹钟 | cron 调度加 standing rules | Automation |
每一条都是先有一个问题、再有一个办法、最后办法被贴上一个名字。术语只是给解决办法贴的标签------读者只需要抓住问题就够了。
带得走的设计清单
如果你也在做 agent 项目,这几个问题不答完就别上线:
-
你怎么给操作分风险档? READ / WRITE / EXEC / EXTERNAL 至少四档------风险不是布尔值。
-
你的命令白名单是前缀匹配还是 argv token 精确匹配? 前缀匹配会被
git status && rm -rf ~绕过。先拦 shell 元字符,再做 token 匹配。 -
审批结果落盘了吗?重启后能恢复吗? 幂等键用
(session_id, tool_call_id),重启后重放未应答的------否则用户点完 Allow 你崩了,审批就丢了。 -
长会话怎么压? 原文不动,只压出站视图。摘要要带理由------"带有原因的决定才不会被重新讨论"。
-
切模型要改代码吗? canonical 中间表示加转换函数对 = 一次字段写入。改一家只动一个文件。
-
克隆的仓库你信吗? workspace trust:不显式信任就不读
.coworker/配置------克隆不等于信任。 -
凭据会进模型上下文吗? 永远不。调用时读,
status()只回元数据,审计日志自动脱敏。 -
loopback 就安全了吗? 浏览器里任意网页都能访问 127.0.0.1。token 走 WS subprotocol,加 Origin 白名单。
这八条就是缰绳悖论的实操版:每答一条,就多一档能放心交给 agent 的场景。
这又回到了开头那件最简单的事。OpenWorker 做的事和开头说的一样:你说目的地,它把你送到。但中间绕了一大圈------风险分档、命令白名单两道门、Inbox 幂等键、上下文压缩不变量、canonical 中间表示、fail-closed 的 MCP 控制------这些不是花活,是让"敢让它干活"成立的前提。
一条线贯穿全文:给 agent 套缰绳不等于削弱能力。standing rules 加审批挂起让"无人值守"成为可能------约束越多,能授权的场景越多。AI 同事能不能靠谱,不取决于模型有多强,而取决于工程上敢不敢让它犯错前先问你。
注:本文代码事实基于 2026-08-02 本地副本快照,项目迭代快(App 自更新 + 每周多个 PR),具体实现可能已有变化。