回首页

Brain —— AI Agent 桌面工作台

  • Electron
  • React
  • Node.js
  • TypeScript
  • SQLite
  • Langfuse
  • Go

众安信科内部产品

Brain 是我所在团队在众安信科研发的桌面工作台,用来运行 AI 编码 Agent。Codex、Claude Code 和 ACP 协议的 Agent 在本地工作区里并排运行,项目、会话、工具调用、终端、git 和文件都在一处。外壳是 Electron + React,下面是本地 Node 服务;云端控制面用 Go。我 2026 年 3 月加入,这一页写我负责的部分。

LLM 可观测层

问题

首版在事后从聊天消息的结构倒推 Trace。子 Agent 并行时会出几种具体的错:Agent 关闭时父消息被覆盖、运行中的子任务提前结束、指向空处的 turnId、span 结束时间不准。排查一个 Agent 只能翻日志。

我的做法

  • 事件契约:13 种事件(回合、消息、思考、工具调用,以及 6 种子 Agent 事件),4 种结束状态:完成、失败、取消、孤立。结构在采集时就定下来,不靠事后猜。
  • 一个统一的 Trace 采集器,挂在 Agent 旁边运行,不碰界面状态。每次只上传上次之后变了的部分。
  • 所有用户共用一个 Langfuse project,按用户 ID 隔离,不再每人一个。控制端只做鉴权、写入归属、转发。
  • 本地 SQLite 发件箱,用 Node 内置的 node:sqlite,WAL 模式。上传成功就删,失败按退避重试,重启后接着传。上限 500 行、7 天、单条 8 MiB。观测 ID 用稳定哈希,重传不会产生重复数据。

几个关键细节

  • Codex 上报的 token 是会话累计值,每一轮取相邻两次累计值的差。耗时按各轮相加,不用首尾跨度。
  • 个人视图强制只看自己。看别人的 Trace 要单独的权限,部门管理员只看本部门,越权一律返回「不存在」。
  • 打包工具把 node:sqlite 当成了第三方包,队列悄悄退化成只存内存。我改了加载方式,并给打包产物加了检查。

发件箱只是缩小数据丢失的窗口,不承诺绝对不丢。

后台有自己的观测树,按个人、部门、全公司三级查看,用量大屏读的是同一套事件。已上线。

      • 调用模型1.9k tokens,3.1 秒
      • 写入计划3 步
      • 读 Git 提交37 条
      • 读日历5 个会议
      • 调用模型4.2k tokens,5.4 秒
      • 调用模型6.8k tokens,14 秒
      • 生成文档周报.md
一次运行在观测树里的样子,示意数据。

人机共用浏览器

这个决定

原来的内置浏览器只给人用。Agent 操作不了用户正开着的页面,也用不上用户的登录态。我 8 月 9 日的第一版方案是给 Agent 一个独立页面,不做密码库。两天后我推翻了它:由一个 Browser Host 统一管理,人和 Agent 共用同一批页面、标签和登录态。

保证人和 Agent 操作同一个页面的,不是哪个组件,而是一条规则:一个标签只对应一个页面实例。

控制怎么做

  • 对模型只开放一个工具 browser_js。Agent 写 JavaScript,调用一个有 20 个动作的浏览器门面;门面由同一份目录生成,三种 Agent 引擎共用。
  • 每个会话拿一个短期的能力凭证,每个回合拿一个唯一的租约。每个标签有串行命令队列,可以硬取消;每个请求都带回合、页面、控制权三个版本号,导航或人工接管之后,旧请求不能再提交结果。
  • 同一个标签同一时刻只有一方操作,人优先。「停止」会拦住后续动作,但不假装能撤销已经提交的表单。
  • 黑名单优先于白名单。Cookie、存储、剪贴板、执行脚本这些能力按站点首次询问:允许一次、本站始终允许、拒绝,都可以撤销。

看得见,也安全

  • Agent 动手前,目标边缘会亮起一圈光,模拟光标沿曲线移动 400 到 1200 毫秒,短文本按每字 45 毫秒输入,人能跟上它在做什么。
  • 密码用 Electron safeStorage 加密,明文不离开主进程;Agent 用已存密码前要按站点授权。支持从 Chrome、Edge、Brave 一次性导入密码、Cookie 和浏览记录。
  • 审计记录从结构上就不收秘密:只记「向密码框输入过」,而不是先存正文再脱敏。
  • 每个会话一个浏览器实例,后台最多保活 6 个,按最近最少使用回收。关掉了后台降频,否则后台会话里的 Agent 会慢得没法用。

从 webview 迁到 WebContentsView 写在方案里,还没做;现在跑的是 webview,通过 CDP 代理给 Playwright 使用。

设计能力扩展

先完整移植

我把 Open Design,一个开源的 AI 设计工作台 移植进 Brain,版本固定在 v0.14.2:Studio、daemon、公共包和资源,每一样都记下了来源。整站 iframe 改成直接接入 React 源码,iframe 只留给不可信的预览内容。砍掉了在线部署、公开分享和独立记忆。

再重做

移植版是一个「静态资源浏览器加导出按钮」,和旁边的对话互相不知道对方存在。上下文进、产物出、反馈回,三条边都是断的。8 月 5 日起我把它重做成扩展(设计系统、模板、预览、评论批注、版本、导出)加一个提供技能的插件,项目、会话、文件、终端都复用 Brain 已有的能力。

  • 给扩展平台加了两项能力。预览桥:扩展自己声明注入脚本,不超过 256 KiB,用 SHA-256 锁定,每个扩展最多 8 个。输入框草稿:面板可以把草稿写进输入框,但绝不自动发送,单条不超过 8 KiB,每 10 秒最多 5 次。
  • 把原来写死在核心里的设计专属代码拿了出来。
  • 状态存在项目里:一个给 Agent 读的 design.md,一个按版本号乐观加锁的 state.json,以及每个文件都记了 SHA-256 的版本快照。

平台升级之后的取舍

平台换到 1.6 版接口后,桌面导出没有跟过来,PDF 和 PPTX 导出暂时下线。对不上的源码标注直接放弃,不去猜。

没标注的元素只是不能手动编辑,比标错之后写坏源码安全得多。

现在有 333 个设计技能、297 个模板,是一个独立的仓库。我还给团队做了一次 30 分钟、12 页的技术分享,结论是:Open Design 不是新的设计模型,而是一套让通用编码 Agent 按设计流程工作的上下文系统。

文档与桌面端

Office 与 Markdown

  • DOCX、XLSX、PPTX、PDF 只读预览。表格在 Web Worker 里解析,只渲染有内容的单元格;幻灯片按窗口懒加载。单文件上限 20 MiB,拒绝 ZIP64、加密文件、不安全路径和伪造的扩展名。选中一段文字可以直接发起 Ask AI,并带上原文位置。
  • Markdown 富文本、源码、Diff 三模式编辑器,基于 MDXEditor,Diff 用 CodeMirror merge。修了保存期间继续编辑导致内容丢失、切换文件后显示旧内容、外部修改覆盖正在编辑的内容。

Windows 与发布

  • 5 月到 6 月建设了桌面端的多平台版本发布与自动更新。
  • PowerShell 守护进程转发输出时吞掉了本地服务的就绪信号。修复时保留了 Job Object 和退出码传递,半启动状态也不再干等满 15 秒超时。
  • 同步检查版本号被 Defender 首次扫描卡住,改成存在性校验、缓存加异步解析。
  • 磁盘写满时日志内容写进了打包后的 package.json,现在打包后会校验。
  • 中文路径:绝对路径改由服务端生成,前端不再自己拼。

配套基础设施

  • 团队的 LLM 网关,前后三代:3 月 CLIProxyAPI,4 月底 sub2api,6 月 New API。选型、容器化、内网部署、密钥、额度和用量都是我做的。用户从组内 8 人扩展到 40 余人,之后移交同事维护。
  • 用量度量:用 Go 写的采集器把会话日志读进 PostgreSQL,按会话和回合去重,重复读取不会重复计数;上面是 dbt 建模和 Lightdash 大屏。后来网关自己就能提供 9 个字段里的 7 个,这条采集链路就退役了。
  • 部署:Docker Compose 管镜像仓库、PostgreSQL、Redis、MinIO 和网关;kind 管控制端和工作区;从 Helm 换成 Kustomize;init、build-and-push、deploy、smoke 四个脚本。
  • 文档:MkDocs Material 文档站直接由 Go 控制端提供,后来整体重写为 30 页,并配了一个能根据文档回答问题的技能。

学到的

  • 结构在哪里产生,就在哪里定下来。Trace 变可靠,是因为它的形状在采集时就固定了,而不是事后还原。
  • 规则比组件靠得住。共用浏览器能成立,靠的是「一个标签一个页面实例」,和用什么组件渲染无关。
  • 没做完的就写没做完。分享里的实测对照表一直标着「待补」,没有填编出来的数;迁到 WebContentsView 仍是计划;Windows 上工具调用密集时仍然偏慢。

时间线

  1. 2026.03入职;ACP 调研,第一代 LLM 网关
  2. 2026.04用量链路接到大屏;网关换成 sub2api
  3. 2026.05桌面端发布与自动更新
  4. 2026.06kind + Kustomize 部署;网关换成 New API
  5. 2026.07Trace 链路重构;移植 Open Design;Office 预览
  6. 2026.08设计扩展重做;定下并实现统一 Browser Host
  7. 2026.09按站点授权、密码库、Chrome 导入、按会话隔离