1. 项目概述与核心价值最近在折腾AI驱动的自动化任务特别是让AI模型直接操作浏览器完成一些重复性工作OpenAI官方开源的openai-cua-sample-app项目就成了一个绝佳的参考。这个项目本质上是一个演示应用展示了如何通过OpenAI的Responses API让GPT-5.4这样的模型以“计算机使用代理”的身份在浏览器环境中执行任务。它不是一个大而全的框架而是一个精心设计的“样板间”清晰地揭示了如何将强大的语言模型与真实的计算机操作环境在这里主要是浏览器安全、可控地连接起来。对于开发者而言这个项目的价值在于它提供了一个端到端的、可运行的参考实现。它拆解了构建一个“计算机使用代理”系统所需的核心组件一个管理浏览器会话和任务执行的后端运行器一个供操作员监控和发起任务的前端控制台以及一套定义任务、验证结果的标准化契约。无论你是想快速验证一个自动化想法还是计划构建一个更复杂的AI助手系统这个项目都能帮你跳过从零设计架构的迷茫期直接切入核心的实现逻辑和最佳实践。它特别适合那些希望探索AI在RPA、自动化测试、数据抓取或交互式教学等场景下应用的工程师和研究者。2. 项目架构深度解析2.1 核心组件与职责划分这个TypeScript项目采用了典型的Monorepo结构使用pnpm作为包管理器清晰地分离了关注点。理解每个包的职责是定制和扩展的基础。apps/runner后端运行器这是整个系统的心脏基于Fastify构建。它的核心职责是管理“可变工作空间”和“浏览器会话”。每一个自动化任务称为一个“Run”都会在一个独立、隔离的工作空间内执行这避免了任务间的相互污染。运行器通过Server-Sent Events向控制台实时推送任务状态、事件和截图并负责生成任务执行过程的“回放包”这对于事后分析和调试至关重要。它直接集成了OpenAI的Responses API是模型与浏览器环境交互的桥梁。apps/demo-web前端控制台这是一个Next.js应用作为操作员的控制面板。它的设计哲学很明确即使在运行器离线或某个任务执行失败时控制台界面也必须保持清晰可理解。这意味着它不能仅仅是一个简单的远程调用客户端而需要具备足够的状态管理和错误展示能力。你可以在这里选择预定义的“场景”启动任务并实时查看浏览器截图、模型产生的操作事件如点击、输入以及最终的任务结果验证报告。packages/*共享功能包这是项目保持灵活性和可扩展性的关键。packages/scenario-kit定义了“场景清单”的格式和默认提示词任何新任务都需要遵循这个契约来定义。packages/browser-runtime封装了Playwright浏览器实例的创建、生命周期管理和基本操作为上层的运行器提供稳定的浏览器抽象层。packages/runner-core则包含了最核心的“响应循环”逻辑、场景执行器以及结果验证器。packages/replay-schema定义了任务请求、响应、回放数据和错误信息的标准化数据结构确保了前后端以及不同组件间数据交换的一致性。这种架构的好处在于如果你想增加一个新的自动化任务类型例如操作一个桌面GUI应用而非浏览器你主要需要修改或替换的是packages/browser-runtime和packages/runner-core中的执行逻辑而前后端的通信协议、任务管理界面和场景定义方式可以很大程度上复用。2.2 两种执行模式的本质区别项目演示了两种让模型控制浏览器的模式理解它们的区别对于选择正确的应用场景至关重要。native原生计算机模式这是最直接模拟人类操作的模式。在此模式下Responses API暴露出的“计算机工具”允许模型直接请求诸如click点击、type输入、drag拖拽、wait等待和screenshot截图等底层原子操作。运行器接收到这些请求后通过Playwright将其翻译成对真实浏览器实例的操作。这种模式的优点是操作粒度细非常接近人类在图形界面上的交互逻辑易于理解和调试。模型需要“思考”每一步具体的动作比如“将鼠标移动到坐标(X, Y)然后点击”。code代码模式在此模式下系统向模型暴露的是一个持久的Playwright JavaScript运行时环境REPL。模型不再请求具体的点击或输入动作而是直接生成并执行JavaScript代码片段通过exec_js工具。例如模型可能会生成一段代码await page.locator(‘button#submit’).click();。这种模式的抽象层次更高模型可以一次性执行更复杂的逻辑组合效率可能更高尤其适合那些可以用清晰脚本描述的任务。它更像是让模型扮演了一个自动化脚本编写者的角色。注意模式选择的核心考量native模式更适合探索性、交互路径不确定的任务因为模型可以边“看”截图边决策下一步动作。code模式则更适合流程固定、逻辑清晰的任务可以生成更高效、可复用的脚本。两者使用相同的场景定义和回放管道这意味着你可以在不改变任务定义的情况下切换不同的执行策略来观察模型的表现差异这对于评估模型能力非常有价值。3. 从零开始的本地环境搭建与运行3.1 环境准备与依赖安装首先确保你的开发环境满足基础要求。Node.js版本必须严格是22.20.0这是项目package.json中engines字段的指定版本使用其他版本可能导致依赖解析或原生模块构建失败。pnpm版本要求10.26.0或兼容版本它是Monorepo管理的效率关键。# 1. 使用nvm或类似工具安装并切换Node.js版本 nvm install 22.20.0 nvm use 22.20.0 # 2. 全局安装指定版本的pnpm如果尚未安装 npm install -g pnpm10.26.0 # 3. 克隆项目代码 git clone https://github.com/openai/openai-cua-sample-app.git cd openai-cua-sample-app # 4. 启用Corepack确保使用项目定义的包管理器版本 corepack enable # 5. 安装项目所有依赖 pnpm install在执行pnpm install时你可能会看到关于sharp或esbuild等可选依赖的Ignored build scripts警告。对于本地开发这些警告通常可以安全忽略项目的基本构建和启动不会受到影响。这些通常是某些平台特定的原生模块如果后续功能需要如图片处理再按提示单独处理即可。3.2 关键配置与首次启动安装完依赖后需要进行关键的环境变量配置。# 1. 复制环境变量示例文件 cp .env.example .env # 2. 编辑.env文件填入你的OpenAI API密钥 # 使用你喜欢的文本编辑器如vim或code vim .env在.env文件中你至少需要设置OPENAI_API_KEY。这是运行器与OpenAI API通信的凭证。其他变量如HOST、PORT、CUA_DEFAULT_MODEL等可以暂时保持默认。# .env 最小配置示例 OPENAI_API_KEYsk-你的真实API密钥接下来需要安装Playwright所需的浏览器。项目脚本已经封装好了命令# 安装Chromium浏览器 pnpm playwright:install如果你在Linux系统上开发为了确保所有依赖齐全最好运行带系统依赖安装的命令pnpm playwright:install:with-deps这个命令会尝试通过系统包管理器如apt、yum安装Playwright运行所需的库如字体、音频库等。如果后续启动时仍报告缺少库重新运行此命令并按照其输出的提示安装相应的系统包即可。完成以上步骤后就可以一键启动整个应用了pnpm dev这个命令会同时启动后端运行器默认在http://127.0.0.1:4001和前端控制台默认在http://127.0.0.1:3000。启动成功后在浏览器中打开http://127.0.0.1:3000。3.3 执行第一个自动化任务在控制台界面你会看到几个预置的官方场景。以kanban-reprioritize-sprint看板重排为例这是一个很好的入门场景。选择场景在下拉菜单中选择kanban。保持默认确保Headless无头模式被选中。这意味着浏览器会在后台运行不显示图形界面适合初次测试。启动运行点击“Start Run”按钮。此时运行器会执行以下动作在labs/kanban目录下复制一份实验室模板到独立的工作空间。启动一个Playwright Chromium实例导航到该工作空间内的本地HTML文件一个简单的看板应用。将操作员提示词如“将‘设计评审’卡片移动到‘进行中’列的最上方”连同初始浏览器截图一起通过Responses API发送给GPT-5.4模型。模型开始以native模式响应返回一系列计算机操作指令。运行器执行这些指令并不断将新的截图和状态反馈给模型直到模型认为任务完成或达到最大交互轮次。最后运行器会根据场景定义中的验证逻辑检查看板的状态是否符合预期并将成功/失败的结果、完整的操作事件日志和回放包返回给控制台。在控制台你可以实时看到截图更新、模型发出的操作事件流。任务完成后你可以查看详细的回放一步步复盘AI是如何操作浏览器的。4. 官方场景详解与自定义任务创建4.1 深入理解预置场景项目提供了三个官方场景每个都旨在教授一组特定的验证技能和交互模式。kanban-reprioritize-sprint看板重排核心教学点状态验证。这个场景的验证逻辑不是检查UI上是否出现了某个文字而是验证整个应用的状态数据是否达到了目标。实验室包含一个简单的JavaScript内存数据模型来表示看板状态。任务完成后验证器会比对工作空间内生成的状态文件如result.json与预期状态是否一致。这教会了系统如何验证那些不直接体现在DOM上的业务逻辑状态。实操细节场景定义文件在packages/scenario-kit中会指定启动的本地URL、给模型的提示词、最大交互轮次以及关键的verifier验证器模块路径。验证器是一个导出了verify函数的TypeScript模块它接收工作空间路径作为参数读取运行时产生的状态文件并进行断言。paint-draw-poster绘图核心教学点光标坐标控制与画布状态验证。这个场景要求模型使用鼠标在HTML5 Canvas上绘制图形。验证器需要能够解析Canvas的像素数据或保存的图像文件来确认绘制内容是否符合要求例如是否画了一个红色的圆形。这演示了如何对非结构化、像素级的输出进行自动化验证。实操细节实现此类验证通常需要将Canvas图像数据导出为Base64或保存为PNG然后使用图像处理库如sharp或jimp进行像素比对或特征识别。项目中的验证器可能会计算图像哈希或检查特定坐标的颜色值。booking-complete-reservation预订核心教学点多步骤表单填写与数据提取验证。这个场景模拟了一个多页的表单填写流程。验证不仅需要检查最终的成功页面还可能涉及验证在流程中收集或生成的数据例如确认号码、日期是否正确。这展示了如何处理需要跨多个页面、有状态保持的复杂任务。实操细节验证器可能需要从最终页面的DOM中提取文本或者检查浏览器本地存储、甚至拦截网络请求来获取提交的数据然后与预期值进行比对。4.2 创建自定义场景的完整流程基于现有场景模板创建你自己的自动化任务是这个项目最大的实用价值所在。以下是步骤分解第一步创建实验室模板在项目的labs/目录下复制一个现有场景如kanban的文件夹重命名为你的场景名例如my-task。cp -r labs/kanban labs/my-task清理labs/my-task目录只保留最基本的静态文件一个index.html以及任务所需的所有前端资源JS, CSS, 图片。这个HTML文件就是你将要自动化操作的“靶子”应用。确保它是一个完整的、可独立运行在浏览器中的前端应用。第二步定义场景清单在packages/scenario-kit/src/scenarios/目录下创建一个新的TypeScript文件例如my-task.ts。// packages/scenario-kit/src/scenarios/my-task.ts import { defineScenario } from ‘../define-scenario’; export const myTaskScenario defineScenario({ // 场景的唯一标识符用于在控制台选择 slug: ‘my-task’, // 显示名称 label: ‘My Custom Task’, // 实验室模板目录名对应 labs/my-task lab: ‘my-task’, // 启动的入口URL通常是工作空间内的index.html url: ‘./index.html’, // 执行模式可选 ‘native’ 或 ‘code’ mode: ‘native’, // 最大交互轮次防止无限循环 maxTurns: 20, // 给AI模型的系统提示词清晰描述任务目标和规则 systemPrompt: 你是一个助手负责操作一个测试网页。你的目标是..., // 给操作员填写的提示词模板其中{{goal}}会被控制台输入替换 userPromptTemplate: ‘请完成以下任务{{goal}}’, // 验证器模块的路径相对于 packages/scenario-kit verifier: ‘./src/verifiers/my-task-verifier.ts’, });然后需要将这个场景导出到主场景列表中。编辑packages/scenario-kit/src/scenarios/index.ts文件导入并添加你的场景。第三步实现验证器验证器是确保任务被正确执行的关键。在packages/scenario-kit/src/verifiers/目录下创建my-task-verifier.ts。// packages/scenario-kit/src/verifiers/my-task-verifier.ts import type { Verifier } from ‘openai-cua-sample-app/replay-schema’; import { readFile } from ‘fs/promises’; import { join } from ‘path’; export const verify: Verifier async (workspacePath: string) { // 1. 读取你的应用在运行过程中生成的结果文件 // 例如你的应用可能在完成时在 workspacePath 下写入一个 result.json const resultPath join(workspacePath, ‘result.json’); let actualResult; try { const data await readFile(resultPath, ‘utf-8’); actualResult JSON.parse(data); } catch (error) { return { success: false, message: 未能读取结果文件: ${error.message}, }; } // 2. 定义你期望的结果 const expectedResult { status: ‘completed’, value: 42 }; // 3. 进行比较断言 if (actualResult.status expectedResult.status actualResult.value expectedResult.value) { return { success: true, message: ‘任务成功完成结果符合预期。’ }; } else { return { success: false, message: 验证失败。期望: ${JSON.stringify(expectedResult)} 实际: ${JSON.stringify(actualResult)}, }; } };验证器的逻辑完全由你定义可以检查文件内容、DOM状态、网络请求记录甚至调用外部API。第四步构建与测试在项目根目录下运行构建命令确保类型检查和编译通过pnpm build然后重启开发服务器pnpm dev现在打开前端控制台你应该能在场景下拉列表中看到My Custom Task。选择它输入你的任务目标启动运行观察AI模型是否能操作你的自定义页面并成功通过验证器的检查。5. 开发、调试与生产化考量5.1 独立运行与调试技巧在开发过程中同时运行前后端可能会使日志混杂。为了更好的调试体验可以分开启动服务# 终端1启动后端运行器 pnpm dev:runner # 运行器将在 http://127.0.0.1:4001 启动 # 终端2启动前端控制台并指定后端地址 RUNNER_BASE_URLhttp://127.0.0.1:4001 pnpm dev:web # 控制台将在 http://127.0.0.1:3000 启动这样你可以分别在两个终端查看各自的日志。运行器的日志会详细打印出与OpenAI API的通信、浏览器操作指令的执行情况以及验证过程对于排查问题至关重要。项目提供了一系列质量保证脚本pnpm lint: 运行ESLint检查代码风格。pnpm typecheck: 运行TypeScript编译器进行类型检查不输出文件。pnpm test: 运行单元测试。pnpm build: 执行完整的项目构建。pnpm check: 通常是一个组合命令依次执行lint、typecheck、test和build确保代码库处于健康状态。对于需要真实调用OpenAI API的集成测试“活体测试”项目设置了独立的命令并且要求提供API密钥以避免意外消耗额度OPENAI_API_KEYsk-your-key-here pnpm test:live5.2 配置项详解与环境管理环境变量是控制应用行为的主要方式。除了必须的OPENAI_API_KEY以下配置值得关注运行器配置 (apps/runner)CUA_DEFAULT_MODEL: 默认使用的AI模型例如gpt-5.4。你可以根据可用性和成本尝试其他支持Responses API的模型。CUA_RESPONSES_MODE: 控制Responses API的行为模式。auto默认由API决定最佳模式。fallback: 在特定条件下回退到其他模式。live: 强制使用实时响应模式。理解这些模式需要参考OpenAI API文档它们影响响应速度和计费。HOST/PORT: 绑定运行器的网络接口和端口。前端控制台配置 (apps/demo-web)RUNNER_BASE_URL: 前端连接的后端运行器地址。在分布式部署时尤为重要。NEXT_PUBLIC_CUA_DEFAULT_MAX_RESPONSE_TURNS: 前端控制台默认设置的最大交互轮次防止任务失控运行过久。环境文件管理最佳实践是为不同环境开发、测试、生产创建不同的.env文件如.env.development,.env.production并通过NODE_ENV等环境变量来加载对应的配置。前端Next.js应用会自动根据环境加载.env.local,.env.development,.env.production等文件。5.3 安全边界与生产部署注意事项官方README中明确强调了安全限制这绝非危言耸听而是构建此类系统的首要原则。核心安全警告绝对不要将此示例应用指向任何需要认证的真实生产环境如公司内网、邮箱、CRM系统。绝对不要用于操作涉及金融交易、医疗健康、个人隐私或任何高风险的网站和应用。当前示例没有实现OpenAI API可能要求的“计算机使用安全确认”功能。这意味着如果API在运行高风险操作前要求用户确认当前代码会因unsupported_safety_acknowledgement错误而失败。在生产系统中你必须实现一个机制来拦截这类请求并交由人类操作员审核批准。生产化部署考量工作空间隔离确保每个运行任务的工作空间在文件系统和进程层面都是完全隔离的使用Docker容器或虚拟机是更安全的选择。资源限制为每个浏览器会话设置内存、CPU使用上限和运行超时时间防止恶意或异常任务耗尽服务器资源。访问控制为前端控制台和后端API添加身份认证和授权层确保只有授权用户能发起任务。日志与审计详细记录所有AI发出的指令、执行结果、验证状态以及用户操作便于事后审计和问题追溯。回放数据存储回放包包含所有截图和事件可能很大需要规划好存储策略如对象存储和清理策略。错误处理与降级增强网络波动、API限流、浏览器崩溃等情况下的错误处理和自动重试、清理机制。6. 常见问题排查与实战经验在实际搭建和运行过程中你可能会遇到一些典型问题。以下是我在多次部署和实验中总结的排查清单和经验。6.1 安装与启动阶段问题问题一pnpm install失败提示Node版本不符或依赖冲突。排查首先用node -v和pnpm -v确认版本完全符合要求。如果版本正确尝试删除node_modules目录和pnpm-lock.yaml文件然后重新运行pnpm install。有时网络问题会导致依赖下载不完整。经验在团队协作中强烈建议将.node-version或engines声明加入版本控制并使用nvm或fnm等工具统一团队环境。问题二Playwright浏览器安装失败尤其是Linux系统。排查运行pnpm playwright:install:with-deps并仔细阅读其输出。它会列出缺失的系统包。例如在Ubuntu上你可能需要运行sudo apt-get install libgbm1 libasound2等命令。安装完系统依赖后再次运行pnpm playwright:install。经验在Docker中构建时最好选择已经包含这些依赖的基础镜像如mcr.microsoft.com/playwright或者在Dockerfile中提前安装好所有playwright install-deps列出的包。问题三启动pnpm dev后前端控制台无法连接到运行器空白页或连接错误。排查分别检查两个服务是否成功启动。访问http://127.0.0.1:4001/health运行器健康检查端点和http://127.0.0.1:3000。查看两个终端的日志是否有错误。确认前端.env.local或环境变量中RUNNER_BASE_URL设置正确且没有跨域问题CORS。运行器已经配置了CORS但如果你改了端口或主机需要确认。经验开发时打开浏览器的开发者工具F12的“网络”标签页查看前端发起的请求是否失败以及失败的具体原因。6.2 任务执行阶段问题问题四任务启动后立即失败状态为“Failed”错误信息模糊。排查查看运行器日志这是最重要的信息源。日志会显示任务初始化、浏览器启动、API调用等每一步的详细信息。检查API密钥确认.env文件中的OPENAI_API_KEY有效且没有额度耗尽或被限制。检查模型可用性确认CUA_DEFAULT_MODEL如gpt-5.4在你的API账户中可用且有权访问。检查实验室模板确认你选择的场景对应的labs/目录存在且index.html可正常访问。经验将运行器日志级别调为DEBUG如果支持可以获得更详尽的信息。可以在启动运行器前设置环境变量LOG_LEVELdebug。问题五任务执行中AI模型行为异常比如不停重复点击同一个地方或无法理解页面。排查审查系统提示词在packages/scenario-kit中查看对应场景的systemPrompt。提示词的质量直接决定模型的表现。确保指令清晰、无歧义并限定了操作范围。检查截图质量模型依赖截图“看”页面。如果页面布局复杂、动态元素多可能干扰模型判断。考虑在实验室模板中简化UI或通过提示词引导模型关注特定区域。交互轮次限制模型可能陷入循环。适当降低maxTurns或在前端控制台手动停止任务。切换模式如果在native模式下模型表现不佳可以尝试在场景定义中将mode改为code看看模型通过编写脚本是否能更好完成任务。经验设计一个好的自动化任务一半是工程一半是“提示词工程”。你需要像教导一个新手一样在系统提示词中明确规则、约束和成功标准。提供清晰的示例Few-shot Learning在复杂任务中效果显著。问题六任务看似执行完成但验证失败。排查查看验证器日志在运行器日志中搜索verifier相关的输出看验证器具体比较了什么为什么失败。手动检查结果进入该次任务的工作空间目录通常位于临时路径日志中会打印查看应用生成的结果文件如result.json内容是什么与验证器期望的是否一致。检查验证器逻辑确认你的验证器代码逻辑正确文件路径、数据解析、比较逻辑没有错误。检查应用状态有时AI的操作可能触发了页面变化但应用内部状态并未正确更新。需要确保你的实验室应用有明确的“状态完成”信号如生成文件、更新特定DOM属性。经验验证器要具备一定的容错性。例如比较数字时考虑精度误差比较字符串时忽略首尾空格。同时验证失败时应提供尽可能详细的错误信息帮助定位是AI操作错误还是应用逻辑错误。6.3 性能与稳定性优化浏览器实例管理每个任务都启动一个全新的浏览器实例开销很大。对于高频任务可以考虑实现一个浏览器实例池但要注意状态隔离避免任务间相互影响。API调用优化Responses API的调用是主要成本和时间消耗点。合理设置maxTurns并在系统提示词中鼓励模型“思考”后再行动减少无效或冗余操作轮次。超时与重试为网络请求、浏览器操作设置合理的超时时间并对可重试的错误如网络抖动实现重试机制。监控与告警在生产环境中监控任务成功率、平均执行时间、API调用次数和费用、浏览器资源使用情况等指标并设置告警阈值。这个开源示例项目是一个强大的起点它清晰地展示了构建AI驱动自动化系统的核心模式。真正的挑战和乐趣在于如何基于这个样板设计出能够稳健、安全地解决实际业务问题的场景和验证逻辑。从简单的页面操作到复杂的工作流编排其中的可能性正等待你去探索和实现。