ai newsDo., 15. Okt.
EilmeldungMeta and Apple team up to make Muse AI models run better on Macs

停掉控制面之后,AI 任务还在跑:我们为什么把它拆成三层

用一个界面对着某台机器上的某个终端窗口,是大多数人开始用 AI 写代码的方式。任务变多之后会出现三个具体问题:任务分散在多台机器上、每个任务需要独立且可丢弃的环境、长任务不能因为浏览器关了或者界面断了就死掉。 这篇讲 TaskHandoff 在这三个问题上做的架构选择:为什么控制面和执行面要拆开,状态到底归谁管,以及由此付出的代价。 问题:任务一多,你就开始手动当调度器 假设你手上有三台机器:一台笔记本、一台常开的家用服务器、一台公司内网主机。你在它们上面分别跑 Codex 或 OpenCode。于是你每天在做这些事: 记得哪台机器上有哪个仓库、哪个分支、哪个 worktree; 手动把环境

dev.toMittwoch 09:49 · 14.10.1 Min. Lesezeit
Bild: dev.to

用一个界面对着某台机器上的某个终端窗口,是大多数人开始用 AI 写代码的方式。任务变多之后会出现三个具体问题:任务分散在多台机器上、每个任务需要独立且可丢弃的环境、长任务不能因为浏览器关了或者界面断了就死掉。

这篇讲 TaskHandoff 在这三个问题上做的架构选择:为什么控制面和执行面要拆开,状态到底归谁管,以及由此付出的代价。

假设你手上有三台机器:一台笔记本、一台常开的家用服务器、一台公司内网主机。你在它们上面分别跑 Codex 或 OpenCode。于是你每天在做这些事:

浏览器 / 桌面端 / 移动端 / 聊天平台 │ ▼ Control Plane(UI、API、聊天网关) │ ▼ Node Agent(节点资源与实例生命周期) │ ▼ Controlled Instance(工作区、应用、AI 会话) Enter fullscreen mode Exit fullscreen mode 关键不在分层本身,而在 每层各自拥有什么状态 :

因为实例生命周期归 Node Agent, 停止或重启 Control Plane 不会顺带停掉节点上由 Node Agent 管理的 Docker 实例 ;控制面板恢复后会重新同步状态。

同理,AI 会话的对话状态以 AI Session 本身为准,控制面负责的是凭据、绑定、命令解析和路由。所以关掉网页不会中断任务——这条被写进了文档 FAQ,因为它是最常被问的问题。

一篇会话绑定固定工作目录,创建后不会自动改变(这条也在文档里)。要换个 worktree 干活,是「在目标 worktree 上新建会话」,而不是「把当前会话挪过去」。这是同一套状态所有权思路的延续:会话不追着环境跑。

这条不用实测也能从状态所有权推出来,文档里也已经把它写成了 FAQ——因为问的人最多:

这里有个最容易误判的坑,我们也把它写进了文档: 页面显示「正在重连」不等于后台任务停了。 如果界面一直卡在重连,问题通常在网络路径上——最常见的原因是反向代理没有转发 /api/events 的 WebSocket,而不是 Agent 挂了。把「显示状态」和「权威状态」分开看,能省掉不少误判。

为什么不把实例生命周期直接放在控制面? 那样控制面重启就会波及正在跑的长任务,而且单点变成了「UI 挂掉 = 所有任务挂掉」。把生命周期的所有权下移到节点,代价是控制面离线期间你只能在节点上继续跑已经存在的实例——新建实例、改配置这类操作都要等控制面回来。

断线重连的语义要写清楚。 界面断线重连时会重新获取权威会话快照。最容易造成误解的是那个「正在重连」提示——它不代表后台任务已经停止。我们把这条明确写进文档,而不是靠用户自己猜:会话状态在 Agent 那边,界面的连接状态只是显示层的问题。

运行时不锁死在 Docker。 Docker Runtime 是当前主要的隔离运行时,一个节点可以跑多个实例;Local Runtime 直接用宿主机环境,同一宿主用户只能有一个本地实例,也不支持 Windows。两者共享同一套实例模型,运行时通过 adapter 扩展,所以将来接 Kubernetes 不需要另做一套 UI 流程。

Quelle: dev.to (dev.to). Original öffnen