我们先冻结的不是技术栈,而是产品边界
设计 Node 时,最容易做的事是先画服务图:一个聊天服务、一个文件服务、一个任务服务,再配一个后台。但服务图回答的是代码怎么跑,不回答产品属于谁。我们先定下的事实是:Cove Node 是一个完整的客户机产品,本机使用本身就是一条完整路径。
因此,core/app、core/runtime、core/agent、core/control、core/channels 和桌面壳即使运行在不同进程里,也仍然属于同一个 Node。进程边界服务于稳定性与职责分离,不能反过来制造多个需要用户理解、安装和维护的产品。唯一独立的可选产品是公网传输边界 Edge;不安装它,Node 依然成立。
- 本机或局域网使用不依赖 Cove Cloud。
- 一个 Node 对应一份不可变发行版和一套统一生命周期。
- 内部模块可以独立运行,但不向用户暴露成多个产品。
- 公网入口是可选传输能力,不是 Agent 能否工作的前提。
留下来的判断先确定谁拥有产品、断网后还剩下什么,再选择框架和进程。否则架构很容易围着部署便利生长,而不是围着用户所有权生长。
一份安装目录,两类完全不同的所有权
Node 安装后只有一个 Cove Home,但里面有一道刻意保留的边界:core 由产品发行版拥有,workspace 由用户拥有。前者必须能够验证、升级和回滚;后者必须能够长期生长,而且不能在升级或卸载时被顺手替换。
这条边界比把数据放进某个隐藏目录更重要。它让我们可以原子切换 current 与 previous,而不用迁移用户的文件、数据库、技能和凭据;也让用户能直接检查自己的 Harness、插件和工作资料,而不是把一切埋进应用内部。
<personal-agent-home>/
├── core/
│ ├── releases/<release-id>/ # 不可变产品
│ ├── current -> releases/... # 当前版本
│ └── previous -> releases/... # 可回滚版本
└── workspace/
├── registry/ skills/ plugins/
├── files/ publications/ databases/
└── config/ secrets/ runtime/ logs/留下来的判断升级默认替换产品,不替换用户;卸载默认移除 Core,不删除 workspace。所有权必须能落到目录、发行版和恢复动作上。
Next.js 是界面与 BFF,不是 Agent 的大脑
Node 使用 Next.js App Router 统一 Setup Center、对话、动态、邮件、Pages、技能、渠道和更新界面。它负责本地读取、版本化 BFF 与一致的会话边界,但不会承接长生命周期工作。页面请求结束,不应该意味着 Agent、渠道轮询或备份调度也结束。
真正持续运行的工作留在 runtime 与 agent 服务中:前者管理生命周期、本机网关和产品状态,后者管理 Codex 会话、任务、文件、动态、自动化与发布。channels 隔离第三方渠道状态,desktop 只是复用系统 WebView 的轻量窗口。每层都可以失败和恢复,但它们共同组成一个 Node。
Next.js 页面、认证后的本地读取、版本化 Route Handlers。
安装状态、服务编排、本机网关、更新与恢复边界。
Codex 会话、任务、动态、文件、Pages 与周期自动化。
渠道适配与受清单、权限约束的用户扩展。
只提供远程入口和传输,不成为业务数据的家。
长期工作的 Agent,不能被压扁成一次页面请求
传统 Web 应用常把用户点击、服务器处理和页面响应看成一次完整事务。Agent 的工作不一样:它可能调用多个工具、等待外部渠道、产生阶段结果、被用户中途修正,并在很久以后由计划任务再次启动。用一个 HTTP 请求包住整个过程,既难恢复,也会把界面与运行历史绑死。
所以页面只发起和观察工作,Agent 服务保存可恢复的会话与任务状态。面向用户的动态和任务进展也不是把底层日志原样抛给前端,而是由主 Agent 维护一份可读的展示事实。调试记录服务于诊断,用户记录服务于理解;两者目标不同,读取路径也应不同。
- 页面负责意图提交、状态读取和明确批准,不充当后台任务系统。
- WebSocket、渠道轮询、Worker、备份与计划任务由长期服务拥有。
- 主 Agent 维护用户可见动态,原始工具噪声不直接进入产品页面。
- 失败恢复围绕任务与发行版边界设计,而不是依赖浏览器仍然在线。
连接、模型和扩展,是三条彼此独立的轴
很多 Agent 产品把远程访问、模型供应商和账号体系绑在一起:换模型会影响登录,断开 Cloud 会失去历史,安装扩展又要求把数据交给平台。Node 刻意拆开这三件事。
访问可以是 local-only、自托管 Relay 或 Cove Cloud;模型可以使用 BYOK,也可以连接 OpenAI-compatible Token 网关;能力则通过 Skills、Plugins 和渠道适配器组合。改变其中一条轴,不应该迫使另外两条一起迁移。
本机/LAN、自托管 Edge、可选 Managed Cloud。
BYOK 与兼容网关独立于访问方式。
Skills、Plugins、Channels 各自声明能力与权限。
留下来的判断Cloud 应该像门牌,模型应该像引擎,扩展应该像工具。它们都很重要,但任何一个都不该取得用户工作空间的所有权。
Harness 不是开发脚手架,而是用户能检查的合同
Node 把一套完整 Harness 放进 workspace:AGENTS.md 说明本地所有权与安全约束,registry 声明项目、能力、路由、命令和扩展,skills 与 workflows 说明 Agent 可以怎样工作。它们不是只在源码仓库里有用的开发提示,而是安装后仍然存在、能被用户阅读和扩展的运行合同。
注册表还有一个经常被忽略的作用:区分 implemented、preview 与 planned。界面、CLI 和文档只能把已经落地的能力当作事实。我们宁愿在注册表里明确写出未完成,也不希望一张漂亮的架构图提前替产品做出承诺。
- 用户扩展写入 workspace,不修改不可变 Core。
- 插件通过 manifest 声明版本、能力、权限和贡献点。
- 固定认证、Setup、更新与内部路由不能被插件覆盖。
- 高风险变更继续经过可追踪的 R0–R3 风险与审批模型。
“本地优先”必须能被安全边界证明
把服务监听在 127.0.0.1 并不自动等于本地优先。真正的边界要覆盖凭据写到哪里、谁能发起高风险操作、远程入口能看到什么,以及升级失败时能否回到上一版。
Node 的凭据、数据库、日志和可变状态只进入 workspace;高风险动作使用带摘要、有效期和本机确认的两阶段批准;Edge 只处理 TLS、路由和传输,不持有对话正文、文件、渠道凭据或业务数据库;发行版携带校验、SBOM、provenance,并保留 previous 作为明确回滚点。
- 秘密固定进入 workspace/secrets,不进入源码或发行版。
- 远程访问失败或配额用尽,不影响本机 Console 与 Agent。
- 自托管 Relay 只保存连接密钥摘要,Node 主动建立出站连接。
- 更新与回滚操作围绕不可变制品执行,不在生产目录原地改代码。
留下来的判断隐私承诺只有在断网、升级、恢复和远程访问这几个压力场景里仍然成立,才算架构事实。
这套设计并不免费,它把复杂度放回了正确的位置
本地优先意味着我们必须面对跨平台安装、服务恢复、数据迁移、备份和原生发行;不可变 Core 意味着每次更新都要构建、验证并保留回滚证据;受约束插件意味着扩展不能随意把服务端 React 代码塞进受信任进程。相比一个集中托管的聊天网站,这些工作显然更重。
但这些复杂度换来的是可替换性:Cloud 可以断开,模型可以更换,公网入口可以自建,产品仍能继续工作。用户不需要因为某个供应商、域名或订阅变化,搬走自己的长期上下文。我们把运维复杂度留给产品,把退出自由留给用户。
留下来的判断Cove Node 最终要守住的不是“所有东西都在本机”这句口号,而是用户始终拥有自己的数据、工作空间、运行入口和离开某个供应商的能力。