AI智能体的浏览器执行:Playwright、MCP与安全执行器
AI智能体的浏览器执行方案:以浏览器作为MCP与代码模式之外的运行时环境,底层采用Playwright技术,通过配置文件、域名限制及策略来实现安全保障。
来源: Why Browser Execution Is Becoming the Missing Capability in Agent Architecture?
现有的智能体已经能够熟练操作各种机器。它们可以调用 API、连接 MCP 服务器、运行代码、查询网络、打开文件以及执行 shell 命令。然而,令人惊讶的是,仍有相当一部分实际软件仅通过浏览器界面来展示其部分核心功能,而这正是浏览器执行模式所要填补的空白。
最新的智能体产品会为智能体配备浏览器或云终端。人们很容易将其视为又一种人工智能点击按钮的演示。但从架构角度来看,浏览器并非一种新型的智能体,而是一种新的执行环境。
这种差异很重要。如果某个系统已经提供了MCP服务器、技能、代码运行功能、程序化工具调用、沙箱环境、搜索功能以及直接的后端接口,那么浏览器就不应取代这些功能。浏览器会将系统扩展到其无法可靠处理的领域:那些需要维护状态、依赖大量JavaScript、且为人类用户设计的需要身份验证的应用程序。
搜索功能用于查找信息,API和MCP则用于与系统进行交互,代码则负责处理数据并协调各步骤。而浏览器则用于操作那些为人类设计的界面。
被遗忘的界面
智能体架构通常从结构化的功能开始构建。当某个服务提供了规范的REST API、SDK或MCP服务器时,这几乎总是智能体的最佳接口:明确的契约、带类型的输入输出、更易于处理的故障情况,以及更清晰的安全边界。
接下来是代码执行阶段。与其让模型逐一调用二十个工具,不如让它编写一个小程序来调用这些工具,在本地汇总结果、筛选数据,最终返回一个简洁的答案。这种方式非常适合工具数量众多、需要频繁调用以及处理大量数据的工作流程。沙箱则在一个受控环境中提供了额外的功能,支持使用Python、shell、文件,甚至Kubernetes或GitHub相关的工具。到那时,智能体已经能够执行许多操作,但它仍然假设所有有用的功能都通过机器可读的接口提供。
并非如此。许多工具仅存在于屏幕背后:内部管理面板、旧版供应商门户、报表控制台、合作伙伴系统、招聘平台、分析产品、SaaS设置页面,或是那些只有在设置好多个筛选条件后才获取实时数据的应用程序。数据可能是公开的,但有用的数据格式是由JavaScript生成的。有人认为这项任务很简单,但却没有对应的API文档。偶尔会有内部API,但它可能是私有的、不稳定的,或是被故意放弃支持的。
这才是真正的应用场景:并非让AI抽象地浏览互联网,而是在任务本身需要使用应用程序时,将浏览器作为备用接口。
为何MCP尚未涵盖此功能
每当谈到浏览器执行时,这个问题就会出现,它值得一个明确的答案。MCP从不需要目标系统具备API;它仅规定代理如何与某种功能进行交互。假设目标应用程序仅提供给人使用的用户界面,那么MCP工具背后的代码就可以直接驱动浏览器。限制并非来自MCP本身,而是目标系统背后缺乏稳定、结构化的接口。
目标端可能不会暴露任何结构化内容。MCP背后可以是浏览器、沙箱、工作流引擎,或是完全不同的东西。问题出现在当该应用没有公共API、SDK、数据库集成,也没有可用于执行所需操作的编程接口时。MCP仍然可以发布名为browser_execute的工具,但必须由其背后的组件来操作系统,也就是通过浏览器来执行任务。二者并非竞争对手:MCP可以是用于暴露浏览器功能的协议,而在没有更合适的方案时,浏览器则是面向用户的应用与系统交互的途径。
身份验证可能与浏览器绑定。MCP拥有自身的授权模型,包括OAuth流程,但仅覆盖MCP客户端与MCP服务器之间的交互。它不会干涉工具最终需要操作的系统的登录规则。许多内部门户、供应商应用以及较旧的SaaS产品仅允许通过带有SSO、MFA、会话Cookie或在人工登录时生成的其它状态信息的交互式浏览器流程进行访问,且不存在服务凭证或委托令牌。MCP工具仍可在经过身份验证的浏览器配置文件支持下提供相应功能。用户通过浏览器登录,会话状态处于受控访问状态,之后即可以该身份执行操作。限制因素在于目标应用的授权模型,而非MCP的授权模型。
有些任务属于用户界面工作流,而非单一调用。比如“选择欧洲地区的零售数据以及过去90天的数据,然后计算每个国家的平均转化率”。这类任务可能需要一系列过滤操作、渲染步骤以及结果状态的提取,没有哪个接口能直接返回答案。浏览器可以操作界面并读取应用生成的输出。
只要存在结构化API,无论是直接调用还是通过MCP调用,它们始终是首选。这类API成本更低、更可预测,也更容易实现安全保护。浏览器负责处理那些仅存在于面向用户的界面之后的部分。
搜索与浏览不同
在许多智能体架构中,网络搜索、HTTP请求、浏览器自动化以及计算机操作都被统称为一种模糊的“网络”技能,但实际上它们是不同的工具。
若想了解最新MCP规范有哪些变化,上网搜索即可。只要知道一篇普通公开文章的网址,直接检索往往就足够了。需要与Salesforce交互时,则要使用其API或MCP。要对JSON数据进行统计分析,则需编写代码。
现在想象另一个请求:打开一个公开仪表板,选择乌克兰,将年份设定为2026,挑选“企业”类别,逐个查看各类数据并计算各项指标的平均值。搜索引擎无法完成这样的操作,而普通的HTTP请求可能只会返回页面的空壳。真正有用的数据是在浏览器运行JavaScript、发送客户端请求、更新应用状态并渲染结果之后才会出现。
或者使用招聘网站:选择“AI工程”“远程工作”和“德国”类别,然后统计描述中提到RAG的职位数量。那其实并非真正的搜索查询,而是一种UI工作流程,随后才是数据提取与计算环节。正是在这里,真正的浏览器能为智能体提供新的功能——一个具有状态保持能力的网页执行界面。
浏览器即运行时环境
像Amazon Bedrock AgentCore Browser这样的托管浏览器属于基础设施:它是一个可被程序化控制的隔离式远程浏览器会话。大型语言模型并不会自动与之通信,你需要自行定义智能体与环境之间的交互规则。
AgentCore浏览器通过WebSocket自动化端点暴露会话,而Playwright之类的库则可以通过Chrome DevTools协议连接到远程的Chromium。对于CDP无法妥善处理的交互操作,AWS提供了独立的操作系统级浏览器功能。浏览器只是远程运行时环境,而非智能处理层。从这个角度看,集成会更简单:代理需要具备可编程能力,而浏览器运行时就是执行该能力的场所。
让代理编写浏览器代码
浏览器可以通过多种方式与代理通信。一种方法是使用像browser_task(task="find the latest invoice")这样的高级工具,其中包含专门为浏览器设计的代理,负责读取任务、浏览网站、确定点击操作并反馈结果。这种方法在面对需要探索工作流程的陌生网站时有一定帮助,但作为起点并不理想。
如果主模型是一名出色的编码者,更简洁的设计方式是让它生成浏览器程序,然后将其传递给浏览器执行器。只需一个如 browser_execute(code, profile_id, allowed_domains) 这样的简单函数签名即可:
browser_execute(
code=generated_playwright_code,
profile_id="vendor-portal-user-42",
allowed_domains=["portal.example.com"]
)
接到调用后,执行器会检查请求,然后创建(或重用)一个隔离的会话,并将 Playwright 连接到远程浏览器。它执行程序并返回结构化数据。主代理只需进行一次思考;只有当任务确实需要探索时,才有必要让第二个大语言模型重新解读相同的意图。对于那些可预测的仪表板、目录或门户而言,这种方式在成本以及数据观察的便捷性方面都优于嵌套式浏览器代理。
为何代码模式更合适
在已经使用程序化工具调用的场景中,这一点尤为重要。那种低效的模式很容易被识别:模型先调用 click 获取结果,再调用 screenshot 进行分析,接着调用 type 获取另一组结果。原本用简单脚本几毫秒就能完成的工作,现在却要经过数十次模型的处理。
更好的模式匹配工具集成方式是:让模型编写一个程序,在执行环境中完成多项浏览器操作,最终返回一个简洁的结果。
page = await browser.page()
await page.goto("https://jobs.example.com")
await page.get_by_label("Category").select_option("AI Engineering")
await page.get_by_label("Location").select_option("Germany")
await page.get_by_label("Remote").check()
await page.get_by_role("button", name="Apply").click()
jobs = await page.locator(".job-card").all_inner_texts()
rag_jobs = [job for job in jobs if "RAG" in job.upper()]
return {
"total_jobs": len(jobs),
"jobs_mentioning_rag": len(rag_jobs)
}
模型编写一个程序,执行器会进行数十甚至数百次确定的DOM操作,而代理则接收一个简小的JSON对象,无需一系列复杂的点击操作和截图。
它还可以更进一步。具备能力感知功能的代码运行时可以为生成的程序提供若干受控接口,包括MCP客户端、普通HTTP、文件操作、浏览器控制以及本地计算功能。同一个程序可以通过MCP从Salesforce获取账户信息,打开旧版门户网站,读取每个账户的指标数据,进行汇总后返回一个结果。
customers = await mcp.salesforce.search_accounts(segment="enterprise")
results = []
for customer in customers:
await browser.goto(f"https://legacy.example.com/customer/{customer.id}")
metric = await browser.locator("#health-score").inner_text()
results.append({
"customer": customer.name,
"health_score": metric,
})
return summarize(results)
那并非人工智能在随意点击操作,而是通过机器界面与人类界面之间的程序化协同来实现的。
实际工作流程
以一个看似简单的请求为例:进入公共分析仪表板,选择“零售”类别,限定地区为欧洲,时间范围为过去90天,进而比较不同国家之间的转化率和用户留存率差异。
代理程序不应直接打开浏览器。首先会由能力路由器判断是否存在更高效、结构更清晰的处理路径。如果搜索功能可以回答问题,则先进行搜索;如果页面提供了稳定的API,则调用该API;如果直接通过HTTP获取数据即可,就无需启动Chromium浏览器。
如果这些数值仅在客户端交互之后出现,路由器会选择在浏览器中执行。主代理会生成一个 Playwright 程序,执行器会在受管理的会话中运行该程序,等待页面停止变化,读取渲染出的数值并将其作为结构化数据返回。随后代码模式会进行比较运算,代理则负责输出结果。用户无需知晓浏览器已被打开。在许多产品中,这应是一种不可见的后端功能,类似于数据库查询或代码沙箱。
先自动化,再使用计算机
浏览器自动化与计算机使用有时被视为一回事,但实际上它们属于技术栈中的不同层级。Playwright和CDP作用于浏览器结构:页面、选择器、DOM元素、表单、网络请求、下载内容以及状态。正因如此,它们的运行速度更快、成本更低,同时也更易于测试和隔离。
计算机的使用依赖于可视化操作。模型通过观察屏幕来发出鼠标或键盘指令。当 DOM 无法可靠地处理某些界面元素时——比如画布应用、原生对话框、上下文菜单以及复杂的拖放操作——这种模型就能发挥作用。AWS 在 AgentCore 浏览器中也采用了类似思路,其 WebSocket 自动化功能基于 CDP 构建,而 InvokeBrowser API 则能为 CDP 无法完成的任务提供操作系统级的控制能力。因此,应优先使用结构化自动化方式,仅在必要时才采用可视化控制。代理在技术栈中的层级越低,其灵活性就越高,但每项操作的代价也越大,且更容易出现状态问题与风险。
在转而使用计算机之后,执行器应运行一个封闭的验证循环,而非一系列盲目的操作。一次无错误返回的点击并不能证明操作已经完成——页面可能仍在加载中,某个模态框可能拦截了该操作,或者有其他元素抢占了点击。在执行任何后续步骤之前,运行时系统应检查新状态,确认预期的变化确实发生后再继续。它还应能识别出那些毫无作用的重复操作。如果同一步骤重复执行却没有任何变化,再次尝试是错误的;正确的做法是重新规划或退回到更为结构化的策略。
这个循环依赖于三重保障:限制保存的截图数量、检测那些不会带来任何变化的重复操作,以及逐个应用不同的权限级别。
身份验证让工作真正落地
公共控制面板适用于概念验证,但企业级价值体现在经过身份验证的应用程序中。Playwright已经具备完善的浏览器上下文管理机制以及可重复使用的身份验证状态功能,而AgentCore Browser则增加了托管式配置文件,能够跨会话保留Cookie和本地存储数据。用户只需登录一次,其配置文件就会被保存,后续会话即可自动恢复该状态。这对于内部门户、客户系统、传统SaaS应用以及供应商应用程序尤为有用,因为在这些场景中,若要通过API集成,往往需要自行进行逆向工程,否则根本无法实现。
它还改变了身份模型的构建方式。浏览器配置文件实际上是一种带有认证信息的执行身份,而非普通的便捷对象。能够访问金融门户的配置文件不应自动对所有代理或工作流开放。在实际应用中,应将配置文件与租户、用户、用途及策略范围绑定,并仅授予代理对特定配置文件的访问权限,而非允许其访问用户拥有的所有会话。
安全性比演示更重要
浏览器执行方式之所以强大,是因为它通过与人类相同的界面进行操作,这也意味着它可能会以人类的权限犯错。
第一道防线是执行器。生成的浏览器代码应在隔离环境中运行,具备明确的域名限制、超时设置、资源上限以及对配置文件的受控访问权限。仅因为模型能够运行 Playwright,并不意味着它就能获取主机环境变量、任意凭证或通用网络路径。
第二道防线是操作策略。从页面中提取数据与发布内容、发送消息、修改账户权限、删除数据或批准支付属于不同的操作。应将这类副作用归类到模型之外,并在执行层进行管控。
第三种是提示注入。一旦智能体能够读取任意页面,所有显示的内容都可能成为不可信的输入。控制面板、邮件、横幅或文档中的文本都可能被视作智能体的指令。执行者绝不能将屏幕上的内容视为用户的授权依据。OpenAI的计算机使用指南也指出同样的原则:应将第三方内容视为不可信的,并在执行发布、发送、删除、更改权限或转账等高风险操作之前寻求确认。这属于执行策略的问题,而不仅仅是提示工程的问题。浏览器虽然可以广泛观察,但只能通过明确的策略来改变实际状态。
接下来是可观测性。生产环境执行器应记录被请求的任务、所使用的配置文件、访问的域名、执行的程序、下载的文件、尝试的外部操作以及需要人工审批的情况。AgentCore浏览器支持实时监控,而自定义浏览器则具备会话录制与回放功能,这为审计工作提供了坚实基础。
它与MCP、技能及沙箱的关系
这里没有任何东西可以替代其他方式。对于结构化的业务操作,MCP和API依然是首选。技能组合则包括可重复执行的流程、相关背景知识以及操作经验。代码模式则是进行重复调用、数据聚合与转换的高效方式。沙箱环境则为文件处理、命令行操作、Python编程、测试以及高负载计算提供了受控的空间。而浏览器执行则用于填补另一类场景:在没有足够可靠的机器端对应方案时,用于操作面向用户的界面。
请保持路由策略的保守性。如果API能够完成任务,就使用它;如果直接检索就能解决问题,就无需打开浏览器;如果必须操作网站本身才能获得结果,那么浏览器执行才是合适的选择;如果结构化自动化无法完成交互,使用计算机才是最后的手段。
MCP作为契约
在实际应用中,这些功能分支很少会保持分离状态。代码执行、浏览器执行甚至工具发现通常都会在 MCP 服务器背后完成。MCP 不仅仅是 API 分支,它还是代理获取各种功能的契约,无论是通过 REST 调用、沙箱脚本,还是底层的远程 Chromium 引擎。
采用单个专用的 MCP 服务器来提供少量工具(如 execute_code、browser_execute 和 find_tool)会比为每个底层操作单独提供工具更高效。这样工具数量仅为三到四个,而非三十个。模型无需单独的点击、截图和选择选项工具,正如它也不需要将重启、扩展和回滚功能拆分为独立工具——因为一个带有计划的操作就足以完成这些任务。
可移植性是另一个原因。同一台服务器既可以通过自定义代理工具使用,也可以直接接入 Claude、ChatGPT 或任何支持 MCP 的客户端,这样无需再次集成,就能通过熟悉的界面测试相同的功能。
将执行器单独隔离
从代理的角度来看,浏览器可能看起来像是代码模式的一部分,因为某个生成的脚本可能会在同一个逻辑运行时中,与MCP客户端、文件及计算API一同使用browser.goto()和browser.locator()。但在部署时,将浏览器执行器作为独立组件使用仍然更为合适。浏览器拥有自身的生命周期与风险:会话、Cookie、本地存储、下载的文件、网络规则、登录的账号信息、页面状态,以及系统外部产生的记录和副作用。而代码沙箱则主要处理CPU、内存、文件、包和进程等资源。将二者分开可以让各自的运行时实施适合自身的安全模型。代码模式可以提供受限的浏览器客户端,而执行器则负责管理远程会话,这样编程模型保持统一,而基础设施则保持分离。
开始变得无聊
一开始不必使用通用的自动化浏览器代理。首个可用的版本刻意设计得较为简单:一个独立的远程 Chromium 会话、一个小的 browser_execute 接口、用于自动化的 Playwright 工具、严格的域名允许列表以及结构化的结果输出。可以在一个依赖大量 JavaScript 的公共控制面板或示例应用上对其进行测试,以此证明该浏览器比搜索和 HTTP 获取方式更高效。
在这一点实现之后,将其与代码模式中已使用的编程化模式相连,这样主代理就能生成浏览器程序,而无需反复调用低级的点击工具。接着为受控的内部应用添加经过身份验证的配置文件,再设置操作策略和审批机制,以确保任何工作流在产生外部影响之前都经过验证。仅在对Playwright无法可靠处理的界面时才使用可视化操作方式,并考虑设计一种专门的浏览器代理循环,该循环能够在任务过于模糊、主代理无法生成稳定程序时进行观察、推理、重试和探索。这样的设计顺序能让架构更易于理解,同时将成本最高、最不可预测的行为置于边缘位置,而非使其成为默认行为。
更大的变革
有趣之处并不在于大语言模型能够点击按钮——浏览器自动化技术早已存在多年。新的是,智能体可以自行判断何时使用浏览器作为操作界面,编写驱动浏览器的程序,将执行结果与MCP调用及代码执行相结合并继续处理任务,而无需开发者为每个面向用户的应用单独开发定制化的集成方案。
机器界面依然更优:更可靠、更安全,也更容易管理。但现实中有很多系统无法通过简洁的接口实现所需操作,以往的工作流程往往需要人工打开网站来完成工作。浏览器执行技术打破了这一限制,它让人类用户界面也成为另一种可编程的操作界面,使用时需格外谨慎,应严格隔离,并且仅在结构化界面无法满足需求时才予以使用。
下一代智能体平台不应被理解为更大的工具集合或大量的浏览器机器人,而应是拥有多个执行环境以及能够判断哪个工作环节应由哪个环境处理的路由器的系统。其目标并非让智能体点击更多次,而是让它们能够访问那些API尚未公开的软件部分。
相关阅读
- 工具调用详解:模型如何指令软件执行操作及可能出现的问题 —— 一篇关于函数调用与工具使用的实用指南:请求流程、数据结构、读取类工具与操作类工具、智能体、MCP、提示注入、追踪方法以及常见故障。