
最近圈子里聊AI编码代理的人越来越多Claude Code、Codex、Cursor这些工具我也重度用了一阵子。直到有一天一个需求把我卡住了代码改动AI能搞定但改完之后要自己在测试环境里登录系统、点页面、开表单做一套冒烟验证——这一串GUI操作几乎没有现成的agent能完全代劳。折腾了几个方案之后我决定自己写一个。这个项目最终做成了一款免费开源的AI编码代理核心卖点就三个能操控GUI界面、完整支持MCP协议、整个程序打包成单文件直接运行。所以这篇文我不打算写什么产品发布稿而是把整个设计和实现过程摊开来讲包括我为什么这么设计、踩了哪些坑、实测效果如何。内容会比较长但对想自己动手做类似工具、或者正在给团队选型AI编码代理的朋友应该有不少能直接拿走的东西。1. 为什么我要做这个能动手的AI编码代理1.1 现有编码代理的看不见的手现在市面上主流的AI编码代理本质上都是跑在终端里的agent。它们能读你的项目文件、改代码、执行命令行、跑测试、看错误日志这一套在纯后端开发生态里确实很强。但我用了几个星期之后发现一个明显的边界它们对图形界面基本是瞎的。举个真实例子。我手头有个老项目需要做一次小升级前端界面逻辑改了涉及一个流程表单的字段调整。代码层面AI改得很干净但你依然要自己打开系统、用测试账号登录、一步步点到那个页面去验证改动是否生效。这种打开系统-登录-导航-操作-截图确认的工作在大多数编码代理眼里根本不存在因为它们的观测通道只有文本和命令行输出。这不是某个厂商做得不够好而是架构上的一种盲区。终端型agent的所有感知都建立在结构化文本上GUI世界的像素、控件、窗口状态对他们来说是不可见的。如果你面临的实际工作流里有很大一部分是改完代码之后还要在界面上确认效果那现有的编码代理体验就永远差了一口气。1.2 项目定位与三条硬约束想清楚痛点之后我给自己定了三条硬约束既是产品定位也是筛选需求的手段免费开源不搞闭源收费代码仓库直接公开任何人可以拿去用、改、内部分发。单文件运行分发形态是一个可执行文件拷过去就能跑不要求目标机器装一堆依赖。同时支持GUI操作和MCP协议这是和主流终端型agent最大的差异化也是这个项目最核心的工作量来源。定这三条约束是有原因的。免费是为了降低尝试门槛单文件是为了让能操控GUI这件事真的可以被普通开发者用起来——如果还需要安装Python环境、配置一堆动态库那能操作界面这个卖点就废了一半。GUI和MCP两件事绑在一起则是因为我想做一个真正能落到实际工作流里的agent而不是又一个只能在终端里自嗨的玩具。1.3 不重复造模型我写的是调度中枢刚立项的时候有人问我你是不是要去微调一个模型或者自己训练识别UI的模型我说不是。这个项目真正的核心技术不在模型侧而在调度中枢。我的定位是模型用现成的可以是本地跑的、也可以是云端API我只需要把屏幕观测、工具调用、行动执行、结果汇总这几个环节串起来写成一个高效的、可扩展的agent框架。至于最终决策用什么模型那是可配置项我不绑定任何一家。技术栈上我选了Rust。原因也很朴素单文件分发这件事Rust做静态编译很成熟跨平台时不用带解释器或运行时而且并发处理和系统API调用的生态比较顺手正好是我后面要做GUI操控时的硬需求。老实说如果只用Python写原型一周就能跑通但距离一个文件拷过去能跑的交付态还差得很远。用Rust写前期开发慢后期分发爽。2. GUI操控能力给代理一双眼睛和能点击的手2.1 三层结构观测、决策、执行让AI代理操作GUI我没有选择那种AI自己画一个界面然后模拟操作的不切实际路线而是采用了最贴近真实用户行为的感知-决策-执行闭环拆成三个独立模块观测层负责看。采集当前屏幕内容、当前活跃窗口的控件树、鼠标键盘状态。输出是一份结构化的屏幕摘要包含控件类型、位置、文本、可用状态。决策层负责想。把观测结果和用户指令一起丢给大模型让它决定下一步动作。动作被严格限制在一张预定义的行为列表里点击、双击、右键、输入、按键、滚轮、等待、截图、读取文本。执行层负责做。把模型输出的动作翻译成真实的系统级鼠标键盘事件注入到目标窗口操作完成后再次触发观测形成闭环。这个设计里最关键的是第一层。因为GUI操作的本质问题是AI不知道屏幕上有什么只有把屏幕变成可读的数据后面的决策和执行才有意义。2.2 观测层的两套方案无障碍树和OCR兜底观测层我同时做了两条路按优先级使用。第一路是系统无障碍API读取界面元素树。Windows上有UI AutomationmacOS上是Accessibility APILinux桌面则走AT-SPI。这相当于让AI直接阅读界面的DOM结构能拿到控件的准确类型、坐标、名称、状态精确度非常高。大多数主流桌面应用、浏览器页面、以及基于Qt/Electron/WPF的应用都能从中拿到有效信息。这一步做得好AI的点击操作基本不会点偏。第二路是屏幕截图加OCR作为兜底。无障碍树不是万能的有些游戏、自绘界面、远程桌面画面根本不给树或者树是空的。这时候就只能靠截图然后对截图像素做文本识别和元素定位。我内置了一个轻量级的OCR引擎并在程序里做了区域裁剪和对比度增强的预处理让OCR在小控件文本上也能达到可用的准确率。两套方案切换的规则很简单先尝试无障碍树失败或超时则自动降级到OCR模式。对用户来说这个切换是无感的但决策层拿到的观测数据会标记来源这样模型就知道自己看到的到底是结构化控件还是图片识别结果置信度会相应调整。2.3 执行层的跨平台差异与权限处理执行层是整个项目里最脏活累活的部分因为三套操作系统对模拟输入的态度完全不一样。Windows最直接通过SendInput注入鼠标键盘事件绝大多数窗口都会正常响应。macOS比较麻烦需要给程序授予辅助功能权限否则事件被系统拦截而且macOS对输入注入有额外的安全机制目标应用如果拒绝自动化事件会失败。Linux则是窗口管理器说了算X11下稳定Wayland下很多合成器禁止全局输入注入只能退而求其次用辅助技术的接口。我在设计之初就把权限问题放到了非常靠前的位置。程序第一次启动时会让用户对各个平台做一次授权自检明确告诉你哪些能力可用、哪些被系统拦截了。这一点很重要因为很多AI工具一上来就静默失败用户根本不知道是模型决策错了还是系统不允许操作。执行层另外引入了一个节奏控制器。真实GUI操作不是瞬间完成的菜单要展开、窗口要刷新、按钮要进入可点击状态如果AI按照代码执行的速度疯狂点击屏幕根本反应不过来。我实测发现必须强制在两次动作之间保留几百毫秒的动态间隔而且在点击之后、下一次观测之前要等到界面稳定下来一般用窗口内容变化检测来做比对前后两帧截图变化小于阈值才认为界面稳定了。这一步做得不好再聪明的模型也操作不了一个一直在闪的界面。2.4 安全边界能操作不代表可以乱操作让AI接管鼠标键盘等于把一台机器的控制权交给了模型。这个风险不能指望模型自觉必须在工程层面对冲。我在系统里做了四条防线操作确认模式默认开启AI每次准备执行高风险动作如删除、覆盖、提交表单前必须弹窗征求人类确认。也可以改成全自动模式但需要显式关闭保护。只读沙箱模式只允许AI观测和截图不允许注入任何输入事件适合让AI先看再让人类决定要不要让它动。目标窗口锁定可以指定只允许操控某个窗口或进程。AI不会跑到窗口外面乱点避免出现改着代码突然去点开了浏览器这种失控情况。完整操作日志每个注入的动作、每帧观测结果、每轮模型决策都记录在案。出问题时能完整回放而不是靠猜。我始终觉得AI编码代理这类工具能力边界可以激进但权限边界必须保守。特别是GUI操控一旦出事就是直接影响用户机器上的真实环境。宁可多做几次确认也不能让用户有一次被工具坑了的糟糕体验。3. MCP接入让代理长出外挂工具3.1 MCP到底是什么为什么编码代理必须支持它MCP全称Model Context Protocol是Anthropic提出的一种开放协议后来被整个AI工具生态接纳了。如果你看过一些比喻最贴切的就是AI界的USB-C接口模型不需要为每一个数据库、每一个浏览器、每一个业务系统单独定制接入方式只要遵循同一个协议就能连接各类外部工具或数据源。这就像你的手机不需要为每个设备造一个专用充电口一个USB-C口就能接各种外设。对编码代理来说MCP的意义比普通人理解得更大。因为编码代理的核心工作不只是写代码而是要理解代码背后涉及的整个系统。真实的开发任务里你需要查数据库、调API、看日志、搜文档、发HTTP请求、操作版本库。如果没有MCP这类标准化接入能力你就得为每个数据源去写定制插件或者让用户在配置文件里手写一大堆本地脚本。有了MCP工具生态是共享的今天有人写了一个好的数据库MCP服务器整个社区的agent都能直接用。我在设计这个项目时把MCP支持列为核心能力之一就是这个原因AI编码代理的竞争力很大程度上等于它能接入的工具生态的丰富程度。3.2 内置MCP客户端的设计实现这个项目内置了一个完整的MCP客户端而不是部分兼容或者只读支持。具体实现了两块传输层同时支持stdio本地进程间通信和SSEHTTP服务端事件流两种标准传输方式。stdio适合接本地的、随agent一起启动的MCP服务器SSE适合接远程部署的工具服务比如团队成员共享的一个数据库查询服务。协议层完整实现了工具发现tools/list、工具调用tools/call、资源读取、提示词模板等核心方法。启动时agent会自动向每个已注册的MCP服务器发送握手请求拿到能力清单并把它们合并进模型可见的工具列表里。交互流程上我做了先发现、后授权、再调用三段式。工具发现阶段只获取名称、描述和参数Schema不实质性执行任何操作授权阶段用户可以选择对某个MCP工具全自动放行、每次确认、或者完全禁用调用阶段才真正把参数发给MCP服务器执行并把结果结构化回传给模型。为什么要这么设计因为MCP服务器的能力千差万别有的是查数据库的有的是读文件系统的有的是操控浏览器的。如果agent启动后不分青红皂白地把所有工具都交给模型等于把一把万能钥匙给了它这既不安全也对用户不公平。所以我把能否调用某个MCP工具这个决定权始终保留在人类这一侧。3.3 实测让AI连着数据库和界面一起干活MCP支持不是纸面功能我拿一个接近真实工作的场景做了完整验证。场景是这样的一个基于RuoYi-Vue-Pro风格的后台管理项目我需要AI帮我完成一次按关键词查数据库记录、然后到界面上对应的表单去核对的联调任务。具体链路是我先在agent的配置里注册了一个数据库查询类的MCP服务器再打开后台管理系统的GUI界面。任务指令是从数据库查出所有状态为待审核的记录然后到界面上的列表页看看这些记录是否都正常显示。agent拿到指令后自己做了几件事通过MCP调用数据库查询接口拿到待审核记录的ID列表。切换到GUI操作模式读取当前浏览器窗口的无障碍树找到列表页表格的位置。点击搜索框、输入筛选条件、触发查询。重新观测界面比对结果和数据库查到的ID输出差异报告。整个过程约三分钟中途我只在执行搜索这个动作上点了一次确认。这个例子的价值在于它展示了MCP和GUI操控不是两个孤立的功能而是可以串成一条完整工作流的能力。这也正是我坚持要把两个功能放在同一个agent里的原因——分开的能力到处都是合起来才能解决真实问题。3.4 与现有生态的兼容状况因为MCP是标准协议这个客户端天然能和社区里已经成型的MCP服务器配合。我在测试中直接接过的有数据库类MCP、浏览器控制类MCP、设计稿转代码类MCP、以及几个头部项目里常见的文件读写和命令行工具MCP。基本上只要是遵循官方SDK写的MCP服务器把启动命令写进配置文件就能用。这一点省了我大量精力也让我更确信做标准协议是正确选择。接Codex生态里那种Figma授权类MCP的时候倒是踩过一个坑有些MCP服务器需要OAuth授权跳转但跳转会拉起默认浏览器结果agent本身又在操控GUI两个进程会打架。我的处理是给MCP调用加了一个阻塞模式在执行需要外部授权流程的MCP工具时暂停一切GUI注入动作等授权完成后自动恢复。这个细节看起来小但实际使用中极其重要否则就是各种莫名其妙的互相抢焦点。4. 单文件运行交付形态的工程取舍4.1 拷过去就能跑为什么是刚需单文件运行这个特性做之前觉得无所谓做之后发现它是这个工具被团队接受的关键因素。道理很简单大部分开发者最烦的就是装环境。我在公司内部测试的时候一开始给出的是一个zip包里面有几个动态库和一份Python辅助脚本。结果反馈最多的就是这个依赖怎么又报错了Python版本对不上给我个绿色版吧。后来我改成单一可执行文件下载、双击、跑起来配置也是自动生成的。反馈立刻变了大家开始关心功能本身而不是环境问题。单文件的价值不只是方便这么简单。在企业内网环境、隔离网络、客户现场这些场景能拷贝的单个可执行文件几乎是唯一可行的分发方式。你不可能要求客户机器上装好某语言的运行时、一套依赖和一个连你自己都说不清的配置。单文件交付意味着你把自己的完全体打包在了一起而不是把一半的运行环境问题丢给了用户。4.2 打包方案静态编译与依赖内嵌用Rust做单文件有个天然优势只要目标平台有对应工具链静态编译出来的二进制不依赖系统的动态链接库。但实际操作中没那么容易我重点处理了三类事情GUI库和系统API绑定我最终没有选择那种重量级GUI框架而是直接用系统原生API做窗口和控件渲染并把外部依赖降到了最低。这让最终产物不需要额外携带任何GUI运行时库。内置模型的嵌入轻量OCR模型和本地推理参数设置全部以资源形式编译进二进制里。代价是体积变大但换来的是运行时完全离线装完就能用。动态插件外置MCP服务器本身不内嵌它们仍然是独立的子进程或远程服务agent只在配置里记录启动命令。这样避免了把大量无用的工具都塞进一个文件里保持了单文件体积在一个可接受的范围。按照不同目标平台我分别只出一个二进制比如Windows平台就是agent.exemacOS是agentLinux也是agent。整包大小大概在90MB左右比很多IDE插件还小对于同时包含AI推理、GUI操控和MCP客户端的工具来说这个体积我认为是合理的。4.3 启动速度和常驻内存间的平衡单文件还有一个容易被忽略的工程细节启动速度。如果你每次打开工具都要加载一个巨大的二进制和解压内嵌资源用户体感会很差。我把资源类数据做了惰性加载obviously需要时再把OCR模型等大块资源从文件里映射到内存而不是程序一启动就全部加载。实测空载启动时间压在1秒以内OCR模型按需加载后再加半秒这个数据对GUI工具来说是可以接受的。常驻内存控制上也有取舍。模型和GUI控件树观测都比较吃内存我在不影响功能的前提下做了一些缓存策略比如相同区域的截图短时间内复用、OCR结果做短时缓存、无障碍树只在界面变化时重新拉取。对整个应用来说空闲时大概占170MB左右内存操作高峰期会上浮一些考虑到它身兼数职这个占用不算离谱。4.4 跨平台三件套的差异化处理单文件运行不代表代码一套通吃。三套系统在打包细节上差别很大Windows有代码签名要求macOS有公证和Gatekeeper拦截Linux有发行版碎片化。我的做法是给每个平台单独发一个编译产物并在项目文档里写清楚每个平台需要解除的限制和授权步骤。虽然看起来不统一但对用户来说实际上比一个到处受阻的通用包更友好。5. 实测记录、翻车复盘和剩下的事5.1 三个典型场景的真实跑分功能都做完之后我拿几个相对典型的场景做了标准化测试。数据不敢说多权威但绝对真实。测试机器是同一台笔记本模型走的是同一家云端APIGUI模式默认开启确认MCP注册了数据库、浏览器控制和一个命令行工具。场景操作内容结果耗时后端项目冒烟测试改完代码后自动启动服务访问本地接口并核对返回JSON全流程通过无人工参与约2分10秒后台管理界面数据核对按客户要求查数据库然后在网页列表页逐项核对记录通过中途确认了一次搜索动作约3分半桌面工具界面自动化启动一个本地桌面小工具重复执行导入-处理-导出的操作基本稳定但有一处分辨率适配不稳需要重试约4分钟第三个场景暴露的问题我先记着后面会展开说。总体而言在需要GUI操作的任务里这个工具能把过去必须人盯着的重复操作降级为偶尔确认一次的半自动任务实际情况符合我立项时的预期。5.2 翻车记录分辨率、OCR误判、权限弹窗这个项目开发过程中翻过的车值得记录的不少。写出来给后面做类似项目的人参考。第一辆是分辨率适配。我在自己的显示器上调得稳稳当当换了台不同分辨率的机器一跑坐标全部漂移。原因很直接我早期直接把无障碍树里的坐标当作绝对坐标传给了鼠标注入忽略了显示器缩放比例和DPI变化。修复方式是统一做一个逻辑坐标到物理坐标的转换层所有动作都经过这个转换层下发而不是在使用处临时换算。第二辆是OCR误判导致点了错误按钮。我在一个界面上的**保存并提交和保存为草稿**两个按钮靠得很近OCR把小号字体识别错了AI直接点了提交。虽然单测场景是测试环境但这件事给我提了个醒OCR识别结果必须带置信度低于阈值时要明说无法确定而不是猜一个。我后来加了一条规则当OCR置信度低于设定值时决策层必须要求人工指定或放弃操作。第三辆是权限弹窗被AI吃掉。macOS上第一次跑辅助功能授权时系统弹出授权对话框结果AI以为那是任务弹窗直接点掉了。这个问题非常黑色幽默但也很现实当一个工具能操控GUI时它连系统权限确认框都能当操作对象。修复措施是在进入授权流程检测状态时暂停所有GUI动作任何系统级弹窗优先交给人工处理。5.3 还想做的事插件化、模型无关、更细的GUI理解当前版本还谈不上完美。下一步我优先做三件事。插件化是第一个方向。现在GUI动作集是内置的用户不能扩展。我想把动作体系改成插件化接口让有需要的人可以自己写自定义动作比如调用特定软件的API、执行某个IDE的快捷键组合。这让agent的能力可以跟着团队的实际需求长出来而不是我预设什么就是什么。模型无关是我一直在坚持的原则。目前决策层可以对接多个常见模型提供方本地和云端的都在配置里支持了但不同模型的工具调用格式差异比较大我还想再抽象一层让切换模型时的适配成本进一步降低。这样用户想省成本用轻量模型跑简单任务想冲效果换强模型跑复杂任务都不用改任何工作流。更细的GUI理解是技术上的长远目标。现在的观测层能识别控件、能OCR但对界面布局语义的理解还比较浅。比如一个卡片信息区域包含了多个字段AI现在能逐个读但未必能理解这些字段是一个整体。我打算在观测层引入布局分析把界面按视觉区块做聚类让决策层看到的不只是零散控件而是一张有结构的界面地图。这一步如果能做成GUI操控的准确率和任务复杂度上限会有明显提升。这个项目从立项到现在我最直观的感受是AI编码代理的下一个竞争点不在谁能写更多代码而在谁能把代码之外的真实操作链路也接管过去。终端里的代码和屏幕上的界面是一个完整工程工作流的两端只盯着一端做永远差一口气。最后说点实在的。我把这个工具免费开出来就是想让更多人能用上AI既能看代码、又能动手开界面的完整形态。如果你也在做类似的东西或者在你自己的项目里接MCP、做GUI自动化欢迎直接用我这套框架当底座省掉那些我已经踩过的坑。单文件、GUI操控、MCP这三件事能拼在一起跑通本身就是一次很值得的尝试。