文章目录
- 前言
- 1. 这事儿是怎么火起来的
- 2. OpenMuse 到底是个啥
- 3. 本地跑起来,坑我先替你踩了
- 4. 派个活给它,看看它怎么干
- 5. 中途崩了咋办?人家早留后手了
- 6. 浏览器这块,目前只会"读"
- 7. 最后说两句
P.S. 无意间发现了一个巨牛的人工智能教程,非常通俗易懂,对AI感兴趣的朋友强烈推荐去看看, 传送门https://blog.csdn.net/qq_34419312
前言
先问个事啊,你有没有幻想过这么一个场景——早上你出门,电脑自己在那儿开机、收邮件、填表格、查资料,等你晚上回来,活儿全干完了,就等你签字确认。
别觉得这是科幻片,这事现在真有人给你开源出来了。
1. 这事儿是怎么火起来的
一个多月前,Meta 那边憋了个大招,搞了个叫 Muse 的 Personal Agent。
说白了就是你给它一台云电脑,它自己开浏览器、登账号、填表单、订行程,你只需要在旁边看着,关键节点点个同意就行。
这玩意儿一出来,整个行业都炸了。为啥?因为以前的 AI 助手你得一句一句喂,它才动一下,跟个需要你全程盯着的实习生似的。现在倒好,Meta 直接说"你交代完就走,回来给你交结果"。
这就好比隔壁老王花几百万装了个智能家居,你们小区物业一看,这思路不错啊,立马整了个共享版,让大家都能用上。
Muse 发布才两周,做 AG-UI 协议的 CopilotKit 就开源了一个 OpenMuse。浏览器、Linux 终端、文件管理、后台任务,Muse 有的它全照着做了一套,MIT 协议,一套 React Native 代码同时跑 iOS、Android 和 Web。
GitHub 地址:github.com/CopilotKit/OpenMuse
现在还是 alpha 版本,但我跟你讲,这玩意你要是在公司里第一个跑通了,你就是那个"我们公司也能做"的先行者。写简历上,HR 看了都得高看你一眼。
2. OpenMuse 到底是个啥
一句话总结:一个自带电脑的 Personal Agent,你交代给它的任务会在后台一直跑,跑到需要你拍板的时候,它停下来等你。
你品品这个设计——以前你用 AI,是你坐在那儿,你说一句它动一下。现在倒过来了,你说一句"帮我把那堆邮件里关于学校旅行的找出来,填了同意书,再回一封邮件",然后你就可以去忙别的了。
这就像你招了个远程实习生,给它配了工位、开了电脑权限,你在群里发完任务就去开自己的会,等你回来它给你交差。
它主要有这么几个模块:
聊天窗口,收邮件、读邮件、把复杂活儿派成后台任务;一个常驻的 Chromium 浏览器,外加一个可选的 Linux 容器;活动中心,任务跑到哪一步了、暂停了、等你审批了,全在这儿;目标追踪,还能定时帮你盯着某个网页有没有更新;文档处理,从邮件附件里抠出 PDF,填好,再给你准备一封回信;最后是 Gmail 和日历接入,发邮件、改日程这种敏感操作,都得你单独点同意。
模型默认支持 DeepSeek V4.1 Flash,数据存在你本地的.openmuse/目录里,不上云。
架构也不复杂。客户端是 Expo 加 React Native,一套代码三端跑。客户端和服务端之间走 AG-UI 协议,就是 CopilotKit 搞出来的一套事件流规范,约定好 Agent 怎么把文本、工具调用、状态变化推给前端。
服务端是 Hono 加 CopilotKit runtime,跑pnpm dev就起一个 Node.js 进程。执行后台任务的 Worker 也在这个进程里一起跑。你可以理解成一个 Spring Boot 项目,既暴露 Controller 接口,又用@Scheduled跑定时任务,全塞一个进程里。
数据库用的 PGlite,就是编译成 WASM 塞进进程里的 Postgres。浏览器是独立的 Playwright 服务,Linux 电脑是个 Docker 容器。
3. 本地跑起来,坑我先替你踩了
别光听我说,你自己拉下来跑一遍才知道香不香。
第一步,克隆仓库。
git clone https://github.com/CopilotKit/OpenMuse.git openmuse第二步,登录 CopilotKit。
npx copilotkit@latest login && npx copilotkit@latest project select这一步绕不开。为啥?因为服务端读配置的时候,强制检查CPK_INTELLIGENCE_API_KEY。你没这个 Key,连那个不需要模型的 sample 模式都启动不了。这个 Key 对应的是 CopilotKit Intelligence 服务,负责保存和回放对话线程。
我跟你说,这种设计就像你去饭店吃饭,门口保安非得看你会员卡,你说我就进去喝杯水行不行?不行,没卡不让进。不过后续你 fork 下来改掉就行,问题不大。
登录完就可以pnpm dev启动本地服务了。
第三步,配置环境变量。先复制一份:
cp .env.example .env比如说你想把模型换成 DeepSeek V4.1 Flash,注意了,OpenMuse 只认openai、anthropic、google三种前缀,DeepSeek 得借openai这个壳,再把 Base URL 指过去。
AGENT_BACKEND=model MODEL=openai/deepseek-flash OPENAI_API_KEY=<你的 DeepSeek API Key> OPENAI_BASE_URL=https://api.deepseek.com OPENAI_CHAT_COMPLETIONS=true最后这行OPENAI_CHAT_COMPLETIONS=true一定要加。为啥?因为 OpenMuse 默认走 OpenAI 的 Responses API,但它发现 DeepSeek 这类兼容端点的 Responses API 工具调用不完整,得切回 Chat Completions 接口。
这种事就像你买了个转接头,以为能直接插,结果发现耳机麦和声音是分开的,你还得再买个一分二。
浏览器那边是个独立的 HTTP 服务,服务端每次调它,请求头里都得带一个共享密钥WORKER_TOKEN,对上了才理你。这个密钥至少 32 个字符,两边从同一个 .env 里读。
BROWSER_WORKER_URL=http://127.0.0.1:8790 WORKER_TOKEN=<用 openssl rand -hex 32 生成一串随机的>然后开三个终端,分别起 API、Web 端和浏览器服务。
# 终端一:构建 Linux 电脑镜像并启动 API docker build -t openmuse-computer:local apps/computer COMPUTER_ENABLED=true pnpm dev # 终端二:启动 Web 端 pnpm dev:web # 终端三:装 Chromium 并启动浏览器服务 pnpm --dir apps/worker exec playwright install chromium pnpm dev:browser浏览器打开localhost:8081,界面就出来了。
三个终端啊朋友们,就像你同时开三个炒菜锅,一个炒一个炖一个炸,你还得盯着别糊了。我第一次跑的时候,终端一起就忘一个,来回切,跟个 multitasking 都不会的产品经理似的。
跑之前还有两个默认配置建议你看一眼。
第一个是遥测。就是软件跑起来偷偷把使用数据发回开发商那边,类似 VS Code 里那个"发送使用情况统计信息"。OpenMuse 用的是 CopilotKit SDK 自带的遥测,服务启动、收到请求这种事件,全发到 CopilotKit 的服务器,再存进 PostHog。源码里采样率默认设成了 1,也就是每个事件都上报,还跟你登录的 CopilotKit 账号绑着。
你不想被盯着?在 .env 里加一行:
COPILOTKIT_TELEMETRY_DISABLED=true这种事就像你住酒店,床头有个小卡片写着"您的房间已纳入智能体验计划",你翻过来背面写着"入住即视为同意"。你说你膈应不膈应?
第二个是网页搜索。默认开着,用的是 Parallel 提供的免费 Search MCP,模型生成的搜索词和对话上下文都会发给 Parallel。不需要就关掉:
WEB_SEARCH_ENABLED=false4. 派个活给它,看看它怎么干
第一个推荐你试的任务,是填一份"家长同意书"。
你在对话框里输一句"Complete the permission slip",它立马给你安排得明明白白。
它会先跟你说:“permission slip 具体是哪一份我这边还没线索,我先去你邮箱里找,别凭空猜。”
然后它真就去邮箱里翻,找到一封学校发来的邮件,标题是"水族馆校外教学许可单,周五截止"。
整个任务被它自己拆成了五步:找到源文件,填一份新的副本,准备一封回复邮件,等你拍板,记录结果。
跑到第二步它会停下来,问你表单里要填什么,还把这份 PDF 支持的字段全列出来:participant_name、guardian_name、emergency_contact、emergency_phone、additional_notes、permission_granted。
你把值填进去,它接着跑,给你生成一份填好的 PDF 副本。
你品品这个流程——以前你用 AI,它一口气给你编完,错了你都不知道它哪步错的。现在人家是一步一步来,每一步都给你看,关键地方停下来等你确认。这就像你把活儿甩给实习生,他还真不是瞎搞,他是先翻邮件、再开文件、再填表,每一步都留痕,你回来一看就知道他干了啥。
5. 中途崩了咋办?人家早留后手了
这里有个点特别值得细看:任务跑到一半,服务重启了怎么办?
这其实就是你技术功底的试金石。你自己写后台任务的时候,是不是经常遇到"任务跑了一半进程被杀了,重启以后从头再来,前面白跑了"这种情况?
OpenMuse 的做法是检查点。每完成一步,就把这一步的产出写回任务状态里。找到的源文件存进state.source,填好的副本 ID 存进state.filledId。下次重新执行这个任务时,函数先看状态里有没有这些值,有就直接跳过这一步。
// apps/server/src/engine/service.ts(节选)letfilledId=typeoftask.state.filledId==="string"?task.state.filledId:undefined;if(!filledId){awaitctx.guard();constfilled=awaitthis.files.fill(owner,source.fileId,fields,`document:${task.id}`);filledId=filled.id;task=awaitctx.checkpoint({state:{...task.state,source,filledId},artifactIds:[filledId],});}那谁来发现任务中断了?谁又接着把它跑下去?
答案是任务 Worker,外加一套基于 SQL 的租约机制。
Worker 每秒扫一次任务表,最多同时跑 3 个任务。它会找四类任务来执行:排队中的、定时到点的、正在等审批的,以及状态是执行中但租约已经过期的。
抢占任务用的是 CAS。OpenMuse 整个数据库就一张records表,所有实体都以 JSONB 的形式存在data列里,CAS 靠 Postgres 的 JSONB 包含运算符@>实现。
// apps/server/src/db.ts:69-81asynccompareAndSwap<T>(owner,kind,id,expected,patch){constresult=awaitthis.db.query("UPDATErecordsSETdata=data||$5::jsonb,updated_at=now()WHEREowner=$1ANDkind=$2ANDid=$3ANDdata @>$4::jsonbRETURNINGdata",[owner,kind,id,JSON.stringify(expected),JSON.stringify(patch)],);return(result.rows[0]?.dataasT|undefined)??null;}只有data里的字段和期望值完全一致时,UPDATE 才会命中。这跟你在 MySQL 里用 version 字段做乐观锁是一回事。
你看,技术这东西,绕来绕去都是那几招。你在 MySQL 里玩过的乐观锁,换个数据库它还是乐观锁,只是换了个写法。
这种 CAS 机制我给你打个比方——就像你抢公共卫生间。你不能直接推门,你得先看一眼门锁上写的"无人",然后你推门进去反锁。但如果你刚看到"无人",里面那个人同时也推门出来了,你一推门就尴尬了。CAS 就是在你推门那一瞬间,再确认一次门锁真的是"无人",对上了你才进去,对不上你就重新排队。
Worker 抢到任务时,会生成一个新的leaseId,把租约过期时间设成 60 秒以后。执行期间,每 20 秒续一次租约,续租同样用 CAS,条件是leaseId没变、状态还是执行中。
// apps/server/src/engine/worker.ts(节选)constheartbeat=setInterval(()=>{voidthis.db.compareAndSwap(owner,"tasks",taskId,{leaseId,status:"running"},{leaseUntil:newDate(this.now()+leaseMs).toISOString()}).then((value)=>{if(!value)controller.abort();}).catch(()=>controller.abort());},Math.max(10,Math.floor(leaseMs/3)));续租失败,说明这个任务已经被暂停、取消,或者被别的 Worker 接手了,当前执行立马中止。前面说的检查点写入也带着同一个leaseId做条件,租约丢了,写检查点就会失败。
这样一来,进程崩溃以后,60 秒内没人续租,租约自然过期,下一轮扫描时任务被重新领走,再借助检查点跳过已完成的步骤。
这套机制我跟你讲,就像公司打卡。你每 20 秒在系统上打一次卡,证明你还活着、还在干活。60 秒没打卡,系统就当你跑路了,你的工位立马被别人占。新员工接手的时候,他从你留下的文档(检查点)接着干,不用从头再来。
你自己写后台任务的时候,是不是经常就是"任务跑一半崩了,重启以后从第一步开始重跑"?人家这套设计,你拿过去直接就能用。
6. 浏览器这块,目前只会"读"
你在对话框里输这么一句:
用 Browser 打开 https://1.1.1.1/cdn-cgi/trace, 读取页面里的 http、tls、loc 字段,并解释含义。 必须实际读取网页,不要用搜索结果代替。它真就打开浏览器,导航过去,把页面内容读回来给你解释。
但我用下来发现一个事:OpenMuse 的浏览器目前只能做一件事——读网页。
不管是对话里的browse_web,还是任务里的read_web,都是先导航到目标地址,再调浏览器服务的读取接口。
// apps/worker/src/browser.ts(节选)// Evaluation is fixed by the worker; callers cannot inject JavaScript.constresult=awaitpage.evaluate(()=>{consttext=document.body?.innerText??"";return{url:location.href,title:document.title.slice(0,300),text:text.slice(0,100_000),truncated:text.length>100_000,};});看到没,它就是把document.body.innerText抠出来,截断到 10 万字符,完事。它不会帮你点按钮、填表单、下单付款。
这一步跟 Meta Muse 差别就大了。Muse 能直接帮你订行程、下单付款,OpenMuse 暂时还做不到。当然了,后面版本可能会补上,毕竟现在才 alpha。
不过它浏览器服务本身有一套出网限制,用来防 SSRF。规则是只允许访问 80 和 443 端口的公网 HTTP(S) 地址,域名里带localhost、local、internal、home、lan后缀的直接拦。DNS 解析出来的任何一个 IP 不符合要求,整个请求都拒。
但你只在请求前校验 DNS 还不够。为啥?因为有个东西叫 DNS 重绑定。
啥意思呢?就是攻击者让同一个域名第一次解析时返回公网 IP,骗过你的校验。等浏览器真正建立连接时,再解析一次,这次返回内网 IP。你以为它在访问外面的网站,其实它在内网里到处逛。
这就像骗子先在保安面前装成快递员,保安看他穿得像、说话也像,就放他进去了。结果他一进门,快递服一脱,里面是贼的衣服,开始挨个办公室翻东西。
OpenMuse 的做法是在浏览器服务里起一个本地代理,Chromium 的所有流量都过这个代理。代理只连接校验时解析出来的那个 IP,不做第二次 DNS 查询。
// apps/worker/src/proxy.ts:13/** All upstream sockets connect to a validated IP, * never a second DNS lookup. */翻译成人话就是:保安不光在门口看了你身份证,他还派了个小弟跟着你进门,你这一路上想换身份?没门。
7. 最后说两句
Meta 超级智能实验室的产品负责人 Nat Friedman 自己都承认,Muse 深受 OpenClaw 启发,连工作区文件名和 SOUL.md 的内容都很接近。他今年一月份用上 OpenClaw 以后,直接给团队买了几百台 Mac mini。
Meta 想做的,是一个更安全、更容易上手、能服务几十亿人的 OpenClaw。
但这里面有个关键区别,就是 Personal Agent 和编程 Agent 在用法上根本不是一回事。
你用 Claude Code 写代码的时候,你就坐在终端前面,每一步都看得到,发现不对你立马按 Esc 打断,或者补一句"不是这个意思,重来"。
Personal Agent 不是这样用的。Personal Agent 是你交代一件事,然后你去忙别的,过一阵子回来再看结果。
你人不在场,设计的重心就得跟着变。任务中断了得自己接着跑,所以要有租约和检查点。你回来时要能看懂这段时间发生了啥,所以每个操作都得留记录。
这就像你在家看着孩子写作业,和你把孩子送托管班,回来检查作业,这两种带法是完全不一样的。你在家看着,孩子写错一个字你立马指出来;你送托管班,你就得要求老师把每一步都记下来,回来你翻记录。
所以啊,正在做 Personal Agent 的朋友,OpenMuse 这套设计,你真的可以直接拿过来参考。检查点怎么写、租约怎么续、CAS 怎么抢任务、SSRF 怎么防,人家全给你摊开了。
剩下的,就看你自己怎么往上面加业务了。
P.S. 无意间发现了一个巨牛的人工智能教程,非常通俗易懂,对AI感兴趣的朋友强烈推荐去看看,传送门https://blog.csdn.net/qq_34419312