
这是什么
OpenBot 是 CopilotKit 开源的 AI 同事平台,每个同事都分到一台自己的电脑:一个装着 Chromium、一块 /workspace 卷、一套自己的登录态和一份自己的浏览器配置的容器。同事可以是任何说 AG-UI 的端点,所以用 LangGraph、CrewAI、Pydantic AI、Google ADK 写的、或者手写的 agent,进来时都是一个样子;示例包里随附十三个同事,它们是 YAML 配置而不是代码。一个 Bot 对浏览器、文件、MCP 服务器或组件做的任何事,都要走服务端那唯一的网关:解析目标、按 CEL 动作策略裁决、写下一行审计,然后才去调用那台电脑——被拒绝时还会说出是哪条规则导致的。这个仓库是模板而不是产品:没有托管版本,没有任何工作区被发布成包,README 让你把它克隆下来,用你自己的同事、频道与技能替换掉示例租户包。它靠 Docker Compose 在一台笔记本上起来,需要一份 CopilotKit Intelligence 项目和一个模型密钥,另外还带一个可选的 Tauri 桌面应用。
谁做的这是一个组织账号,不是个人。仓库列出约六周内 33 位贡献者、451 次提交:davidmckayv 写了其中 126 次,kevin9327 91 次,Ayush7614 48 次,zopeVaibhav 37 次;一个工作流机器人占 12 次,Renovate 占 6 次。历史里有 242 条共同作者尾注,其中被署名最多的是 David McKay(130 次),另有 13 条写成账号名 davidmckayv——也就是说最忙的账号与被署名最多的共同作者同名,而他之后最大的共同作者群体是模型。
它是怎么搭起来的
组成 · 6Bot 是 AG-UI 端点另一头的一个进程,而产品是它周围的一切:一个为它造容器的 supervisor,容器里一台握着真浏览器的电脑,以及站在两者与部署其余部分之间的服务端。三个后果塑造了代码。第一,网关是唯一的入口——这也是为什么服务端里最大的文件就是网关,为什么目标解析、策略与审计各自成模块,而不是散落在各个路由里的检查。第二,Bot 被当作一个可能粗心甚至可能恶意的东西:它有 shell,所以数据库被放到电脑不在的那个网络上;电脑绑在回环地址后面并要带令牌;supervisor 握着 Docker socket,只提供四个操作;凭据库静态加密、从不把存进去的东西还回来;而一条秘密被记下来的是「它被要过、有多长」,不是它说了什么。第三,这是模板而不是服务——十三个同事以 YAML 形式随附,没有任何模型随包发布,没有任何工作区被发布成包,仓库是拿来克隆并改写的,而不是由作者替别人运营的。
- server/
- API 与裁决点:143 个源文件,领头的是一份 105 KB 的 CopilotKit 运行时、67 KB 的 app、66 KB 的入口和 55 KB 的配置模块,另有 49,664 字节的电脑网关、37 KB 的审计模块,以及策略、快照与 supervisor 客户端,再往外是插件、频道、例程、语音、认证与学习。旁边是 222 份测试——其中
plugin-store.integration.test.ts一个文件就有 319,249 字节——以及 97 个 Drizzle 文件,装着编号 0000 到 0047 的迁移,它们的名字是整句话,比如truncate_is_not_a_way_around_append_only。 - app/
- 界面:272 个 React 与 Vite 文件,覆盖输入框、对话记录、带实时画面的电脑面板、技能与 agent 页面,以及十五条管理端路由,旁边跟着 132 份测试,其中一份有 114,325 字节。最大的几个源文件是 82,677 字节的 composer、74,777 字节的对话记录和 45,055 字节的频道聊天——产品的表面积大多花在这里。
- agent-computer/ 与 supervisor/
- 那台电脑,以及分配「每个 Bot 一台」的东西。
agent-computer是围着 60,722 字节入口的 25 个源文件,其中配置 27,263 字节、工作区 15,459、shell 13,819、控制权交接 11,892、截屏 9,177,由 32 份测试看着。supervisor 是七个文件,其中 27,198 字节的 Docker 模块负责创建、停止、重置与列出容器,另有一个内存上限、一份身份和一套命名器。 - 十四个 agent-* 目录
- 骨架群:作为概念验证的
agent-bot、TypeScript 的agent-langgraph、agent-mastra、agent-langgraph-agui,以及十一个 Python Bot——每一个都有自己的 Dockerfile、依赖文件,和一个装着主测试、学习投递测试与模型规格测试的 tests 目录。它们的存在让 README 那句「Bot 可以是任何 AG-UI 端点」可以当真;其中最大的一份agent-crewai/tests/test_main.py有 26,918 字节。 - desktop/
- 一个 Tauri 桌面应用:
src-tauri下 70 个文件、4,563 KB 的 Rust,其中main.rs416,470 字节、stack.rs318,549 字节、env.rs101,450 字节;另有 PowerShell 写的 Windows 代码签名与签名校验脚本、一份 macOS 麦克风说明、一份遥测文档及其校验器,以及一个自带 35,009 字节测试的 provider 选择器。 - shared/、charts/openbot/、docker/s6/ 与 scripts/
- 所有必须在语言之间、在部署之间保持一致的东西。
shared/model-providers.json是唯一命名各家 provider 的密钥变量、端点变量与默认模型的文件,由一个 TypeScript 载入器和一个 Python 载入器读取。charts/openbot是 33 个文件的 Helm,含 28,138 字节的 values、19,951 字节的校验模板、13,888 字节的网络策略,以及给 AKS、EKS、GKE 与自托管用的 CI values。docker/s6是 27 个 s6-rc 定义文件,让一个镜像同时扛起 API、电脑、迁移和可选的 PostgreSQL;而 21,826 字节的scripts/start.sh才是克隆下来之后真正要跑的东西。
取舍,以及它替代了什么
每个 Bot 一台电脑,而不是共用一台 替代 让所有 Bot 指向同一个浏览器容器
设了
COMPUTER_SUPERVISOR_URL,每个 Bot 就拿到自己的容器、自己的工作区卷和自己的浏览器配置;不设,所有 Bot 共用同一个AGENT_COMPUTER_URL。README 把「每个 Bot 一台」当作这个功能的要点,而「一个能用你的工具的 agent」与「一个你敢让它靠近这些工具的 agent」之间的差别,正是在这台电脑上被执行的。网关是唯一路径,所以记录先于动作存在 替代 让电脑自己决定自己可以做什么
电脑本身不做策略决定:服务端从自己持有的快照里解析目标、评估策略、写一行审计,只在决定放行时才去调电脑。README 把后果直接写了出来——没有任何一条路径可以在记录存在之前动手——并且把电脑自己那些更底层的端点标注为「不要用来绕过网关」。
provider 的事实写进一份规格文件,两种语言共读 替代 在 TypeScript 和 Python 里各维护一份 provider 表
一个 JSON 文件同时装着某家 provider 的密钥变量、端点变量、在别处都没指定时用哪个模型,以及每个 Bot 一行。两个载入器都在启动时校验整份文件,遇到缺字段的行、或者
bots指向文件不认识的 provider,就带着出错键的路径让 Bot 起不来,而不是等到第一次模型调用;两种语言各自有一个测试把自己的 provider 列表钉到同一份文件上,所以只改一边、忘了另一边会挂测试。读取失败不可以长得像「空结果」 替代 让处于 pending 的查询落进它的空状态
有三处改动持同一个立场:
isPending在读取失败时与成功时一样变成 false,于是技能页告诉有十几个技能的人「一个技能都没有」,连接器页面说某个连接器不存在,Boundaries 页面只剩一个悬在空处的标题。每一处修法都把失败引到一个错误状态上,并在服务端给了原因时把原因也显示出来——因为在读取回来之前就显示空状态,用仓库自己的话说,是一个页面尚未挣得的断言。把签名与公证刻意推迟,而不是发一个签了一半的包 替代 在产出构建物的那条工作流里顺手签名
桌面工作流里留着一句注释:真正做签名和公证的是 bundle 那一步,而它被刻意排除在这里,因为它需要这条工作流并不持有的证书;这里用的是
-这个临时身份,签名被登记成一个有名字的独立步骤。对那条要求签名 DMG 的 issue 来说,这个区别才是关键:它是一件被推迟并且带了标签的工作,而不是一件没人注意到的事。按字符切文本,而不是按码元切 替代 按固定的 UTF-16 码元数切片
语音会给拼接的上下文、显示的字幕和返回的答案设上限,而每一处上限原本都是朴素的
slice——它可能正好落在 emoji 的两半之间,把半个字符交给模型或字幕。现在这些上限都在字符之间下刀,最多短一个单元、绝不超上限,与路由文本和服务端早就在用的规则一致。
依据docs/architecture.md(28,069 字符)、README.md(28,799 字符)、docs/configuration.md(54 KB)、CHANGELOG.md(291,939 字节)、.github/workflows/ci.yml(30,219 字节)、.env.example(26,511 字节)、docker-compose.yml(22,056 字节)、scripts/start.sh(21,826 字节)、.claude/skills/ 下的两份技能文档,以及完整的 1,382 个文件树及其体积。
制作过程
6 个阶段- 01
六周、十五个版本,和一份 292 KB 的变更日志
仓库建于 2026-08-17,而它最早的那次提交比这个日期还早两天。此后六周里落了 451 次提交——八月 178 次,九月 273 次——发成十五个版本,从建仓当天的
v0.0.1到 2026-09-22 的v0.0.15;其中v0.0.2、v0.0.3、v0.0.4是同一天(2026-08-22)一起切出来的。文件树里有 1,382 个文件。CHANGELOG.md有 291,939 字节,.env.example有 26,511 字节——也就是说「改了什么」的流水账比它所描述的大部分代码还长。到九月底,它有 5,761 个星、765 个 fork、23 个 watcher 和 18 个开着的 issue,MIT 协议、TypeScript 写成,README 上还挂着一枚日榜第三名的徽章。长得这么快的仓库通常是一堆脚本;这一个却带着一份 Helm chart、一个 Tauri 桌面应用、一套让单个容器同时扛起 app、API、浏览器与可选 PostgreSQL 的 s6 服务树,以及仅 server 目录下就有的 222 个测试文件。 - 02
一个 monorepo、十四套 agent 骨架,和一只装在盒子里的浏览器
目录结构直接说明了产品是什么。
app/是 272 个文件的 React 与 Vite 界面;server/是 143 个源文件的 Hono API,旁边还有 222 个测试文件与 97 个 Drizzle 文件;而agent-computer/是整个想法赖以成立的那一块:25 个源文件,管着一只 Chromium、一块/workspace卷、浏览器配置、截图、ARIA 快照、一个 shell 和那些文件工具。supervisor/是七个文件,握着 Docker socket,只做四件事——ensure、stop、reset、list——每个 Bot 一个容器;它绑在回环地址上,因为它的令牌是共享密钥而不是网络边界。围在它们周围的是十四个骨架目录:十一个 Python Bot(ADK、AG2、Agno、Claude SDK、CrewAI、LangGraph AG-UI、Langroid、LlamaIndex、Microsoft Agent Framework、Pydantic AI 与 Strands),一个 TypeScript 写的 LangGraph Bot,一个 Mastra Bot,以及一个手写的概念验证。每个 Python Bot 都带着自己的 Dockerfile、依赖文件和三份测试,其中一份把它钉在一份共享的模型规格上。这一群没有一个享有特权,因为 Bot 只是一个 AG-UI 端点:治理搭在协议上,而不是搭在框架上。 - 03
网关先裁决、再记录,最后才动手
产品主张只有一句话,而代码是围着它排的:Bot 对浏览器、文件、MCP 服务器或组件做的每一次动作,都要先回到服务端。
server/src/computer/gateway.ts有 49,664 字节,跑一个五步循环——从服务端持有的快照里解析出目标、评估当前策略、为这个决定写一行审计、只有在决定放行时才去调用那台电脑,而放行动作失败时再写第二行。策略是 CEL,deny 先于 allow 求值,引擎失败时关闭:缺失或空的策略什么都不允许,写坏的 deny 规则一律拒绝,写坏的 allow 规则也不放行。配置进来的策略一旦格式错误就直接让服务端起不来;出厂默认被明确写出来,是deny: []配allow: ["true"],而不是留给人去猜。规则可以读tool.name、intent、page.host、element.*、key、command、file.*、mcp.*与initiator.*——最后这个是「这次运行是谁起的」,也是唯一能区分无人值守的例程和有人在打字的字段。网络本身也是设计的一部分:Bot 有一个 shell,而 shell 能够到它那个容器能到的一切,所以 PostgreSQL 独占一个 Docker 网络,电脑绑在127.0.0.1后面并要带每个容器自己的令牌;宿主支持的话,可以用COMPUTER_RUNTIME=runsc把它们跑在 gVisor 底下。 - 04
六周的 bug 报告,和同一个错误犯三次
这些 pull request 读起来像一份「界面能怎样对使用者撒谎」的清单。#665 里,技能页、管理端技能页和技能编辑器都分支在
isPending上,而它在读取失败时和读取成功时一样会变成 false——于是手下有十几个技能的人被告知「You don’t have any skills yet.」;而那个页面自己的注释早就把「读取还没回来就显示空状态」称作一个页面尚未挣得的断言。#664 是同一个 bug 出现在三个连接器页面上,#656 又是同一个:一次从 #60 退化来的问题,让 Boundaries 页面只要开着就一直只有一个标题悬在空处。其余几处同样具体:#657 拒绝管理员去授权一个根本没人写过的技能,因为那次 upsert 照样把行存了下来,而日后一旦有人用同一个 slug 写出技能,它就会自己挂到一台共享 Bot 上;#653 清掉 Bot 浏览器控制状态保存失败时留下的临时文件;#651 只在真的收到一帧时才重置实时画面的重连计数;#652 让语音的上下文、字幕与回答按字符切,而不是按 UTF-16 码元切。另有三处是可移植性:启动脚本在 macOS 上以 bad substitution 收场,因为${name^^}是 bash 4 才有的;Docker Compose v5 需要COMPOSE_PROGRESS=quiet,而对等的那个命令行开关会被旧版本直接拒掉;还有一处健康检查外调python3,在 Git Bash 上这个名字指向 Microsoft Store 的别名,直接以 49 退出。 - 05
三十三位贡献者,和尾注里的模型名字
451 次提交全部关联到了账号,一共 33 位贡献者。占比最大的是 davidmckayv 的 126 次,其后是 kevin9327 的 91 次、Ayush7614 的 48 次与 zopeVaibhav 的 37 次;一个工作流机器人占 12 次,Renovate 占 6 次。让这段历史不寻常的是尾注:242 条共同作者尾注,而在被署名 130 次的 David McKay 之后,最大的那一群是模型。Claude Opus 5 出现 41 次,Claude Opus 5.5 八次,Claude Fable 5.1 五次,百万上下文版 Claude Opus 5 三次,Claude Opus 4.8 三次,Claude Fable 5 一次,另有 Warp 一次、一个叫 pi 的两次。评审同样是自动化的:kevin9327 有八条 pull request 下唯一的评论,来自一个 Codex 连接器,说它已经用完了代码评审的额度。外部贡献者并不会被放行——#649 让一个 JSON 文件成为 TypeScript 与 Python 共用的、唯一命名各家 provider 的密钥变量、端点变量与默认模型的地方;一位评论者说他不是听信说法,而是在某个具体提交上去
main核过,并指出把两种语言各自的 provider 列表钉到那份文件上的两个测试。再往前,#670 与 #671 来自一个自动安全扫描器,维护者对两条的回应都是先复现失败、再推一个后续提交,并补上一个对旧代码会失败的测试。 - 06
架构文档写下了哪些东西还不工作
docs/下有十个文档,领头的是 54 KB 的配置参考和一份 28,069 字符的架构文档;第二份值得读的地方不在于它承诺了什么,而在于它承认了什么。它写明channels.allowed_groups被申报也被存下来了,但不参与访问决定,因为users.groups在任何一条登录路径上都不会被填充——于是基于组的规则没有东西可评估,应当被当成一份等着身份提供方补上组成员关系的声明,而不是一个正在运行的控制。它把 Activity 标签页称作一个窗口而不是一份记录,因为它只活在浏览器里、刷新即失,而审计流水在服务端、能扛住重启。它解释保存下来的文件只贡献路径与体积、从不贡献内容,与那条写入路由一致——那条路由拒绝回显内容,因为 Bot 可能正在保存别人托付给它的东西。它还指出电脑动作不带 initiator,并且这是对的,因为它们是由使用者自己的浏览器会话执行的。桌面这一侧则从另一个方向露出同一种习惯:有评论者指出 macOS 签名工作流是有意不持有证书的,用了-这个临时身份,把签名与公证登记成一个被命名、被刻意推迟的步骤,而不是一件没人注意到的事。
相关档案
全部档案 →第 077 号
Lody
一个让团队共用他们本来就在跑的编码 agent 的工作台:连上一台机器,把 Claude Code、Codex、Kimi 或任何其他说同一套协议的 agent 接进来,然后从桌面端、手机、网页或终端派活;会话之间可以互相派活,而代码始终留在机器主人自己连上来的那台机器上。
第 073 号
Zeron
一个 Rust 桌面程序,把你在用的编码 agent——Claude Code、Codex、Cursor、Devin、Grok、Hermes、Pi、Antigravity——装进同一个控制台,默认只在本机跑、不需要账号;只有你主动登录,它才会把这些会话同步到你其它的设备上。
第 070 号
OpenChatCut
一个本地优先的视频剪辑器,剪辑方式是跟它说话:内置 agent 与外部 Codex、Claude Code 会话调用的是界面自己在用的同一套剪辑工具,于是每一处改动都落在一条真实的多轨时间线上——是片段、转场、字幕、特效或音频,仍然能拖、能撤销、能导出。工程与素材留在本机,预览与最终渲染都出自 Remotion。