基于Browserbase与LLM构建网页操作智能体:从原理到工程实践
在实际项目中将 AI 智能体Agent与网页浏览器自动化能力结合正成为实现复杂业务流程自动化、数据采集和智能交互的新范式。传统的爬虫或脚本在处理需要登录、点击、表单填写、JavaScript 渲染或应对反爬机制的现代网页时往往力不从心。而 AI 智能体特别是基于大语言模型LLM驱动的 Agent能够理解自然语言指令做出决策并执行一系列操作为解决这类问题提供了新思路。本文将以一个典型的技术集成场景为例探讨如何利用 Browserbase 这类浏览器自动化云服务作为智能体的“眼睛和手”构建一个能够自主操作网页的 AI 智能体。我们将从核心概念讲起逐步完成环境搭建、代码实现、运行验证并深入分析其中的关键配置、常见问题及生产级最佳实践。1. 理解智能体与浏览器自动化的结合点1.1 什么是网页操作智能体Web Agent一个网页操作智能体本质上是一个能够理解用户目标例如“去招聘网站搜索北京的 Java 工程师职位并整理前三页的结果”并自主规划、执行一系列浏览器操作如导航、点击、输入、滚动、提取数据的软件程序。其核心能力在于“决策”和“执行”的循环智能体观察当前网页状态DOM、URL、截图决定下一步最佳操作通过浏览器控制器执行该操作然后观察新状态直至任务完成或无法继续。这与传统脚本的关键区别在于适应性。脚本的每一步都是预先写死的而智能体可以根据网页的实际反馈动态调整策略。例如如果登录按钮的 CSS 选择器变了一个健壮的智能体可能会尝试通过文本内容“登录”或“Sign in”来定位元素。1.2 Browserbase 的角色提供可靠的执行环境直接在本地运行无头浏览器如 Puppeteer、Playwright进行自动化会面临环境不一致、资源占用、被网站屏蔽特别是云服务器 IP等问题。Browserbase 这类服务提供了托管、可扩展的浏览器环境主要价值在于环境一致性提供干净、标准的浏览器环境减少“在我机器上能跑”的问题。反检测规避通过一些技术手段使得自动化浏览器更难以被网站的反爬虫系统识别。可扩展性与并发轻松启动多个浏览器会话并行处理任务。会话持久化可以保存和恢复浏览器会话包括 Cookies、LocalStorage这对于需要登录的任务至关重要。易于集成提供简单的 API 或 SDK 来启动、控制和关闭远程浏览器。在智能体架构中Browserbase 充当了执行器。智能体的大脑LLM发出“点击这个按钮”的指令这个指令通过 Browserbase 的 SDK 转换成对远程浏览器的实际操控。1.3 核心架构与工作流一个典型的集成架构包含以下组件控制程序你的代码包含智能体逻辑协调 LLM 和浏览器。大语言模型LLM提供决策能力。可以是 OpenAI GPT、Anthropic Claude、本地部署的 Llama 等模型的 API。浏览器自动化 SDK如 Puppeteer、Playwright 的库用于编程控制浏览器。Browserbase 服务提供浏览器实例。你的 SDK 会连接到一个 Browserbase 提供的远程浏览器端点。目标网站智能体需要交互的网页。工作流如下用户目标 - 控制程序 - LLM 分析目标并生成第一步指令 - 通过 SDK 在 Browserbase 浏览器上执行 - 获取新页面状态HTML/截图- LLM 分析新状态并生成下一步指令 - ... - 循环直至任务完成 - 控制程序输出结果。2. 环境准备与项目初始化2.1 前置条件与工具选择在开始编码前需要准备好以下环境Node.js 环境本文示例使用 Node.js 和 Playwright这是目前功能强大且流行的浏览器自动化方案。确保安装 Node.js (版本 16 或以上) 和 npm/yarn。Browserbase 账户访问 Browserbase 官网注册并获取 API 密钥。通常你会有一个BROWSERBASE_API_KEY用于认证。LLM API 密钥例如如果你使用 OpenAI则需要OPENAI_API_KEY。确保你的账户有足够的额度。代码编辑器如 VS Code。2.2 创建项目并安装依赖首先创建一个新的项目目录并初始化。mkdir web-agent-demo cd web-agent-demo npm init -y安装核心依赖。我们将使用playwright进行浏览器控制使用playwright-core以连接 Browserbase使用openai库调用 GPT 模型并使用dotenv管理环境变量。npm install playwright playwright-core openai dotenv同时为了能连接 Browserbase需要安装他们的适配器npm install browserbasehq/playwright2.3 配置环境变量在项目根目录创建.env文件用于安全存储密钥。务必确保该文件被添加到.gitignore中避免密钥泄露。# .env BROWSERBASE_API_KEYyour_browserbase_api_key_here OPENAI_API_KEYyour_openai_api_key_here # 可选设置代理如果需要且合规 # HTTPS_PROXYhttp://your-proxy-server:port接下来创建项目的主要结构web-agent-demo/ ├── .env ├── .gitignore ├── package.json ├── package-lock.json ├── src/ │ ├── agent.js # 智能体核心逻辑 │ ├── browser.js # 浏览器控制封装 │ └── utils.js # 工具函数 └── examples/ └── simple-navigation.js # 示例运行脚本3. 构建浏览器控制层智能体需要与浏览器交互。我们先封装一个稳定的浏览器控制模块它负责启动 Browserbase 会话、执行基础操作如导航、截图、获取 DOM以及关闭会话。3.1 创建浏览器控制器在src/browser.js中我们创建一个BrowserController类。// src/browser.js require(dotenv).config(); const { chromium } require(playwright-core); const { Browserbase } require(browserbasehq/playwright); class BrowserController { constructor() { this.browser null; this.context null; this.page null; this.browserbase new Browserbase({ apiKey: process.env.BROWSERBASE_API_KEY, }); } /** * 启动一个新的浏览器会话 * param {Object} options - 启动选项 * param {boolean} options.headless - 是否无头模式 * param {string} options.proxy - 代理服务器地址 */ async launch(options { headless: true }) { console.log(正在通过 Browserbase 启动浏览器...); try { // 通过 Browserbase 启动 Playwright this.browser await chromium.connectOverCDP({ endpointUrl: await this.browserbase.getCDPEndpoint(options), }); // 创建新的浏览器上下文类似于隐身会话 this.context this.browser.contexts()[0] || await this.browser.newContext(); // 创建新页面 this.page this.context.pages()[0] || await this.context.newPage(); // 设置视口和 User-Agent可选用于反检测 await this.page.setViewportSize({ width: 1280, height: 720 }); // await this.page.setExtraHTTPHeaders({ User-Agent: Custom-UA }); console.log(浏览器启动成功。); } catch (error) { console.error(启动浏览器失败:, error); throw error; } } /** * 导航到指定 URL * param {string} url */ async goto(url) { if (!this.page) throw new Error(页面未初始化请先调用 launch()); console.log(导航至: ${url}); await this.page.goto(url, { waitUntil: networkidle }); // 等待网络空闲 } /** * 获取当前页面的 HTML 内容 * returns {Promisestring} */ async getPageContent() { if (!this.page) throw new Error(页面未初始化); // 可以只获取 body 内容或者清理掉脚本、样式等 const content await this.page.content(); // 简单清理移除脚本和样式标签以减少 token 消耗 const cleaned content.replace(/script\b[^]*(?:(?!\/script)[^]*)*\/script/gi, ) .replace(/style\b[^]*(?:(?!\/style)[^]*)*\/style/gi, ) .substring(0, 15000); // 限制长度避免 LLM 上下文过长 return cleaned; } /** * 获取当前页面的截图Base64 * returns {Promisestring} */ async getScreenshot() { if (!this.page) throw new Error(页面未初始化); const buffer await this.page.screenshot({ type: png, fullPage: false }); return buffer.toString(base64); } /** * 执行一个 Playwright 动作如点击、输入 * param {string} action - 动作类型如 click, fill, press * param {string} selector - CSS 选择器 * param {string|Object} value - 可选输入的值或按键 */ async performAction(action, selector, value null) { if (!this.page) throw new Error(页面未初始化); console.log(执行动作: ${action} on ${selector}${value ? with value: ${value} : }); try { switch (action) { case click: await this.page.click(selector, { timeout: 10000 }); break; case fill: await this.page.fill(selector, value, { timeout: 10000 }); break; case press: await this.page.press(selector, value, { timeout: 10000 }); break; case waitForSelector: await this.page.waitForSelector(selector, { timeout: 10000 }); break; default: throw new Error(不支持的 action 类型: ${action}); } // 动作执行后等待一小段时间让页面稳定 await this.page.waitForTimeout(1000); } catch (error) { console.error(执行动作失败 [${action} on ${selector}]:, error.message); throw error; // 将错误抛给上层处理 } } /** * 关闭浏览器会话 */ async close() { if (this.browser) { await this.browser.close(); console.log(浏览器会话已关闭。); } } } module.exports BrowserController;这个控制器提供了基础的操作方法。关键点在于launch方法它使用browserbasehq/playwright库来获取一个连接 Browserbase 远程浏览器的端点然后通过chromium.connectOverCDP建立连接。4. 实现智能体决策逻辑智能体的“大脑”需要根据目标、当前页面状态和历史操作来决定下一步做什么。我们将创建一个WebAgent类它利用 LLM这里用 OpenAI GPT-4来生成决策。4.1 设计智能体的提示词Prompt提示词是驱动智能体的核心。一个好的提示词需要清晰地定义角色、任务、可用动作和输出格式。// src/agent.js 中的一部分 - 系统提示词 const SYSTEM_PROMPT 你是一个专业的网页操作智能体。你的目标是根据用户的指令通过操作浏览器来完成网页任务。 你可以执行以下类型的动作 1. CLICK [selector]: 点击一个元素。selector 是 CSS 选择器。 2. FILL [selector] [text]: 向输入框填充文本。 3. PRESS [selector] [key]: 在元素上按下某个键如 Enter。 4. NAVIGATE [url]: 导航到一个新的 URL。 5. EXTRACT [description]: 从当前页面提取信息。描述你想提取什么。 6. DONE [result]: 任务完成并附上最终结果或总结。 7. FAIL [reason]: 任务无法继续说明原因。 当前页面状态会以简化后的 HTML 形式提供给你。你需要分析 HTML找到与任务相关的元素并选择最合适的动作。 你的输出必须是严格的 JSON 格式 { thought: 你的思考过程分析当前情况和下一步计划, action: 动作类型如 CLICK, FILL 等, selector: CSS 选择器如果是 CLICK, FILL, PRESS, value: 可选填充的文本或按键如果是 FILL, PRESS, url: 可选导航的 URL如果是 NAVIGATE, description: 可选提取信息的描述如果是 EXTRACT, result: 可选最终结果如果是 DONE, reason: 可选失败原因如果是 FAIL } 请确保 selector 尽可能精确且稳定。优先使用 id、name、具有唯一性的 class 或>// src/agent.js require(dotenv).config(); const OpenAI require(openai); class WebAgent { constructor() { this.openai new OpenAI({ apiKey: process.env.OPENAI_API_KEY, }); this.model gpt-4-turbo-preview; // 可根据需要调整模型 this.maxSteps 20; // 防止无限循环 this.stepCount 0; this.history []; // 记录操作历史 } /** * 根据用户目标、页面内容和历史决定下一步动作 * param {string} objective - 用户目标 * param {string} pageContent - 当前页面 HTML 内容 * param {Array} history - 历史动作和结果 * returns {PromiseObject} - 解析后的动作对象 */ async decideNextAction(objective, pageContent, history []) { if (this.stepCount this.maxSteps) { return { thought: 已达到最大步数限制任务可能过于复杂或陷入循环。, action: FAIL, reason: Exceeded maximum steps (${this.maxSteps}). }; } const userPrompt 用户目标${objective} 当前页面内容简化HTML --- ${pageContent} --- 最近操作历史 ${history.slice(-3).map(h - ${h}).join(\n) || 无} 请根据以上信息决定下一步动作。输出必须是上述定义的 JSON 格式。 ; try { const completion await this.openai.chat.completions.create({ model: this.model, messages: [ { role: system, content: SYSTEM_PROMPT }, { role: user, content: userPrompt } ], temperature: 0.1, // 低温度保证输出稳定、可解析 response_format: { type: json_object } // 强制 JSON 输出 }); const responseText completion.choices[0].message.content; let actionObj; try { actionObj JSON.parse(responseText); } catch (parseError) { console.error(LLM 返回无法解析的 JSON:, responseText); // 兜底尝试提取可能的 JSON 部分或返回失败动作 const jsonMatch responseText.match(/\{[\s\S]*\}/); if (jsonMatch) { try { actionObj JSON.parse(jsonMatch[0]); } catch { actionObj { action: FAIL, reason: LLM 返回了无效的 JSON 响应。 }; } } else { actionObj { action: FAIL, reason: LLM 返回了非 JSON 响应。 }; } } this.stepCount; this.history.push(Step ${this.stepCount}: ${actionObj.action} - ${actionObj.thought}); return actionObj; } catch (error) { console.error(调用 LLM 决策失败:, error); return { action: FAIL, reason: LLM API 调用失败: ${error.message} }; } } reset() { this.stepCount 0; this.history []; } } module.exports WebAgent;这个类封装了与 OpenAI API 的交互并将决策过程格式化。temperature设为较低值以保证输出一致性response_format强制要求 JSON 输出以便程序解析。5. 组装与运行一个完整的导航搜索示例现在我们将浏览器控制器和智能体组合起来完成一个具体任务“打开百度首页搜索‘人工智能最新进展’并点击搜索按钮”。5.1 创建主运行脚本在examples/simple-navigation.js中编写主逻辑。// examples/simple-navigation.js require(dotenv).config(); const BrowserController require(../src/browser); const WebAgent require(../src/agent); async function runTask(objective) { const browserCtrl new BrowserController(); const agent new WebAgent(); try { // 1. 启动浏览器 await browserCtrl.launch({ headless: false }); // 非无头模式便于观察 // 2. 导航到初始页面例如百度 await browserCtrl.goto(https://www.baidu.com); let isTaskDone false; let finalResult null; // 3. 智能体决策与执行循环 while (!isTaskDone agent.stepCount agent.maxSteps) { // 获取当前页面状态 const pageContent await browserCtrl.getPageContent(); // 截图可选可用于更复杂的视觉分析 // const screenshot await browserCtrl.getScreenshot(); // 智能体决策 const decision await agent.decideNextAction(objective, pageContent, agent.history); console.log([Step ${agent.stepCount}] 决策:, JSON.stringify(decision, null, 2)); // 执行决策 switch (decision.action) { case NAVIGATE: if (decision.url) { await browserCtrl.goto(decision.url); } else { console.warn(NAVIGATE 动作缺少 URL); } break; case CLICK: if (decision.selector) { await browserCtrl.performAction(click, decision.selector); } else { console.warn(CLICK 动作缺少 selector); } break; case FILL: if (decision.selector decision.value ! undefined) { await browserCtrl.performAction(fill, decision.selector, decision.value); } else { console.warn(FILL 动作缺少 selector 或 value); } break; case PRESS: if (decision.selector decision.value) { await browserCtrl.performAction(press, decision.selector, decision.value); } else { console.warn(PRESS 动作缺少 selector 或 value); } break; case EXTRACT: console.log(智能体请求提取: ${decision.description}); // 这里可以实现一个信息提取函数例如通过 DOM 选择器或另一个 LLM 调用 // 本例中我们简单记录并让智能体继续 agent.history.push(Extracted info for: ${decision.description}); break; case DONE: console.log(任务完成); console.log(结果:, decision.result); isTaskDone true; finalResult decision.result; break; case FAIL: console.error(任务失败:, decision.reason); isTaskDone true; finalResult { error: decision.reason }; break; default: console.warn(未知动作: ${decision.action}); // 安全策略如果遇到未知动作等待一下然后继续或者失败 await browserCtrl.page.waitForTimeout(2000); } // 每次动作后稍作等待让页面加载 await browserCtrl.page.waitForTimeout(2000); } if (!isTaskDone) { console.warn(达到最大步数限制 (${agent.maxSteps})任务未完成。); } // 4. 任务结束可以保持浏览器打开供检查或直接关闭 console.log(任务执行完毕。按任意键关闭浏览器...); // 以下行用于等待用户输入在演示时有用 // await new Promise(resolve process.stdin.once(data, resolve)); } catch (error) { console.error(运行任务过程中发生错误:, error); } finally { // 确保浏览器被关闭 await browserCtrl.close(); } } // 执行任务 const userObjective 打开百度首页在搜索框里输入‘人工智能最新进展’然后点击‘百度一下’按钮进行搜索。; runTask(userObjective);5.2 运行与验证在终端中运行该脚本node examples/simple-navigation.js如果一切配置正确你将看到终端显示“正在通过 Browserbase 启动浏览器...”。一个浏览器窗口或标签页会打开并导航到百度首页。终端会打印智能体的决策步骤例如[Step 1] 决策: { thought: 用户目标是搜索。我需要先找到搜索输入框然后输入关键词最后点击搜索按钮。当前页面是百度首页搜索框的 id 可能是 kw按钮的 id 可能是 su。, action: FILL, selector: #kw, value: 人工智能最新进展 }浏览器会自动在搜索框中输入文字。接着智能体会决定点击搜索按钮。最终页面会跳转到搜索结果页智能体可能输出DONE动作任务完成。注意网站 UI 可能变化智能体基于 HTML 分析的 selector 可能失效。这是此类系统的主要挑战之一下文会讨论应对策略。6. 关键配置、参数与调优6.1 Browserbase 连接参数在browser.js的launch方法中我们通过this.browserbase.getCDPEndpoint(options)获取连接端点。options对象可以传递更多配置给 Browserbaseconst launchOptions { headless: false, // 是否无头模式。调试时设为 false生产环境设为 true。 proxy: process.env.HTTPS_PROXY, // 使用代理 sessionId: my-persistent-session, // 会话 ID用于恢复之前的浏览器状态如登录信息 projectId: my-project, // Browserbase 项目 ID用于计费和分组 timeout: 180000, // 连接超时时间毫秒 };6.2 Playwright 动作超时与等待策略在browser.js的performAction方法中我们为每个动作设置了{ timeout: 10000 }。这意味着如果 10 秒内元素未出现或不可操作动作会失败。在实际复杂的网页中可能需要调整增加超时对于加载缓慢的页面可以增加到 30000 毫秒。更智能的等待使用page.waitForSelector(selector, { state: visible })在动作前显式等待元素。重试机制在动作失败后可以加入重试逻辑。6.3 LLM 提示词与参数调优智能体的表现极大程度依赖于提示词和 LLM 参数。模型选择gpt-4-turbo-preview在理解和生成结构化 JSON 方面表现较好。gpt-3.5-turbo成本更低但复杂任务上可能不稳定。可根据任务复杂度选择。Temperature设为较低值如 0.1-0.3以保证输出稳定性和可解析性。如果希望智能体有一定探索性可以适当调高但会增加解析失败风险。上下文长度我们通过substring(0, 15000)限制了传给 LLM 的 HTML 长度。这是因为 GPT-4 有上下文窗口限制如 128k但实际使用中过长的 HTML 会消耗大量 token 并可能降低模型关注重点。需要根据模型窗口和任务复杂度平衡。系统提示词优化可以加入更多示例Few-shot Learning或更详细地描述如何分析页面、如何选择稳定的选择器。6.4 页面状态处理优化当前我们只传递了清理后的 HTML。对于更复杂的任务可以增强状态表示关键元素列表使用 Playwright 提取页面中所有链接、按钮、输入框的文本和选择器以结构化列表形式传给 LLM减少噪声。视觉信息将截图转换为 Base64 并传给支持视觉的模型如 GPT-4V让智能体“看到”页面布局。交互历史摘要不仅传递原始历史还可以总结当前处于流程的哪个阶段。7. 常见问题排查与解决方案在实际运行中你会遇到各种问题。下面是一个排查清单。问题现象可能原因检查与解决步骤无法连接 Browserbase1. API 密钥错误或未设置。2. 网络问题或代理配置错误。3. Browserbase 服务暂时不可用。1. 检查.env文件中的BROWSERBASE_API_KEY是否正确并在 Browserbase 控制台确认密钥有效。2. 运行curl -v https://api.browserbase.com/v1/health测试网络连通性。检查代理设置。3. 查看 Browserbase 状态页面或等待重试。浏览器启动后立即崩溃或无响应1. 资源不足内存/CPU。2. 启动参数冲突。3. Playwright 与 Browserbase 适配器版本不兼容。1. 在 Browserbase 控制台查看会话日志。2. 简化launch参数尝试仅使用{ headless: true }。3. 检查package.json确保playwright-core和browserbasehq/playwright版本兼容。可尝试安装特定版本。智能体无法找到元素CLICK/FILL 失败1. 页面未加载完成。2. 选择器Selector不正确或已过时。3. 元素在 iframe 内。4. 需要滚动才能看到元素。1. 在goto和动作间增加page.waitForLoadState(networkidle)或更长的waitForTimeout。2.最常发生。在浏览器开发者工具中手动验证选择器。让智能体输出更鲁棒的选择器如结合文本button:has-text(搜索)。3. 使用page.frameLocator()处理 iframe。4. 在执行动作前使用page.evaluate滚动到元素位置。LLM 返回的 JSON 无法解析1. LLM 未遵循指令输出了非 JSON 内容。2. JSON 格式有细微错误如尾随逗号。3. 上下文过长导致模型输出截断。1. 降低temperature值。2. 在提示词中更加强调“严格的 JSON 格式”。使用response_format: { type: json_object }OpenAI API 支持。3. 实现一个更健壮的 JSON 解析函数如使用JSON.parse的try-catch并尝试修复常见格式错误。4. 减少传入的页面内容长度。智能体陷入循环或做出无意义动作1. 页面状态未充分传达给 LLM。2. 任务目标描述不清晰。3. 最大步数设置过小任务本身复杂。1. 改进页面状态表示例如提取关键文本和元素属性而非原始 HTML。2. 在用户目标中加入更明确的成功条件例如“...并提取第一页前 5 条结果的标题和链接”。3. 增加maxSteps并在历史中记录更多上下文让 LLM 知道哪些步骤已经尝试过。4. 实现一个简单的循环检测逻辑如果连续几步状态无变化则触发FAIL。操作被网站屏蔽或触发验证码1. 自动化行为被检测。2. 请求频率过高。1. 在 Browserbase 启动选项中启用更高级的反检测功能如果服务提供。2. 在动作之间增加随机延迟 (page.waitForTimeout(2000 Math.random() * 3000))。3. 模拟人类行为如随机移动鼠标轨迹Playwright 支持。4. 对于必须登录的网站考虑使用 Browserbase 的持久会话功能预先手动登录一次后续自动化使用该sessionId。Token 消耗过高或 API 调用慢1. 每次决策都传递了过长的页面 HTML。2. LLM 模型选择不当。1.至关重要优化getPageContent函数只提取与任务相关的部分如主要区域.main-content或使用 LLM 先总结页面。2. 对于简单导航任务可先尝试gpt-3.5-turbo。3. 缓存页面状态如果页面内容未变化则无需重复调用 LLM。8. 生产环境最佳实践与扩展方向将此类智能体用于生产环境需要考虑更多因素。8.1 稳定性与容错重试机制对于网络错误、临时性元素定位失败应实现指数退避的重试逻辑。心跳与超时设置任务级别的总超时并定期检查浏览器会话是否存活。状态快照与恢复定期保存页面截图、HTML 和智能体历史。如果任务中断可以从最近的稳定状态恢复而不是从头开始。降级策略当 LLM 连续决策失败时可以切换到预定义的、确定性的脚本流程。8.2 性能与成本优化异步与并发Browserbase 支持并发会话。可以设计一个任务队列由多个智能体实例并行处理独立任务。LLM 调用优化小模型优先能用小模型如 GPT-3.5完成的任务不用大模型。上下文压缩使用更精炼的方式表示页面状态如只提取所有交互元素的[role, text, selector]三元组。缓存对相同的页面状态和决策请求进行缓存。Browserbase 会话复用对于一系列相关操作尽量复用同一个浏览器会话避免频繁启动关闭的开销。8.3 可观测性与监控详细日志记录每个决策的输入页面摘要、输出动作、执行结果以及耗时。这对于调试和优化至关重要。结构化日志使用 JSON 格式记录日志便于接入 ELKElasticsearch, Logstash, Kibana或类似系统。关键指标监控任务成功率、平均完成步数、LLM 调用耗时、Token 消耗、Browserbase 会话失败率等。告警对任务失败率上升、平均耗时异常等设置告警。8.4 扩展方向多模态输入集成视觉模型如 GPT-4V来分析页面截图处理纯图片验证码或复杂 UI 布局。工具扩展让智能体不仅能操作浏览器还能调用其他工具如计算器、数据库查询、内部 API 等。这需要设计更复杂的动作空间和工具调用规范。记忆与学习为智能体引入长期记忆使其能记住不同网站的操作模式或在失败后学习新的选择器策略。分层规划对于复杂任务引入高层规划器Planner将大目标分解为子任务再由执行层智能体如本文实现的去完成每个子任务。构建一个鲁棒的网页操作智能体是一个迭代过程核心在于平衡 LLM 的灵活性与程序的确定性。从一个小而具体的任务开始逐步完善状态表示、错误处理和提示词工程是通向成功的关键路径。