远程执行器
为智能体提供一台可以实际操作的电脑,支持 Linux、macOS 或 Windows。
什么是远程执行器
Nessie 中的智能体没有自己的电脑。它可以读取 Nessie 中的内容、与人交流,并通过网络调用已连接的工具,但它无法打开笔记本电脑上的文件、运行命令,也无法查看只存在于某人登录状态之后的页面。远程执行器就是让智能体获得一台可以工作的机器的方式。
执行器是一个小型守护进程,你需要将它安装在自己控制的电脑上。它会主动与你的 Nessie 实例配对,借助一把永不离开主机的密钥证明自己是哪台机器,然后只提供一组固定的、有名称的操作,此外别无其他。工作以单独签名的命令到达;结果则以有界的结构化回执返回。这台机器从不接受来自 Nessie 的入站连接。
准确说明执行器不是什么,这一点很重要,因为大多数远程访问工具都属于下列某一类,而执行器刻意不属于其中任何一类。它没有 SSH,没有常驻的远程 shell,不能挂接到你已经打开的终端复用器,没有来自云端的标准输入,也不是通用的本地网络代理。它不是 MCP 服务器,也不是容器或云端执行环境——Nessie 已经提供这些功能,它们是另一回事。执行器是一个携带能力凭证的端点,只提供封闭的操作列表,而这份列表就是它的全部对外能力。
执行器归谁所有
每个执行器在创建时都只有一个范围,创建之后无法更改。该范围决定谁可以调用此执行器,以及谁可以管理它。
| 范围 | 谁可以调用 | 谁管理访问权限 |
|---|---|---|
| 私有 | 发起请求的人员和被调用的智能体必须同时是被指定的使用者,缺一不可。 | 被指定的人类管理员。智能体只能使用私有执行器,不能管理它。 |
| 项目 | 有权访问该特定项目的人员,且只能在该项目中的运行里调用。 | 组织管理者,或项目所有者或管理员。 |
| 组织 | 拥有组织权限的人员。 | 组织管理者。 |
私有执行器必须始终至少有一名处于活动状态的人类管理员。直接移除最后一名管理员会失败;如果某次离职流程会导致没有任何管理员,执行器将停止接受新工作,处理完手头的工作后自行撤销。组织所有者拥有一条仅限撤销的紧急通道,可以结束他们并不直接管理的执行器,但不会向其展示该执行器的私有成员名单、会话或内容——私有访问权限绝不会被悄悄转交给他人。
智能体实际能用它做什么
操作词汇表在代码中固定,不按部署单独配置。它分为两类,这一划分决定你需要安装什么:有些操作由守护进程从其自己的临时目录直接提供,完全不需要虚拟机;其余操作则需要主机上每个会话专用的客户机虚拟机。
| 操作 | 作用 | 客户机虚拟机 |
|---|---|---|
file.list, file.read | 列出并读取配对时所选唯一工作区根目录之下的文件。 | 否 |
file.write | 写入该工作区的写时复制草稿。它从不以写入方式打开真实的根目录。 | 否 |
workspace.review | 报告草稿发生了哪些变更——最多 100 个相对路径,并附带类型和字节数,以及清单摘要。它不包含任何文件内容。 | 否 |
sandbox.stop | 终止本次运行所拥有的会话。 | 否 |
command.run | 在没有出站网络的客户机中,以不经过 shell 的参数向量运行一条命令。此路径中的任何地方都不存在 shell 字符串。 | 是 |
browser.open, browser.observe, browser.act | 在客户机内驱动浏览器,访问机器上配置的源地址列表。观察操作返回有界的无障碍树,以及可选的缩小图像;动作包括导航、点击、输入、按键和滚动,且只能针对智能体刚刚观察到的节点执行——从不使用选择器、坐标或脚本。 | 是 |
coding.launch, coding.observe | 在客户机中启动受管的 Codex 会话,并读回有类型的生命周期状态。没有终端挂接,也没有提示通道:智能体只能得知会话是否在运行,无法看到屏幕上的内容。 | 是 |
workspace.promote | 将已审阅的草稿应用到真实工作区。这是唯一会写入主机的操作,并且刻意不向任何模型开放。 | 否 |
不需要客户机的操作构成工作区套件。无法启动客户机的主机并非损坏的执行器:它仍可正常配对,将其沙箱后端报告为 none,且只提供工作区套件,没有其他操作。这正是没有 Hyper-V 的 Windows 版本,或当前用户无法使用 /dev/kvm 的 Linux 机器所处的状态;界面会明确说明这一点,而不是含糊地失败。
智能体绝不会自行发起浏览器工作。普通的单操作绑定路由会直接拒绝 browser.open 和 browser.observe;浏览器运行由人员在某个频道中发起,作为一个包含四个操作的完整套件,在全新运行中启动,之后不能再向其中添加任何绑定。受管编码会话的处理方式相同。
代码中还存在另外两组操作,但它们被刻意设为不可用。用于驱动你已登录的 Chrome 标签页的操作,已有完整的本地实现和原生消息扩展,但在服务器能够证明发起对话是私密的、并记录谁披露了什么之前,控制平面拒绝公布它们——这一基础有意保持惰性,且该扩展未包含在任何安装包中。另外,若干编码操作(attach、prompt、interrupt 和 close)已在架构中命名,但尚无实现,因此无法授权。
工作原理
连接始终由执行器发起
守护进程只向你的 Nessie API 发起出站 HTTPS 和 WSS 连接,别无其他。Nessie 从不主动连接笔记本电脑,也从不保存其地址,并且从不把任何目录中的端点视为机器传输通道。因此,执行器无需端口转发,也无需入站防火墙规则,即可在家庭网络、NAT 之后或企业 VPN 中正常工作——而停止守护进程,就等于立即且完整地断开连接。
API 源地址必须使用 HTTPS。唯一的例外是本地回环地址,供在自己机器上运行 Nessie 的用户使用,并由其专用环境变量控制;没有任何普通标志能把生产源地址改为明文 HTTP。
配对既证明机器身份,也需要人员确认
配对是双向的证明。有权限的人员在 Nessie 中按指定范围创建执行器,Nessie 随即签发一个注册码:一个 256 位的随机挑战,Nessie 只保存其 SHA-256 验证值,有效期为十分钟,且只能使用一次。
在机器上,守护进程生成一对 Ed25519 密钥,将其保存在仅所有者可访问、受操作系统保护的存储中,并在发起任何网络请求之前将精确的签名请求写入磁盘——这样,即使响应丢失,也能使用同一把已准备好的密钥重试,而不会悄悄地完成两次配对。随后,它提交注册码 ID、挑战、公钥以及证明签名。Nessie 保存公钥及其指纹,从不保存私钥。
随后,Nessie 会向某位人员展示该指纹,由其确认。在此确认及随后的持有证明完成之前,执行器保持离线。配对绝不能通过聊天文本或终端记录完成,必须由人在网页或桌面界面中进行明确的操作。
丢失密钥的机器无法重新认领其执行器记录。该执行器会被撤销,并作为新执行器重新注册。与此不同,密钥轮换是一笔由旧密钥和新密钥共同签名的单一事务。
描述符是机器对自身的签名声明
已配对的守护进程会发布一个描述符:这是一份经过签名、版本号单调递增的声明,仅包含结构性事实——它支持哪些操作的架构、资源和网络限制、平台,以及其本地策略的摘要。它不包含主机路径,也不会在云端产生任何权限。
新版本一经到达不会立即生效。它会被存入待审核状态,必须由有权限的人员查看并确认,才能影响可用的功能。这正是为了防止能力刷新悄悄授予新的权限:新公布的操作默认为拒绝。
请明确签名证明了什么。由已配对执行器密钥签名的描述符,只能证明该密钥做出了这项声明。它不能证明主机未被入侵,界面必须明确说明这一点。
派发:候选项、绑定、命令、回执
智能体从不指定执行器。在运行使用执行器之前,Nessie 会把逻辑操作解析为一个不透明、短期有效的可用性候选项。响应中不包含执行器 ID;数据库只保存该句柄的摘要,以及解析时针对的人员和操作。模型和客户端收到的是一个句柄,而不是可供选择的机器。
可用性由同一个解析器统一处理,API、Worker、界面和助手都使用它:
available(operation, human, agent, immutableRunContext) =
human may discover executor
∩ exact executor-agent-operation grant allows operation
∩ stable logical tool grant allows operation
∩ scope matches immutable run context
∩ executor is online and descriptor is approved
∩ local policy permits operation消费候选项会在数据库锁下创建一个绑定,该锁会再次检查上述每一道关卡,并推进单调递增的围栏号。派发时还会再次检查。结果是:若在两个步骤之间撤销了授权、收紧了策略或吊销了执行器,工作会被直接中止,而不是事后才被发现——重试也绝不会落到与运行所绑定的机器不同的机器上。
命令本身搭载在 Nessie 普通的队列任务和工具调用生命周期之上,而不另建一套。守护进程通过其已认证的控制通道轮询工作,从不被推送。一条命令只会经历四种回执,别无其他:
leased → accepted → started → result-acknowledged每个帧都绑定命令 ID、运行来源、绑定围栏号、能力版本、过期时间、幂等键,以及参数和负载的摘要。守护进程会拒绝不匹配的帧、策略过期的帧、重放的帧,或对已完成命令的第二次结果。参数和终态结果在静态存储时使用 AES-256-GCM 加密;数据库只保存有界的密文和规范摘要,而不保存内容。
如果确认消息丢失,Nessie 不会假定操作已成功。该命令会被记录为结果未知,运行随即进入常规恢复流程;守护进程会在开始工作前把每条已送达的命令记录到本地日志,因此不会重复执行其副作用。迟到的回执仍可以诚实地消除这种不确定性。
信任边界
| 主体 | 可以 | 不可以 |
|---|---|---|
| 人员 | 配对执行器;在拥有权限时管理它;确认访问和策略的变更。 | 放宽机器本身拒绝的策略,或在没有当前权限的情况下采取行动。 |
| 智能体(包括个人助手) | 调用其已可用的操作;为提出请求的人员准备一项拟议的访问变更。 | 管理访问权限、批准自身、选择机器、更改本地策略,或应用它自己准备的变更。 |
| Nessie 控制平面 | 解析可用性、绑定运行、分配命令租约、保存经过脱敏的审计事实。 | 主动连接机器、放宽本地策略、获取主机凭据,或把终端文本当作授权或结果。 |
| 执行器守护进程 | 执行本地策略、向外配对、运行客户机和网关、确认命令。 | 扩大自身范围、接受过期或重放的工作、直接暴露主机工作区或凭据,或把原始本地数据送入审计记录。 |
| 客户机虚拟机及其中的工具 | 在写时复制沙箱中工作,且只能通过网关访问网络。 | 访问主机文件、主机凭据、直接网络或 DNS,或提升主机上的变更。 |
安装并配对执行器
通过 Homebrew 安装 Mac 命令行工具,通过 Homebrew Cask 安装 Mac 应用,通过 APT 或 DNF 安装 Linux 命令行工具,或通过 WinGet 安装 Windows 执行器。每个已配对的团队在电脑上各自保存独立的权限。Nessie 负责管理团队内部的访问,但无法更改本地资源。
安装与配对指南提供了精确的命令、双向的八位数字代码流程,以及本地设置、启动、更新和卸载的方法。
各平台实际验证到什么程度
三种客户机沙箱的状态各不相同,而且差异很大。macOS 是拥有可用且经过实际运行的客户机路径的后端。Linux 上的 Firecracker 后端和 Windows 上的 Hyper-V 后端已经实现,并由主机端测试覆盖——包括启动流程、磁盘镜像、控制与出站传输、草稿协议——但由于这些验证任务从未运行在具备 KVM 或 Hyper-V 的机器上,本项目的持续集成中尚未在真实硬件上启动过任何客户机。无需客户机的工作区套件已在 Windows 上通过真实的控制循环完整验证。在你自己的硬件上完成验证之前,请将 Linux 和 Windows 上需要客户机的操作视为未经证实。Nessie 的配对页面也会用自己的措辞说明同样的内容。
安全与隔离
唯一的工作区根目录,且其路径保留在机器上
配对时只能选择一个规范的工作区根目录:一个目录,而不是一组文件夹,也不能是它们最近的公共父目录。Nessie 只会获知根目录的基本名称,以便用户在界面中识别边界;完整路径保存在仅所有者可访问的机器状态中,从不上传。更改根目录是可能的,但前提是必须先删除所有本地草稿和沙箱,并且更改会生成新的描述符版本,同样需要经过人工审核,如同任何其他策略变更。它永远不会悄悄扩大到父目录。
文件操作只接受相对路径。它们会拒绝路径遍历以及任何符号链接组件,重新检查已配置的根目录是否仍然是普通目录,并返回有界的结构化结果,且结果中不含主机路径。
写入只写到副本,只有人员能应用
智能体从不写入你的文件。file.write 会在守护进程自己的状态目录下,按运行建立一个有界的写时复制目录树,之后该运行的读取和列表操作都能看到这份草稿。包括编码会话在内的客户机工作,使用的也是同一份写时复制的临时空间。
将草稿应用到真实工作区是一项独立的操作——workspace.promote——它是系统中唯一的主机写入操作。它完全没有面向模型的架构:无论是智能体、助手还是调用方提供的路径,都无法把草稿变成主机写入。取而代之的是,由人员打开你审阅过的草稿,点击审阅应用,并输入当前密码确认。服务器随后会重新检查已确认的审阅摘要、清单摘要、发起运行的用户与智能体、授权版本、操作授权以及当前生效的本地策略,然后才会创建命令。在机器上,守护进程会自行重建清单,并拒绝摘要已经变化的请求——因此,审阅之后做出的编辑无法借助审阅的批准蒙混过关。
应用操作本身基于描述符并有日志记录。原生辅助程序接收的是已打开的工作区根目录和草稿目录描述符,而不是路径;它以不跟随链接的方式逐一验证每个组件,拒绝符号链接、硬链接、特殊文件和跨挂载点的情况,并保留一份全有或可恢复的日志。因此,即使发生崩溃,系统也会要么完成已验证的清单,要么先恢复原始内容,然后才执行任何其他操作。
客户机没有网络,且出站流量被强制经过网关
当某项操作确实需要客户机时,它运行在每个会话专用的 Linux 微型虚拟机中。该虚拟机没有主机主目录、没有 Docker 套接字、没有 SSH 代理、不继承任何环境变量,并且除工作区共享外不挂载任何主机目录。可执行的运行时挂载为只读;可写的工作区挂载禁止执行,因此任何运行的内容都来自已验证的运行时载荷,而不是智能体写入的文件。客户机在打开任何套接字之前就降为非特权身份;若共享目录归 root 所有,启动将失败,而不会留下一个以特权身份运行的工作负载。
最重要的是,客户机没有网络接口。在 Linux 上,启动流程刻意不配置任何网络,也不创建 TAP 设备;在 Windows 上,安装过程中会移除 Hyper-V 默认添加的虚拟网卡。客户机唯一通往机器外部的路径,是其内部的一个回环代理,它通过虚拟套接字隧道连接到主机上的桥接器,再把数据交给守护进程自己的网关。该网关是一个仅限所有者访问的本地套接字监听器,没有 TCP 监听,也没有通用转发模式。HTTP、CONNECT、WebSocket、重定向、来源、下载和上传策略都在这个网关中执行,并使用 Nessie 现有的固定地址抓取机制,而不是为同样的规则另建一套实现。这里没有 NAT 网桥,也没有直接的 DNS 解析器:备用 DNS、原始 TCP、QUIC 和绕过代理的流量全部被拒绝。
网关强制执行的源地址列表由机器的所有者在机器上配置,并且刻意不上传。界面会说明这一点,而不是假装 Nessie 是一个源策略编辑器:若想了解浏览器执行器可以访问哪些地址,请询问机器的所有者。
凭据
主机凭据存储从不挂载到任何客户机中,包括钥匙串、~/.codex 或 ~/.claude、全局 CLI 令牌,以及携带 API 密钥的环境变量。受管编码会话唯一支持的登录方式,是一份仅所有者可访问的身份验证文件;其内容只由所有者控制的 initrd 构建器读取——Nessie、描述符、日志或命令参数都绝不会读取它。该文件会被一次性移入客户机内的私有主目录,该目录随虚拟机一并销毁。该客户机只能访问一个源地址。
浏览器执行器的限制更为严格:每个会话都使用全新的私有浏览器配置文件,并拒绝工作区准备的配置文件,因此它启动时没有 Cookie、没有扩展,也没有任何环境中的登录状态。
原始本地数据只能在明确、有界的运行中发送给模型提供方。Nessie 保存的是经过脱敏的清单、参数和策略摘要、结果摘要以及结构化状态。文件内容、终端输出、浏览器 DOM、凭据和身份验证因素,均禁止写入数据库记录、审计条目、日志、实时事件和错误报告。
操作者授予什么权限,以及如何收回
使用执行器的权限不是一个总开关。只有当智能体持有针对该特定执行器和该特定操作的授权,并且常规的逻辑工具策略允许,并且运行范围匹配,并且机器自身的本地策略许可时,智能体才能调用某项操作。因此,为一个执行器授予某项操作,并不会在另一个执行器上授予任何权限;而能力刷新也无法扩大权限,因为新操作默认是拒绝的。
智能体访问权限和共享设置都会立即在页面上生效,无需审批确认、密码提示或重新认证步骤。在执行器的智能体标签页中,管理者可以直接开启或关闭某个智能体对该机器的访问;在共享中,他们可以以相同方式授予某人“可使用”或“管理员”权限,或把使用权扩展到某个项目或当前团队的所有成员。仅在你自己的助手对话中(绝不在共享频道、计划任务或其他智能体的运行中),助手可以改为准备一项智能体访问或指派变更,它会在该对话中发布一张确认卡片;只有你按下卡片上的“允许访问”,变更才会生效——聊天文本绝不构成确认。
以下三类变更在确认时仍需要你重新输入当前密码:激活描述符版本;由助手准备、将机器指派给某人(而非智能体)的操作;以及允许同事以机器所有者身份在该机器上启动命令的常设策略,即无人值守的工单处理策略。断开或删除机器时,系统刻意不要求输入密码,因为紧急停止开关绝不能比它所要停止的东西更难触发。草稿的应用操作则始终需要密码。审计记录会分别记录执行操作的人员以及助手的参与情况。
执行器会经历一组小而明确的状态:
pending_pairing → online ↔ offline
│ ↓
└──────────→ draining → revoked
↓
error页头的电脑菜单是管理者准备每项生命周期变更的地方:暂停、暂停后恢复、断开连接或删除。暂停会让执行器保持在线,但停止其接收命令。断开连接会使其客户端证书和所有未完成的候选句柄失效,且无法撤销——已断开的执行器必须作为新执行器重新配对。删除的效果相同,并且还会将该执行器从列表中移除;与断开连接不同,无论执行器处于何种状态(包括待配对和已断开的状态)都可以删除,因为这是它离开列表的唯一方式。排空——在停止接收更多工作之前完成手头已有的工作——是协议中真实存在的第三种状态,界面可以显示电脑处于该状态,但这里没有任何操作会将其启动:只有直接调用 API 才能做到。每一次已确认的访问变更、描述符审核和生命周期转换(包括排空)都会推进守护进程的连接纪元,因此其下一次控制轮询(最多延迟一秒)会以失败关闭的方式运行,并在重新连接之前停止所有正在运行的客户机。撤销不是机器可以忽略的请求。
运行执行器
检查运行是否正常
Nessie 自身的判断依据是存活状态。守护进程会签署心跳;若执行器最后一次经过认证的活动距今超过六十秒,它会在被列出、选中或派发之前被持久标记为离线。显示为在线的执行器,说明其在过去一分钟内刚刚证明了自身状态。
机器上没有健康检查端点——守护进程出于设计,不监听任何面向操作者的端口。在 macOS 和 Linux 上,请直接询问命令行工具:
nessie-executor status # every paired executor, plus linger state
nessie-executor status <executorId>
systemctl --user status nessie-executor@<executorId>在 macOS 上,status 会报告每个团队的 launchd 代理。systemctl 命令仅适用于 Linux。在 Windows 上,托盘图标可一眼看出状态,其菜单会说明原因,详细信息则记录在服务日志中。在两个平台上,Nessie 中执行器的概览标签页都会显示其已批准的配置文件、数据边界、最后一次在线时间,以及任何等待审核的本地策略提议。
日志
| 平台 | 位置 |
|---|---|
| Linux | journalctl --user -u nessie-executor@<executorId>;守护进程本身不保存日志文件 |
| Windows | %ProgramData%\Nessie Executor\logs\service.log,托盘中的打开日志文件夹即可打开该位置 |
所有需要用户处理的拒绝情况都会记录在那里:未签名或被篡改的运行时、无法保持安全的状态目录、开机时未能启动的执行器。配对挑战、密钥或子进程的输出绝不会记录在那里。没有可以调高的日志级别设置,因为没有更详细的内容可以开启。
Mac 命令行工具会将每个团队的服务日志写入 ~/Library/Logs/NessieExecutor/<executorId>.log。
升级
通过 Homebrew、APT 或 DNF 升级命令行工具,然后依次执行 disable 和 enable,以重启每个团队的服务。WinGet 负责升级 Windows 执行器。Nessie 桌面版安装程序提供已签名的应用内更新;MSI 和 Debian 安装则使用各自的包管理器。配对和本地权限在升级后保持不变。
停止与卸载
停止是由守护进程自身负责的优雅停止流程,而不是强制终止。它会收到终止信号,停止所有客户机会话,释放其租约,然后退出。在 Linux 上,单元会等待十五秒,而清理的时间预算为十秒;它刻意从不升级为无法捕获的强制终止——因为若守护进程在清理过程中被强制终止,微型虚拟机和工作区覆盖层就会失去负责清理它们的进程。因此,停止时若出现挂起,会在 systemctl --user status 中明确显示,而不会悄无声息;是否升级为强制终止,必须由人工明确决定。
卸载 Linux 软件包:
nessie-executor disable <executorId> # stops and disables the service
sudo apt remove nessie-executor
loginctl disable-linger # only if your user manager should stop running at boot too在 Windows 上,msiexec /x 会停止并移除服务、其注册表项以及托盘的开机启动项。两个平台上,已配对的状态都会被刻意保留——Linux 上为 ~/.local/state/nessie-executor/,Windows 上为 %ProgramData%\Nessie Executor。配对包含机器密钥和已签名的策略版本,卸载程序并不意味着要销毁它们;重新安装时会在原位找到它们。如需忘记某个配对,请手动删除该目录,并在 Nessie 中撤销该执行器,从另一端结束配对。
Windows 托盘和桌面伴侣都提供在此电脑上忘记配对这一一等操作:它会停止本地守护进程,移除机器密钥和文件夹选择,并在一次原生确认后永久删除本地草稿副本——同时保留服务器端的执行器及其审计历史,由所有者决定保留还是撤销。
常见故障
| 现象 | 含义 |
|---|---|
| 执行器可以配对,但只提供文件操作 | 主机没有报告可用的沙箱后端。在 Linux 上,请检查你是否能读写 /dev/kvm,以及你是否在 kvm 组中——将自己加入该组后,需要注销并重新登录。在 Windows 上,该版本没有 Hyper-V;这是版本本身的限制,而不是可以更改的设置。 |
| 执行器控件完全缺失 | 此构建无法验证其确实来自预期的发布者。在 Linux 上,运行时必须由 root 拥有,且不得有组或其他用户的写权限位;在 Windows 和 macOS 上,签名必须与构建中固定的发布者或团队一致。每种情况都会用文字说明拒绝原因并给出解决办法,而不是隐藏控件。 |
| 服务在运行,但没有启动守护进程,并拒绝所有命令 | 安装内容在打包后被替换过。这是预期的行为:被篡改的安装会返回原因,而不是消失,因为服务停止会让托盘给出错误的处理建议。 |
| 运行以结果未知结束 | 终态确认丢失。Nessie 不会报告它没有收到的结果:该命令被标记为未知,运行进入恢复流程,且副作用不会被重复执行。守护进程迟到的回执仍可消除这一不确定性。 |
| 昨天能成功的操作今天被拒绝 | 在绑定与派发之间有某道关卡发生了变化,而每一步都会重新检查:授权被撤回、描述符版本等待审核、本地策略收紧、范围与运行不再匹配,或执行器被撤销。拒绝信息会说明具体是哪一项。 |
| 智能体请求浏览器,却被告知无法使用 | 浏览器和编码工作由人员在频道中以完整套件的形式、在全新运行中启动。普通绑定路由出于设计会拒绝它们,并且不能向已在执行其他任务的运行中添加任何浏览器操作。 |