日习一技 - Browser Use
type: channel
link: https://i-study-everyday.online/category/browser-use
description: Browser Use 学习笔记
items: 使用 Patchright 绕过浏览器机器人检测
items: 详解 Browser Use 的浏览器配置
items: 使用 Browser Use 连接你的浏览器
items: 详解 Browser Use 的 Agent 用法（四）
items: 详解 Browser Use 的 Agent 用法（三）
items: 详解 Browser Use 的 Agent 用法（二）
items: 详解 Browser Use 的 Agent 用法（一）
items: 再学 Browser Use 的工具使用
items: 学习 Browser Use 的工具使用
items: 学习 Browser Use 的记忆管理

使用 Patchright 绕过浏览器机器人检测
type: item
date: 2025-06-20T07:34:00+00:00
description: 我们知道，Browser Use 默认采用 Playwright 作为浏览器操作的基础工具。Playwright 原本是由微软开源推出的一款浏览器自动化测试工具，其设计初衷是方便开发人员进行跨浏览器测试。然而，由于其功能强大且使用简便，它逐渐被广泛应用于网络爬虫领域，这也引发了一些问题。许多网站为了保护自身信息安全，采取了封禁措施，试图阻止 Playwright 的访问。浏览器自动化在运行过程中表现出的行为往往与普通用户操作有显著差异，这些差异使得具有反爬措施和网络应用防火墙（WAF）的网站能够有效识别和对抗 Playwright 驱动的爬虫行为。这也就导致了我们在使用 Browser Use 的时候，无法在一些网站上执行操作，大大限制了 Browser Use 的功能，如何绕过这些安全措施成为了 Browser Use 用户需要解决的问题。道高一尺，魔高一丈，有反爬，就有反反爬。在使用 Playwright 的时候，也有一些方法绕过反爬机制，我们今天学习的 Patchright 就是基于 Playwright 改造的另一款浏览器自动化工具，它通过巧妙地模拟真实用户行为，使得浏览器操作可以绕过机器人检测。Patchright 初体验我们先通过一个真实场景体验下 Patchright 的效果。Fingerprint.com 是一家专注于设备识别和反欺诈解决方案的企业，他们提供的浏览器机器人检测功能，通过 Smart Signal 技术实时检测自动化工具、搜索引擎爬虫等威胁，帮助网站保护自身免受机器人攻击。可以点击下面的链接，进入产品页面体验该功能：https://fingerprint.com/products/bot-detection/接下来我们使用 Playwright 和 Patchright 分别打开上面的产品页面，对比下两者有何不同。使用 Playwright 打开该页面：import asyncio from playwright.async_api import async_playwright async def main(): async with async_playwright() as p: browser = await p.chromium.launch(headless=False) page = await browser.new_page() await page.goto("https://fingerprint.com/products/bot-detection/") input() await browser.close() asyncio.run(main())可以看到 Fingerprint.com 成功检测出我们是机器人，并且标识出我们是通过自动化工具访问的：接下来我们换成 Patchright 打开该页面：import asyncio from patchright.async_api import async_playwright async def main(): async with async_playwright() as p: browser = await p.chromium.launch(headless=False) page = await browser.new_page() await page.goto("https://fingerprint.com/products/bot-detection/") input() await browser.close() asyncio.run(main())Patchright 的使用和 Playwright 完全兼容，我们只需将上面的 playwright.async_api 换成了 patchright.async_api 即可。可以看到 Fingerprint.com 这次没有检测出来，我们成功绕过了它的机器人检测功能：在 Browser Use 中使用 Patchright我们昨天学习了 Browser Use 中关于浏览器的很多配置参数，包括会话相关参数和浏览器配置参数，通过 BrowserSession 传入，以调试模式启动并操作浏览器。在会话相关的参数中有一个 playwright 参数，表示 Playwright 或 Patchright API 客户端句柄，一般通过 await async_playwright().start() 得到，我们可以通过这个参数让 Browser Use 连接并复用已有的 Playwright 或 Patchright 浏览器实例：from playwright.async_api import async_playwright async def main(…

详解 Browser Use 的浏览器配置
type: item
date: 2025-06-19T07:33:00+00:00
description: 昨天我们学习了 Browser Use 启动或连接浏览器的几种方法，包括 executable_path、Playwright 对象、Browser Server、CDP 和 PID 等，这些方法有一个共同点，都是通过 BrowserSession 类来设置参数，而这个类也是 Browser Use 配置和操作浏览器的核心。BrowserSession 的配置参数非常繁杂，不过可以将其大致分为两类，一类是 会话相关参数（Session-Specific Parameters），包括浏览器连接参数和活动的 Playwright 对象实例，BrowserSession 通过这些参数连接浏览器并跟踪其活动；另一类是 浏览器配置模版（Browser Profile），包括 Browser Use 特有的参数和 Playwright 相关的参数，这类参数的特点是静态的，可以通过 BrowserProfile 存储，方便 BrowserSession 复用。我们今天就对照官方文档，对这些参数做个盘点。会话相关参数会话相关参数，包括浏览器连接参数和 Playwright 对象实例，这些参数和活动的会话相关，无法存储在 BrowserProfile(...) 模板中。浏览器连接参数这些参数分别对应不同的连接到现有浏览器的方式，在昨天的文章中我们已经详细学过这些内容：参数名默认值参数说明wss_urlNone连接到 Playwright 协议的浏览器服务器地址cdp_urlNone通过 CDP 协议连接到开启调试模式的 Chrome 浏览器browser_pidNone根据 PID 连接到本地运行的浏览器进程Playwright 对象实例我们知道，Browser、BrowserContext 和 Page 都是 Playwright 内置的对象，一般通过 (await async_playwright().start()) 或 (await async_patchright().start()) 以调试模式启动浏览器子进程，然后通过 CDP 将命令传递给浏览器。我们可以将这些对象传递给 BrowserSession，让 Browser Use 连接并复用已有的浏览器实例：参数名默认值参数说明playwrightNone可选的 Playwright 或 Patchright API 客户端句柄browserNone可选的 Playwright Browser 对象browser_contextNone可选的 Playwright BrowserContext 对象pageNone也可以写成 agent_current_page，表示智能体专注的前台页面human_current_pageNone人类专注的前台页面，不必手动设置initializedFalse将 BrowserSession 标记为已初始化，跳过启动和连接（不推荐）浏览器配置模版browser_profile: BrowserProfile = BrowserProfile()BrowserSession 可以接受一个可选的 browser_profile 参数，它是一个配置模板，可以包含一些配置默认值，用法如下：browser_profile = BrowserProfile( executable_path='/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', user_data_dir='~/.config/browseruse/profiles/default', ) browser_session = BrowserSession( browser_profile=browser_profile )所有 BrowserProfile 中的参数都可以直接传给 BrowserSession，下面的写法和上面的代码没有区别：browser_session = BrowserSession( executable_path='/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', user_data_dir='~/.config/browseruse/profiles/default', )如果某个参数同时传给 BrowserProfile 和 BrowserSession，BrowserSession 中的参数值会覆盖 BrowserProfile 中的默认值。尽管 BrowserProfile 是可选的，将参数传给 BrowserProfile 或者 BrowserSession 都可以，但使用 BrowserProfile 提供了一…

使用 Browser Use 连接你的浏览器
type: item
date: 2025-06-18T07:31:00+00:00
description: 浏览器是我们日常生活和工作中不可或缺的重要工具，Browser Use 的本质就是模拟人类对浏览器进行各种操作以完成用户任务。在之前的示例中，默认使用的是 Playwright 内置的 Chromium 浏览器，Browser Use 还支持多种启动或连接其他浏览器的方法，我们今天来学习这方面的内容。通过 executable_path 启动本地浏览器在之前介绍 Agent 配置时，我们曾学过 BrowserSession 参数的概念，它是 Browser Use 配置浏览器的核心类，它有一个 executable_path 参数，可以指定用户电脑上已安装的浏览器路径。当我们设置 executable_path 参数时，Browser Use 就会启动该浏览器，而不使用 Playwright 内置的浏览器：from browser_use import Agent, BrowserSession browser_session = BrowserSession( executable_path='/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', # executable_path='C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', # executable_path='/usr/bin/google-chrome', user_data_dir='~/.config/browseruse/profiles/default', ) agent = Agent( task="Your task here", llm=llm, browser_session=browser_session, )上面的代码使用的是用户已安装的 Chrome 浏览器，注意不同的操作系统下安装路径也不同。Browser Use 只支持基于 Chromium 内核的浏览器，比如 Brave、Patchright、Rebrowser、Microsoft Edge 等，暂时不支持 Firefox 或 Safari 浏览器。自定义 Chrome 启动参数鉴于安全原因，从 v136 开始，Chrome 不再支持使用默认的配置文件来驱动浏览器，所以无法复用你已有的浏览器配置，如登录凭据，收藏夹，扩展程序等。Browser Use 为此创建了一个新的专用配置文件，位于 ~/.config/browseruse/profiles/default，可以在启动 Chrome 浏览器时，将配置文件设置成这个（注意使用全路径）：$ cd /Applications/Google\ Chrome.app/Contents/MacOS $ ./Google\ Chrome --user-data-dir=/Users/aneasystone/.config/browseruse/profiles/default在 macOS 上，还有一种更简单的方式启动应用：# 以应用名称启动 $ open -a <应用名称> --args <参数> # 以应用路径启动 $ open <应用路径> --args <参数>比如：$ open -a "Google Chrome" --args \ --user-data-dir=/Users/aneasystone/.config/browseruse/profiles/default或：$ open "/Applications/Google Chrome.app" --args \ --user-data-dir=/Users/aneasystone/.config/browseruse/profiles/default需要注意的是，启动之前最好先退出所有的 Chrome 实例，不然参数可能无效。通过这种方式打开浏览器后，所有的用户数据会持久化到 Browser Use 的专用配置文件中，所以当我们再次用 Browser Use 启动浏览器时，就可以访问这些用户数据，包括且不限于下面这些：所有已登录的会话和 Cookies如果启用了自动填充，则可访问保存的密码浏览器历史记录和书签扩展程序及其数据所以务必检查分配给智能体的任务，确保符合你的安全要求！对于任何敏感数据，请使用 Agent(sensitive_data=...)，并使用 BrowserSession(allowed_domains=...) 限制浏览器访问。使用现有的 Playwright 对象连接浏览器我们之前学习过 Browser、BrowserContext 和 Page 参数的概念，这三个都是 Playwright 内置的类：Bro…

详解 Browser Use 的 Agent 用法（四）
type: item
date: 2025-06-17T07:30:00+00:00
description: 经过这几天的学习，总算把 Browser Use Agent 所有的配置参数都搞清楚了，我们今天先对这些参数做一个总结回顾，然后继续来研究下 agent.run() 方法，学习它的基本用法和生命周期钩子等概念。配置参数回顾下面这张表格概括了 Agent 所有的配置参数，以及它的默认值和功能说明，可以帮助大家快速理解和回顾之前学习的内容：参数名默认值参数说明task必填表示智能体需要完成的任务，通常为自然语言描述。llm必填使用的大语言模型实例。支持 DeepSeek、GPT-4 等。pageNonePlaywright 的 Page 对象，用于让智能体直接使用预初始化的网页。browserNonePlaywright 的 Browser 对象，用于指定浏览器实例。browser_contextNonePlaywright 的 BrowserContext 对象，用于设置独立的浏览器上下文。browser_profileNoneBrowser Use 内置的配置类，包括浏览器启动参数、连接参数和默认的视图信息。browser_sessionNoneBrowser Use 内置的会话类，表示活跃的浏览器会话（实例化后的浏览器进程）。controllerController()自定义工具管理类，可以通过装饰器 @controller.action 注册工具。升华智能体功能。contextNone任意用户自定义的上下文对象，例如数据库连接、文件句柄或运行时配置，仅透传给自定义工具。override_system_messageNone重写系统提示词的内容，用于替换默认的任务规划和工具调用提示词。extend_system_messageNone在默认提示词后追加内容，用于增强提示词，而不是完全替换。建议优先使用。max_actions_per_step10一次最多执行多少个大模型生成的动作，控制任务中模型生成动作的数目。message_contextNone附加的任务上下文描述，用于让模型更好地理解任务或场景。max_input_tokens128000最大支持输入 token 数，模型的上下文窗口大小（如 DeepSeek V3 为 64K，GPT-4 为 128K）。tool_calling_method'auto'控制工具调用方式，可选 function_calling、json_mode、raw、tools、auto。use_visionTrue是否开启视觉能力，表示是否将网页截图作为消息的一部分。禁用能降低 token 消耗。planner_llmNone用于规划任务的大语言模型实例，可以是一个比主模型更小或更便宜的模型。use_vision_for_plannerFalse是否为规划模型开启视觉能力，如果开启，会传递网页截图给模型。planner_interval1控制每隔多少步规划一次任务，默认是每步都规划。is_planner_reasoningFalse是否通过 HumanMessage 而不是 SystemMessage 传递规划提示词，适配不支持 SystemMessage 的推理模型。extend_planner_system_messageNone向默认规划提示词后附加额外内容，用于定制化任务分解的逻辑。page_extraction_llmNone用于页面内容提取的大语言模型实例，如果未配置，默认使用主模型。initial_actionsNone初始化时执行的固定动作（如打开某个页面），无需调用大模型，能节省 token。save_conversation_pathNone保存会话记录的目录路径，包含每一步的 Prompt 和模型响应结果，便于调试和分析。save_conversation_path_encoding'utf-8'会话记录文件的编码格式，默认为 UTF-8。include_attributestitle, type, name, role 等保留关键网页元素的部分属性，用于节省 token（默认值包括 title, type 等带有语义信息的属性）。validate_outputFalse完成任务时开启输出校验，确保任务的最终结果准确信息。max_failures3遇到异常时的最大重试次数，可处理浏览器异常关闭、token 超限及接口限流等问题。retry_delay10接口限流错误时延迟的时间（单位：秒），然后重试。generate_gifFalse运行结束后生成操作过程的 GIF 动画，包含任务、每一步目标和截屏记录。save_playwright_script_pathNone保存 Playwright 脚本的路径，用于重放操作过程（最新版本已移除，但派生了 Workflow Use …

详解 Browser Use 的 Agent 用法（三）
type: item
date: 2025-06-16T07:29:00+00:00
description: 关于 Browser Use 的 Agent 配置参数还剩一些，我们今天继续学习。注册回调register_new_step_callback: ( Callable[['BrowserStateSummary', 'AgentOutput', int], None] # Sync callback | Callable[['BrowserStateSummary', 'AgentOutput', int], Awaitable[None]] # Async callback | None ) = None, register_done_callback: ( Callable[['AgentHistoryList'], Awaitable[None]] # Async Callback | Callable[['AgentHistoryList'], None] # Sync Callback | None ) = None, register_external_agent_status_raise_error_callback: Callable[[], Awaitable[bool]] | None = None,在上一篇中，我们介绍了一个 Browser Use 的有趣功能，通过 generate_gif=True 参数可以在任务运行结束时生成一个 GIF 动画。但是想象一下，如果我们想基于 Browser Use 开发一款 Web 版的智能体应用，用户希望实时的看到每一步对浏览器的操作，就像 Manus 演示的那样，又该如何实现呢？为此，Browser Use 提供了一些回调机制，允许我们在智能体执行的特定时刻访问其状态数据，并执行自定义代码：register_new_step_callback - 该回调函数在每次调用大模型获取下一步动作之后触发，函数中可以访问当前的浏览器状态和大模型的输出；register_done_callback - 该回调函数在整个任务完成之后触发，函数中可以访问智能体运行的所有历史数据；register_external_agent_status_raise_error_callback - 这个回调函数有点意思，它并不是在出现异常时触发，而是让用户自定义是否触发异常，如果这个函数返回 True，就会触发 InterruptedError；其中最有用的应该是第一个回调函数，我们可以监听 Browser Use 的每一步执行，从浏览器状态中获取屏幕截图，实时地返回给 Web 前端：from browser_use.agent.views import AgentOutput from browser_use.browser.views import BrowserStateSummary def register_new_step_callback(browser_state_summary: BrowserStateSummary, agent_output: AgentOutput, n_steps: int): print(f'========== STEP {n_steps} BEGIN ==========') print("BrowserStateSummary:") print(f' Title: {browser_state_summary.title}') print(f' Url: {browser_state_summary.url}') print(f' Screenshot: {browser_state_summary.screenshot[:80]}...') print("AgentOutput:") print(f' Previous Goal: {agent_output.current_state.evaluation_previous_goal}') print(f' Next Goal: {agent_output.current_state.next_goal}') print(f'========== STEP {n_steps} END ==========') from browser_use import Agent async def main(): agent = Agent( task="Compare the price of gpt-4.1-mini and DeepSeek-V3", llm=llm, # 监听每一步执行 register_new_step_callback=register_new_step_callback, ) result = await agent.run()其中 browser_state_summ…

详解 Browser Use 的 Agent 用法（二）
type: item
date: 2025-06-13T12:18:00+00:00
description: 话不多说，我们今天继续来学习 Browser Use 的 Agent 配置参数。开启规划模型planner_llm: BaseChatModel | None = None, use_vision_for_planner: bool = False, planner_interval: int = 1, is_planner_reasoning: bool = False, extend_planner_system_message: str | None = None,为了更好地处理复杂的多步骤任务，Browser Use 支持配置单独的 规划模型（Planner model） 对任务进行高层规划，上面这些参数都是和规划模型相关的参数。参数 planner_llm 是 LangChain 的 ChatModel，表示规划时使用的模型，可以是一个比主模型更小或更便宜的模型；参数 planner_interval 用于控制每隔多少步规划一次，默认是每步都规划；参数 use_vision_for_planner 表示是否开启视觉能力，如果模型不支持可以禁用，和 use_vision 一样，如果开启视觉能力，Browser Use 会将网页的截图也添加到消息中，可以让大模型更好地理解网页内容，但是同时也会提高成本。agent = Agent( task="your task", llm=llm, # 开启规划模型 planner_llm=planner_llm, # 规划时禁用视觉，默认是开启的 use_vision_for_planner=False, # 每 4 步规划一次，默认是每步都规划 planner_interval=4 )当 Browser Use 开启规划模型时，会使用一段默认的规划提示词，将任务分解为更小的步骤（我们在 “记忆管理” 篇学习过），可以使用 extend_planner_system_message 在默认的提示词后面追加内容；另外，这段规划提示词默认是通过 SystemMessage 传给大模型的，但是有些推理模型不支持 SystemMessage，比如 o1、o1-mini 等，可以设置 is_planner_reasoning=True 参数，这时规划提示词是通过 HumanMessage 传给大模型。内容提取模型page_extraction_llm: BaseChatModel | None = None,在 Browser Use 内置的 20 个工具里，有一个叫 extract_content，它的实现如下：@self.registry.action( '提取页面内容以获取特定信息，并以结构化格式呈现', ) async def extract_content( goal: str, page: Page, page_extraction_llm: BaseChatModel ): # 将页面内容转为 Markdown 文本 content = markdownify.markdownify(await page.content(), strip=strip) # 内容提取提示词 prompt = ''' 您的任务是提取页面的内容。 您将获得一个页面和一个目标，您应该从页面中提取与此目标相关的所有信息。 如果目标模糊，请总结页面。 请以 JSON 格式响应。 提取目标：{goal}，页面：{page}''' template = PromptTemplate(input_variables=['goal', 'page'], template=prompt) # 调用内容提取大模型 output = await page_extraction_llm.ainvoke( template.format(goal=goal, page=content)) msg = f'📄 Extracted from page\n: {output.content}\n' return ActionResult(extracted_content=msg, include_in_memory=True)它使用内容提取模型，从页面中提取特定的内容，并返回 JSON 格式。参数 page_extraction_llm 用于配置内容提取使用的模型，如果不配置，默认使用的是主模型。初始动作initial_actions: list[dict[str, dict[str, Any]]] | None = None,昨天在学习浏览器设置时，我们介绍了一个有趣的例子，先通过 Playwright 做一些固定的动作，比如打开某个页面，然后再让 Browser Use 基于这个页面完成某个任务。其实，还有一种更简单的方法来…

详解 Browser Use 的 Agent 用法（一）
type: item
date: 2025-06-12T12:17:00+00:00
description: 经过这几天的学习，我们已经对 Browser Use 的 “任务规划”、“记忆管理” 和 “工具使用” 都有了更深入的理解，不过这些内容主要是围绕源码展开，偏理论，在实战中很难用上。所以，我们今天再来看下 Browser Use 的实际用法。在入门篇里，我们已经介绍过 Browser Use 的基本用法，如下：agent = Agent( task="Compare the price of gpt-4.1-mini and DeepSeek-V3", llm=llm, ) result = await agent.run()通过 Agent 初始化一个智能体，传入 LLM 实例和我们的任务，然后调用 agent.run() 启动智能体，得到结果。这里有三个点可以展开学习：Agent 类的初始化函数，除了 task 和 llm 这两个必填参数之外，还有哪些选填参数？agent.run() 方法还有哪些额外参数？agent.run() 的结果 result 是什么类型？Agent 参数概览Agent 类是 Browser Use 的核心组件，它除了 task 和 llm 两个必填参数之外，还有很多其他的配置参数：别看这里的参数列表这么长的一串，其实有不少参数在之前的学习中已经介绍过。今天就对所有参数做一个汇总介绍。浏览器设置page: Page | None = None, browser: Browser | None = None, browser_context: BrowserContext | None = None, browser_profile: BrowserProfile | None = None, browser_session: BrowserSession | None = None,这 5 个参数都是和浏览器有关，我们知道 Browser Use 基于 Playwright 实现浏览器操作，这里的 Page、Browser、BrowserContext 都是 Playwright 内置的类，是三个层次不同的概念：Browser（浏览器实例）代表整个浏览器进程是最顶层的对象，包含所有的浏览器上下文通过 playwright.chromium.launch() 等方法创建一个 Browser 可以包含多个 BrowserContextBrowserContext（浏览器上下文）相当于一个隔离的浏览器会话，类似于浏览器的 “无痕模式”每个 BrowserContext 都有独立的 cookies、localStorage、sessionStorage 等存储不同 BrowserContext 之间完全隔离，互不影响一个 BrowserContext 可以包含多个 Page可以设置独立的用户代理、视口大小、权限等Page（页面/标签页）代表浏览器中的一个标签页是实际进行页面操作的对象（点击、输入、导航等）每个 Page 属于一个 BrowserContext包含页面的 DOM、JavaScript 执行环境等Browser 和 Page 比较好理解，BrowserContext 作为他们之间的介质，形成类似下面这样的分层结构：Browser ├── BrowserContext 1 │ ├── Page 1 │ └── Page 2 └── BrowserContext 2 ├── Page 3 └── Page 4BrowserContext 主要用于隔离不同的测试场景，比如登录不同的用户或者使用不同的配置，这种分层设计既能高效复用浏览器资源，又能保证测试之间的隔离性。BrowserProfile 和 BrowserSession 是 Browser Use 内置的类，它们两的概念如下：BrowserProfile（浏览器配置）静态的配置信息，包括浏览器的启动参数、连接参数、视图信息等Browser Use 根据这些配置创建浏览器会话BrowserSession（浏览器会话）表示一个活跃的浏览器会话，对应一个正在运行的浏览器进程这是 Browser Use 管理浏览器的核心，在构造记忆时，其中的浏览器状态就是通过它实现的上面的所有参数，最终都是转换为浏览器会话浏览器设置是一个复杂的话题，后面我们单开一篇来介绍，目前先了解下这些概念。通过不同的浏览器设置，我们可以实现一些有趣的功能，比如我们先通过 Playwright 做一些固定的操作，比如打开某个页面，然后再让 Browser Use 基于这个页面完成某个任务（这样可以省去打开页面这一步消耗的 token）：async with async_playwright() as p: # 手动打开页面 browser = await p.chromium.la…

再学 Browser Use 的工具使用
type: item
date: 2025-06-11T12:15:00+00:00
description: 昨天我们学习了 Browser Use 是如何利用大模型的结构化输出能力实现工具调用的，通过 AgentOutput 模式定义与动态的 ActionModel 的结合，实现了智能体在执行网页任务时灵活选择和使用不同浏览器工具。今天我们将继续探讨浏览器操作的具体实现以及如何自定义工具，以扩展 Browser Use 的功能。工具调用流程现在我们再次回顾下 Browser Use 智能体循环中的 step() 方法，调用大模型得到下一步动作后，接着通过 multi_act() 方法对每一个动作进行执行：model_output = await self.get_next_action(input_messages) result: list[ActionResult] = await self.multi_act(model_output.action)接着通过 controller.act() -> registry.execute_action() 等方法，最后从 registry.actions 数组中找到对应的动作：action = self.registry.actions[action_name] return await action.function(params=validated_params, **special_context)这里的 registry.actions 表示 Browser Use 支持的所有工具，那么这个数组是怎么来的呢？我们可以在 Controller 的初始化函数中找到答案：截图中是 go_to_url 的实现，注意函数上有一个 @self.registry.action 装饰器，这个装饰器的作用就是将这个函数实现添加到 registry.actions 数组中。内置浏览器动作Controller 是 Browser Use 工具调用的核心，这个类定义在 browser_use/controller/service.py 文件中，除了上面截图中的 go_to_url 动作，Browser Use 一共内置了 20 个操作浏览器的动作，如 open_tab、scroll_down、extract_content 等，我将其整理成表格如下：Action 名称描述（中文）done完成任务 - 返回文本，并指明任务是否完成（success=True 表示已完成，否则未完全完成）search_google在 Google 中搜索查询，查询应像人类在 Google 搜索时一样具体，不要太模糊或太长go_to_url在当前标签页导航到指定 URLgo_back后退wait等待指定秒数，默认 3 秒click_element_by_index通过索引点击元素input_text向输入交互元素输入文本save_pdf将当前页面保存为 PDF 文件switch_tab切换标签页open_tab在新标签页打开指定 URLclose_tab关闭已有标签页extract_content提取页面内容以获取特定信息，例如所有公司名、特定描述、所有关于 xyc 的信息、带结构的公司链接等get_ax_tree获取页面的可访问性树，格式为“role name”，返回指定数量的元素scroll_down页面向下滚动指定像素数，未指定则滚动一页scroll_up页面向上滚动指定像素数，未指定则滚动一页send_keys发送特殊按键字符串，如 Escape、Backspace、Insert、PageDown、Delete、Enter，支持快捷键组合scroll_to_text如果找不到想要交互的内容，则滚动到该文本位置get_dropdown_options获取原生下拉框的所有选项select_dropdown_option通过选项文本为交互元素选择下拉选项drag_drop拖放页面上的元素或坐标，适用于画布绘图、可排序列表、滑块、文件上传和 UI 重排等另外还内置了 6 个操作 Google Sheets 的动作，这些动作仅对 https://docs.google.com 域名生效：Action 名称描述（中文）read_sheet_contents获取整个工作表的内容read_cell_contents获取一个单元格或单元格范围的内容update_cell_contents更新一个单元格或单元格范围的内容clear_cell_contents清除当前选定的任意单元格select_cell_or_range选择特定的单元格或单元格范围fallback_input_into_single_selected_cell备用方法在（仅一个）当前选定的单元格中输入文本Playwright 介绍分析上面内置的 20 个浏览器动作源码…

学习 Browser Use 的工具使用
type: item
date: 2025-06-10T12:14:00+00:00
description: 我们已经学习了 Browser Use 的 “任务规划” 和 “记忆管理”，通过剖析相关代码，相信大家对 Browser Use 的实现原理已经有了基本认识。今天我们将关注智能体三大核心组件中的 “工具使用”，学习 Browser Use 是如何使用工具的。正如 Browser Use 的名字所示，它最重要的工具就是浏览器，通过各种浏览器操作，例如导航、滚动、点击、输入文本等，实现网页任务自动化和智能化；除此之外，Browser Use 也支持用户自定义工具，例如保存文件、访问数据库、发送通知、接收人类输入等，实现更丰富的智能体功能。AgentOutput 模式通过前面的学习，我们知道 Browser Use 通过 消息管理器 将系统提示词、用户任务、历史操作记录、当前浏览器状态以及上一步动作的执行结果等信息，组装成大模型的输入参数。调用大模型后，得到结构化的结果，类似于下面这个样子：{ "current_state": { "evaluation_previous_goal": "we did ok, team", "memory": "filled in xyz into page, still need to do xyz...", "next_goal": "click on the link at index 127, then open that new tab" }, "action": [ { "click_element_by_index": { "index": 127 } }, { "switch_to_tab": { "page_id": 3 } } ] }这个结构化的结果就是 AgentOutput 模式，定义如下：class AgentOutput(BaseModel): model_config = ConfigDict(arbitrary_types_allowed=True) current_state: AgentBrain action: list[ActionModel] = Field( ..., description='List of actions to execute', json_schema_extra={'min_items': 1}, # Ensure at least one action is provided )很明显，这是一个 Pydantic 模式。很多地方把 Pydantic 的 Model 翻译成 “模型”，但是为避免和大模型混淆，我统一翻译成 “模式”。其中第一行的 model_config 是模式配置，arbitrary_types_allowed=True 表示模式中可以包含任意类型的字段，比如自定义类、第三方库的对象等。如果不设置为 True，Pydantic 默认只允许标准类型和已注册的类型。下面的 current_state 和 action 是 AgentOutput 模式的两个字段，current_state 对应 AgentBrain 模式：class AgentBrain(BaseModel): evaluation_previous_goal: str memory: str next_goal: str表示当前的状态信息，以及前一个目标的回顾和下一个目标的展望。action 对应 ActionModel 模式：class ActionModel(BaseModel): model_config = ConfigDict(arbitrary_types_allowed=True)表示下一步要执行的动作，这是一个动态模式，因为每个动作的名称和参数都是不一样的。值得一提的是，参数 action 后面的 Field(...) 是 Pydantic 的特殊语法，这个不是省略的意思，而是表示该参数是必填的。不仅必填，后面的 {'min_items': 1} 还规定该列表至少包含一项。Pydantic 模式和结构化输出在大多数场景下，大模型都是直接用自然语言回应用户的，但是有一些特殊场景，我们需要模型以结构化格式输出，比如我们希望将模型输出存储在数据库中，并确保输出符合数据库模式。这就是 结构化输出（Structured outputs） 功能：结构化输出有两个要点：模式定义：指示模型输出格式结构化输出：模型返回符合该模式的输出关于第一点，我们可以直接以 JSON 方式定义，或者使用 JSON Schema 方式定义，但是更常见的做法是使用 Pydantic 库，Pydantic 是一个现代的 Python 数据验证库，使用 Python 类型提示来定义数据模式并自动进行数据验证、序列化和文档生成。Pydantic 特别适合定义结构化输出模式，下…

学习 Browser Use 的记忆管理
type: item
date: 2025-06-09T12:12:00+00:00
description: 昨天我们学习了 Browser Use 的任务规划，对相关的代码和提示词进行了简单的剖析，正如前面所提到的，智能体 = 规划（Planning） + 记忆（Memory） + 工具使用（Tool use），所以按顺序，我们今天继续来看下 Browser Use 是如何管理记忆的。消息管理器回顾下 Browser Use 智能体循环中的 step() 方法，我们通过 _message_manager 的 get_messages() 方法来组装大模型的输入：@time_execution_async('--step (agent)') async def step(self, step_info: AgentStepInfo | None = None) -> None: """Execute one step of the task""" input_messages = self._message_manager.get_messages() model_output = await self.get_next_action(input_messages) self.state.n_steps += 1 result: list[ActionResult] = await self.multi_act(model_output.action) if len(result) > 0 and result[-1].is_done: logger.info(f'📄 Result: {result[-1].extracted_content}') self.state.last_result = result_message_manager 被称为 消息管理器，其实也就是记忆管理器，里面存储了系统提示词、用户任务、运行过程中产生的历史消息，以及当前浏览器状态等等一系列的内容。Browser Use 就是通过它来存储和操作记忆的，是 Browser Use 记忆系统的核心。那么这些内容是如何添加到记忆中的呢？我们可以在 Agent 的 __init__ 方法中找到消息管理器的初始化代码：# Initialize message manager with state # Initial system prompt with all actions - will be updated during each step self._message_manager = MessageManager( task=task, system_message=SystemPrompt( action_description=self.unfiltered_actions, max_actions_per_step=self.settings.max_actions_per_step, override_system_message=override_system_message, extend_system_message=extend_system_message, ).get_system_message(), settings=MessageManagerSettings( max_input_tokens=self.settings.max_input_tokens, include_attributes=self.settings.include_attributes, message_context=self.settings.message_context, sensitive_data=sensitive_data, available_file_paths=self.settings.available_file_paths, ), state=self.state.message_manager_state, )这里是消息管理器的四个参数：task - 用户的任务；system_message - 系统提示词，用户可以通过 override_system_message 参数重写，或者通过 extend_system_message 往默认的提示词后面追加内容；默认的提示词中有一个参数 {max_actions} 用于控制大模型一次最多生成多少动作，可以通过 max_actions_per_step 参数配置；settings - 一些额外的配置参数，比如大模型的最大输入 token 数，消息上下文，敏感数据等；state - 主要用于存储和操作运行过程中产生的历史记录，维护当前的 token 数等；Browser Use 根据这四个参数构造初始记忆。看下 MessageManager 的 _init_messages() 方法：…