Cognition 宣布为其 AI 软件工程师 Devin 推出原生的 macOS 云端支持

为什么 AI 软件工程师必须拥有一台 Mac,以及 Cognition 如何从存储、网络、镜像准备、实时画面和无障碍树打通原生应用的运行验证闭环。

Cognition 宣布为其自主 AI 编程智能体 Devin 推出 macOS 支持,将其自主云端开发工作流扩展至 iOS 应用、原生 macOS 程序以及所有依赖 Apple 开发工具的项目。

为什么 Devin 必须有一台 Mac?

要让 AI 智能体在苹果生态中独立完成开发任务,面临着两个递进的现实要求:

  • 编译与启动不能证明运行时行为正确:在本地开发中,代码助手很容易根据编译器报错不断修改代码直至构建通过。但对于面向用户的图形界面应用,单纯代码编译通过、进程成功启动并不等于实际工作,真正的验证在于运行时行为与状态还原。
  • 原生应用验证与工具链依赖 macOS 工作区:苹果生态的原生应用深度依赖 Xcode、iOS 模拟器等专属开发工具链;要验证应用在运行时的真实表现,智能体必须拥有能够实际运行、操作与核验的原生 macOS 工作区。

例如开发一款 iPhone 手机游戏,核心需求是即便用户退出游戏,再次打开时也能精准回到上次暂停时的状态。单纯编译通过与成功启动,无法保证游戏引擎正确保存并还原了运行数据。智能体必须像真实用户一样完成“玩、暂停、退出、重开并验证恢复”的完整闭环。

Devin 录制的验证过程:操作游戏、暂停、退出并重新打开,检查运行状态是否正确恢复。

在云端把这套闭环跑通并不简单。在虚拟机里把 macOS 跑起来只是第一步;要让它成为一个可用的自主开发工作区,必须在底层解决数据状态持久化、会话网络安全隔离、开机免人工干预配置,以及人机两端的实时画面与控件操作问题。

Devin Cloud 选择 Mac 环境

这些工作沿着同一条五层验证链逐层衔接:底层先打通存储快照并管住网络,镜像准备把人工弹窗移出任务时间,实时画面让用户查看和接管运行中的应用,结构化无障碍树则让 Devin 能够查询、操作并检查原生控件。

从云端基础设施到运行结果

Mac 工作区的五层验证链

每一层解决一个阻断点;全部接通后,Devin 才能从修改代码走到实际操作并核验原生应用。

  1. 01 保存会话

    NBD 把虚拟磁盘接入原有快照后端,退出后先完成持久化。

  2. 02 约束网络

    用户态网关处理以太网帧,再把 IP 流量交给 pf 与代理策略。

  3. 03 准备环境

    离线写入用户与配置,启动后安装工具、验证 Xcode 并预热模拟器。

  4. 04 看见与接管

    Mac 桌面和 iOS 模拟器画面经过受控队列传给用户。

  5. 05 操作并验证

    无障碍树定位控件,截图核对树中没有的视觉状态。

验证失败时回到代码与环境继续修改;验证通过才闭合开发循环。


1. 存储层设计:用 NBD 协议打通跨会话快照

Devin 的云端服务搭建在 AWS EC2 Mac 裸金属服务器上,宿主机通过苹果官方的 Virtualization.framework 虚拟化框架运行 macOS 客体虚拟机。

云端智能体开发的一大特征是异步协作:用户把需求交给智能体后无需全程盯盘,而空闲会话也无需让虚拟机一直运行。为了让用户下一次打开会话时能直接回到上次的工作进度,系统需要一套快照机制来保存会话里的所有依赖项、工程文件与代码变更,免去重新搭建环境的过程。

对操作系统而言,虚拟磁盘是一种底层块设备——只负责按固定大小的数据块读写原始数据,并不感知上层文件系统与快照存储的具体实现。在 Linux 虚拟机中,Devin 通常借助 vhost-user 协议将虚拟磁盘的 I/O 操作直接委托给宿主机上的独立存储进程。但苹果的 Virtualization.framework 并不支持 vhost-user。

作为替代,苹果的虚拟化框架支持另一种经典通信协议——网络块设备(Network Block Device,简称 NBD)。NBD 允许客户端通过本地套接字直接读写远程或宿主机上的块设备。团队在原有的快照存储系统前端增加了一层网络块设备(NBD)前端,无需改动底层的快照后端(snapshot backend),就成功复用了既有的持久化架构,客体虚拟机看到的仍是普通的虚拟磁盘。

虚拟机与快照存储的连接路径

[macOS 客体机内部]
应用与文件系统读写
       ↓
标准虚拟磁盘(块设备)
       ↓
[系统分界线:宿主机]
Virtualization.framework
       ↓ (NBD 协议 / 本地 Unix Socket)
宿主机快照存储进程(NBD 前端接入原有快照后端)

虚拟机的停机生命周期同样需要严格把控。当虚拟机完成任务断开连接并退出后,宿主机上的存储进程继续保持运行,负责保存尚未完成的待写内容并上传快照。宿主机的虚拟化管理器(hypervisor)会严格等待该终结流程(finalization)完成,随后才继续执行最终的资源清理。

虚机退出与快照固化时序

虚拟机状态:   [ 正在运行 ] ──────> [ 断开连接 / 停止 ]
存储进程状态: [ 处理读写 ] ──────> [ 写入挂起数据 ] ──> [ 快照就绪 ]
虚拟化管理器:                      [ 等待数据落盘 ] ──> [ 清理回收资源 ]

2. 网络层控制:自建用户态以太网网关规避防火墙竞态

云端工作区需要严格的网络边界保护:虚拟机既需要根据会话策略访问外部依赖网络,又必须严格阻断对宿主机私有基础架构的访问。

苹果 Virtualization.framework 提供了三种将虚拟机连入网络的方式:

桥接模式(Bridged):将虚拟机的以太网数据帧直接发往宿主机的物理网卡。

NAT 模式:让虚拟机共享宿主机的外部 IP 地址,由 macOS 操作系统接管地址转换。

文件句柄模式(File-handle attachment):通过宿主机本地的 Unix 数据报套接字(Datagram Socket)直接收发原始的以太网数据帧,每个数据报承载一帧,后续处理由接收方负责。

NAT 模式虽然直观,但在该部署环境中,macOS 系统的 Apple NAT 与 Devin 的网络控制机制都会管理底层的包过滤防火墙(pf,Packet Filter)。当两者同时运行时,会竞相配置同一个包过滤器,从而产生规则配置上的冲突与竞态。

为了规避这一冲突,团队放弃了苹果托管的 NAT,选择了最底层的“文件句柄模式”。这一选择带来的挑战在于:宿主机收到的不再是可直接路由的三层 IP 数据包,而是二层以太网数据帧(包含 MAC 地址等物理链路信息)。举例来说,当虚拟机想向外发包前,必须先在局域网内广播 ARP(地址解析协议)请求,询问网关的物理地址究竟是什么。

为此,宿主机上专门构建了一个自建用户态以太网网关来接管这些通信细节:

虚拟机网络数据包往返链路

[ macOS 虚拟机 ]
       │ 原始以太网帧(Guest MAC → Gateway MAC)
       ▼
[ 宿主机用户态以太网网关 ]
  ├── 响应虚拟机的 ARP 物理地址查询
  ├── 校验以太网源/目标 MAC 地址合法性
  └── 核实源 IP 地址是否匹配系统分配
       │ 放行清洗后的三层 IP 数据包
       ▼
[ 宿主机虚拟通道接口(Tunnel Interface)]
       │
       ▼
[ pf 防火墙规则与代理服务 ] ──> 执行会话访问控制策略并出网

这是一种明确的技术取舍:团队承担的明确代价是在宿主机端自行负责数据链路层的解析与校验,以此规避与苹果自带 NAT 竞相配置防火墙的问题,并将接受的 IP 数据包交给宿主机 tunnel、pf 规则与代理服务处理。


3. 镜像预制与预热:在系统开机前切断权限弹窗

只要在 Mac 上装过开发软件的人都知道,一台刚刚完成操作系统安装的电脑离实际干活差得很远。系统里缺少用户账号、可用的桌面、Xcode 工具,更关键的是缺少自动化交互所需的各种系统权限。

macOS 会对屏幕录制、辅助功能控制等权限弹出授权确认窗口。如果把这些问题留到会话开始后处理,每个弹窗都可能让 Devin 停下来等待人类点击。

未做预制处理时 macOS 默认弹出的繁琐权限确认窗口

一种办法是在机器启动后用 UI 自动化创建用户、进入桌面、触发权限请求并逐一批准,但协调这串界面操作既不可靠,代价也更高。

系统采取了分阶段的准备方案:首先在母盘镜像构建阶段离线挂载客体磁盘。宿主机直接将虚拟磁盘挂载为本地目录,绕过图形界面创建系统用户并修改 macOS 内部配置数据库,在开机前预先完成基础配置。

然而,有些依赖项无法完全在离线状态下完成配置。如果将这些任务留到智能体接手后再处理,Devin 就会与系统初始化争用资源。因此,系统在镜像构建阶段还会执行一次“在线预热”:

  • 启动预制好的镜像,安装剩余的开发者工具并验证 Xcode 环境。
  • 提前拉起并“唤醒” iOS 模拟器,等待其内部系统启动就绪。
  • 等待 Spotlight 桌面索引建立以及后台初始化任务全部完成,并主动关掉无关的系统后台守护进程。

通过离线配置与启动后的预热准备,工作区在智能体接入前完成了工具安装、环境验证与不必要后台守护进程的停用,减少了开机后的初始化干扰。


4. 实时画面:让实时画面保持跟手

开发环境就绪后,系统需要让两类角色参与到应用操作中:人类开发者需要观察画面并按需接管,AI 智能体则需要高效检查界面的运行结果。

人类的远程接入主要依靠 VNC 协议呈现 macOS 桌面,并额外提供了一个专门映射 iOS 模拟器窗口的独立视图面板。为了让实时画面足够跟手,团队处理了两个具体的视频工程细节:

缓冲竞争问题:ScreenCaptureKit 使用有限的可复用缓冲区。系统若需保留画面会复制一份独立副本,避免持续占用采集系统所需的缓冲区。

队列积压问题:视频在采集、编码、传输或显示任一阶段跟不上时,队列中都会积压旧帧,导致远程画面产生动作滞后。

为了避免盲目丢帧导致解码异常,系统限制了可排队的帧数上限。一旦检测到模拟器流画面落后,系统会从近期的关键帧(keyframe)恢复,或者请求新的关键帧,使播放端无需重放积压历史即可同步至最新状态。

实时控制演示:用户可以查看 Mac 桌面和 iOS 模拟器中的应用,并在需要时接管操作。

5. 无障碍树:让原生控件可查询

对 AI 智能体而言,操作图形界面依赖于更高效稳定的交互途径。纯粹依靠屏幕截图(Screenshot)的多模态路径在文章中被描述为缓慢且昂贵(slow and expensive):智能体需要截取整屏图片、通过多模态模型定位按钮像素并调用虚拟鼠标,每一步操作后再截图核验。在长交互路径测试中,这种方式十分沉重。

与网页端借助 DOM 树定位元素类似,原生应用具备一套底层基础设施——无障碍树(Accessibility Tree)。系统将界面元素整理成包含角色(role)、名称(name)、取值(value)、状态(state)、关系(relationship)与支持动作(actions)的结构化语义树。

借助 Dioxus 开源项目的 accessibility-cli,系统获得了无障碍访问、输入控制与画面截取等基础能力(accessibility、input、capture primitives)。Devin 由此建立了结构化的操作链条:

智能体操作 iOS 模拟器的语义闭环

1. 智能体发起结构化控件查询
{
  "action": "query",
  "target": "ios",
  "role": "button",
  "name": "Resume"
}

2. 系统返回语义树匹配结果与临时句柄
@i17 button "Resume" {press}
(@i17 为句柄,button 为角色,Resume 为名称,press 为支持的操作)

3. 智能体直接调用句柄执行动作
{
  "action": "act",
  "target": "ios",
  "reference": "@i17",
  "operation": "press"
}

4. 智能体重新读取无障碍树并报告状态变化

通过该工具,Devin 可以直接通过语义树查询并引用控件发起操作,无需在像素图像中猜测控件坐标。

但无障碍树并不能覆盖所有的视觉内容。例如自定义绘制的游戏画面等视觉状态无法反映在无障碍树中,系统依然保留了屏幕截图能力,在必要时配合截图完成完整的状态验证。


适用边界与工程启示

Devin 对 macOS 的支持打通了云端开发与验证苹果原生应用的技术路径,但在评估其适用范围时,仍需理清其技术前提与工程边界:

  • 无障碍树无法覆盖所有视觉状态:看到暂停菜单消失,并不能证明游戏角色的位置已经正确恢复;直接绘制的画面可能根本不出现在树中,因此仍需截图核对视觉结果。
  • 没有量化基准:这套技术说明交代了云端工作区的体系结构与产品能力,但没有提供运行性能、基础设施成本或安全效果的量化数据,不能据此比较它与其他开发环境的效率或成本。

从虚拟磁盘、网络边界与镜像准备,到实时画面、语义控件与截图校验,这些底层工程为 Devin 提供了构建与测试原生应用所需的完整苹果工作区,把单纯编写代码延伸为在真实运行界面里的“开发—运行—验证闭环”。这正是 Devin 获得 macOS 支持后最实质的变化。

来源
Bringing macOS to DevinCognition·2026-09-15·查看主材料
本站说明
本文依据 Cognition 官方技术文章整理。原文说明了架构与产品能力,但未提供运行性能、基础设施成本或安全效果的量化基准。