
1. 从“纸上谈兵”到“真枪实弹”为什么我们需要 Web Agent如果你在过去一年里关注过 AI 领域尤其是 Agent智能体的发展你可能会有一个强烈的感受很多所谓的“Agent”项目演示起来天花乱坠但一到实际应用场景尤其是需要与真实世界交互时就变得束手无策。它们能根据指令生成一段完美的代码能写出一篇逻辑清晰的报告但当你让它“去某某官网查一下最新的产品价格然后对比三家给我一个购买建议”时它大概率会告诉你“抱歉我无法浏览网页。”这就是当前大多数 Agent 面临的“最后一公里”问题。它们被困在了一个由纯文本和代码构成的“温室”里缺乏与现实数字世界尤其是 Web进行感知和交互的能力。一个无法浏览网页、点击按钮、填写表单、提取信息的 Agent就像是一个拥有顶级大脑却四肢瘫痪的智者空有计算和推理能力却无法将想法付诸行动。因此Web Agent应运而生它的核心使命就是赋予 Agent 真正的“手”和“眼睛”让它们能够像人类一样操作浏览器完成基于网页的任务。这不仅仅是“让 AI 上网”那么简单。Web Agent 的成熟标志着 AI 从“内容生成”向“任务执行”的范式转变。它不再仅仅是一个对话伙伴或内容创作者而是一个可以自主完成复杂工作流的数字员工。想象一下一个能自动帮你完成数据填报、竞品监控、信息聚合、甚至在线购物的助手其价值远超一个只能聊天的聊天机器人。近期随着 LangGraph 等新一代 Agent 编排框架的兴起以及 RAG检索增强生成工程化的深入构建稳定、可靠的 Web Agent 从理论探索进入了工程实践阶段。我们不再满足于用 Playwright 或 Selenium 写几个脚本而是希望构建一个能理解任务、规划步骤、处理异常、并从错误中学习的智能体系统。2. Web Agent 的核心架构感知、决策与执行的闭环构建一个实用的 Web Agent远非调用一个driver.get(url)那么简单。它需要一个完整的、健壮的架构来支撑。我们可以将其抽象为一个经典的“感知-决策-执行”循环但这个循环在 Web 环境下有其特殊性和复杂性。2.1 感知层从像素到语义的理解感知是 Agent 与网页交互的第一步。传统的自动化脚本依赖于 XPath 或 CSS 选择器等“坐标”来定位元素。但网页结构千变万化一个按钮的id或class可能随时改变这种方法极其脆弱。现代 Web Agent 的感知层需要更高级的“理解”能力。1. 视觉感知Vision-based Perception这是最接近人类的方式。Agent 获取网页的截图或 DOM 的渲染树然后使用多模态大模型如 GPT-4V、Claude 3来“看”懂页面。模型可以识别出“这是一个登录按钮”、“那是一个搜索框”、“下面有一个商品列表”。这种方式的优点是健壮性强不依赖于底层代码结构即使页面经过混淆或动态加载只要视觉上可识别Agent 就能操作。缺点是成本高调用视觉模型 API 较贵、速度慢且对模型的空间理解能力要求高。2. 混合感知Hybrid Perception这是目前工程上更主流和实用的方法。它结合了 DOM 结构信息和轻量级的视觉或语义信息。DOM 可访问性树Accessibility Tree浏览器提供的可访问性树包含了元素的角色role、名称name、状态等语义信息比原始 DOM 更结构化。例如一个div可能被标记为role”button”和name”提交”。这为 Agent 提供了更可靠的交互线索。DOM 元素语义嵌入将页面上的关键交互元素如按钮、输入框、链接的文本内容、附近文本、aria-label等属性提取出来转化为向量嵌入。当 Agent 收到指令如“点击登录”时它可以将指令与所有元素的语义嵌入进行相似度计算找到最匹配的元素。这种方法平衡了精度和效率。在实际构建中我们通常不会将整个庞大的 DOM 树扔给 LLM而是先进行关键信息提取和简化。例如使用轻量级规则或小模型过滤掉纯装饰性的div、span只保留具有交互属性如onclick、href、input或特定语义角色button、link的元素并为其生成一个简洁的描述如[BUTTON] id‘submitBtn’, text‘提交订单’。这大大降低了后续决策模型的上下文负担。2.2 决策与规划层任务分解与步骤编排这是 Agent 的“大脑”。它接收用户的高层目标如“预订下周五北京到上海的机票”并结合当前感知到的网页状态决定下一步该做什么。1. 基于LLM的零样本/小样本规划这是最灵活的方式。将当前页面简化后的元素列表、浏览历史、任务目标一起构成提示词Prompt让 LLM 直接输出下一个动作。例如当前页面携程首页。可见元素有[搜索框] 目的地 [搜索框] 出发地 [按钮] 搜索机票 [链接] 酒店预订... 任务目标查找下周五北京到上海的经济舱机票。 历史动作无。 请输出下一个动作格式为CLICK [元素描述] 或 TYPE [元素描述] [输入内容] 或 SCROLL [方向] 或 WAIT。LLM 可能会输出TYPE [搜索框] 出发地 北京。这种方式无需训练但依赖高质量的提示工程且单步决策可能缺乏长远规划容易陷入局部循环。2. 使用 LangGraph 等框架进行状态机编排对于复杂、多步骤的任务我们需要更结构化的控制流。这就是LangGraph这类框架大显身手的地方。LangGraph 允许你以“图”的形式定义 Agent 的工作流节点是处理步骤可以是调用 LLM、执行工具函数边是状态流转的条件。以一个简单的登录任务为例用 LangGraph 可以这样定义节点1导航到登录页调用浏览器工具访问网站首页寻找登录链接并点击。节点2填写表单感知当前页面是否为登录表单。是则调用 LLM 决定填写哪个字段用户名/密码否则跳转到错误处理节点。节点3提交与验证点击提交按钮然后检查页面是否跳转成功例如是否出现了“欢迎”字样或跳转到用户主页。节点4错误处理如果登录失败感知错误信息如“密码错误”并决定重试或退出。LangGraph 的StateGraph会维护一个共享的“状态”State里面包含了当前 URL、页面内容、历史动作、任务目标等。每个节点读取状态、执行操作、并更新状态。这种显式的状态机和流程控制使得 Agent 的行为更可预测、可调试也更容易处理分支和循环比如重试逻辑。它与 LangChain 的关系可以理解为LangChain 提供了连接各种组件的“链”而 LangGraph 是在链的基础上提供了更强大的、带有循环和状态的工作流编排能力特别适合长序列、多步骤的 Agent 任务。3. 子任务分解与长期记忆对于“比价”这类超长任务Agent 需要将其分解为“搜索A产品”、“提取A价格”、“搜索B产品”、“提取B价格”、“对比并生成报告”等多个子任务。这需要任务规划能力。我们可以让一个“规划器”Agent通常也是一个 LLM先分解任务然后由“执行器”Agent即 Web Agent去逐个完成。LangGraph 的“子图”功能非常适合封装这样的子任务模块。 同时为了在长达数分钟甚至更长的任务中保持连贯性Agent 需要长期记忆。这不仅仅是保存对话历史还包括已经访问过的网址、提取到的数据、遇到的错误类型等。这些记忆可以帮助 Agent 避免重复操作、从错误中学习例如记住某个网站的登录需要验证码下次提前准备、并在最终汇总信息时使用。2.3 执行层稳健的浏览器自动化决策层输出一个动作指令如CLICK [提交按钮]执行层负责将其转化为浏览器中真实无误的操作。这里就是 Playwright 或 Selenium 等浏览器自动化工具的舞台。但 Web Agent 的执行层需要更高的容错性。动作映射与执行需要将抽象的CLICK、TYPE指令映射到具体的 DOM 元素选择器和操作。这里要处理元素定位失败、元素状态不可交互如禁用、隐藏、操作后页面加载超时等问题。等待策略这是 Web 自动化中最容易出错的部分。点击后是等待页面跳转wait_for_navigation还是等待某个元素出现wait_for_selector还是等待网络空闲一个健壮的 Web Agent 需要根据动作类型和页面特征动态选择等待策略。例如点击“搜索”后应等待结果区域更新点击“详情”后应等待新页面加载。异常处理与恢复当元素找不到或操作失败时不能直接崩溃。执行层应捕获异常并将其转化为一种结构化的错误信息如ELEMENT_NOT_FOUND、TIMEOUT反馈给决策层。决策层或一个专门的“错误处理”节点可以根据错误类型决定重试、尝试替代方案如用更宽松的选择器、或请求人工帮助。将这三层组合起来就形成了一个完整的闭环执行层操作浏览器 - 感知层获取新的页面状态 - 决策层根据新状态和任务目标决定下一个动作 - 执行层执行...如此循环直至任务完成或失败。3. 工程化挑战与实战技巧从 Demo 到生产系统让一个 Web Agent 在实验室里跑通一个 demo 是一回事让它稳定可靠地运行在生产环境中是另一回事。以下是几个关键的工程化挑战和对应的实战技巧。3.1 状态表示与上下文管理给 Agent 一个“工作记忆”LLM 有上下文长度限制我们不可能把整个浏览器会话历史都塞进提示词。如何高效地表示“当前状态”技巧增量式摘要与关键快照不要每次都传递完整的页面内容。维护一个“会话摘要”初始目标始终保留。已完成步骤用一两句话摘要记录例如“已登录账号进入商品搜索页”。当前页面关键信息只提取与任务最相关的部分。如果是搜索页提取搜索框和结果列表的概要如果是商品详情页提取价格、规格等关键属性。下一步的候选动作由感知层提供的一个精简列表如“可能动作查看详情、加入购物车、返回列表”。最近一次错误如果上一步失败了记录错误类型。这样每次决策时传递给 LLM 的上下文是一个轻量的、信息高度浓缩的状态对象而不是冗长的原始数据。3.2 处理动态内容与等待与“活”的网页共舞现代网页大量使用 JavaScript 动态加载内容这给感知和等待带来了巨大挑战。技巧混合等待与主动探测网络空闲检测在执行可能触发新请求的动作如点击搜索后先等待主要网络请求完成Playwright 的page.wait_for_load_state(‘networkidle’)。特定内容等待在关键交互点定义你“期望出现”的内容。例如点击登录后期望出现“欢迎”字样或用户头像。可以设置一个等待该文本或元素出现的检查点并设定超时。视觉稳定性检测进阶对于极端动态的页面如单页应用不断微调可以周期性地对页面特定区域截图并计算连续截图之间的差异。当差异低于某个阈值时认为页面已稳定。这可以防止在页面还在加载动画时就急于进行下一步操作。3.3 提高鲁棒性让 Agent 学会“绕路走”网页布局会改元素选择器会变验证码会出现。如何让 Agent 更抗打击技巧多模态后备与动作回退策略多定位器策略不要只依赖一种方式定位元素。为关键元素准备一个优先级列表首选唯一的 CSS 选择器次选 XPath再其次是文本内容匹配最后是视觉坐标通过截图和模型识别。执行时按顺序尝试。定义动作回退链例如任务“提取价格”。首选查找带有class”price”或>