本节摘要:本节讲 browser-use 的四个定制面与一条版本纪律。自定义动作(Controller 机制):给智能体增加「浏览器动作之外」的能力——写文件、调内部接口、弹出人工确认门(2.2 节确认门的完整语法在此展开);系统提示定制:什么时候该改系统提示(领域约束、输出格式),什么时候不该动(默认提示承载了大量循环纪律);模型选择:主模型与备用模型的取舍维度(结构化输出可靠性、延迟、成本、上下文长度),不推荐唯参数论;浏览器会话选项:headless、窗口尺寸、会话复用,以及 stealth 选项只点到为止——其合规语境归第 8 章。最后一节是版本纪律:browser-use 迭代接近日更,历史上经历过 3.x 到 0.x 的重构式换代,版本号回退正是重构痕迹;给出锁定、升级、示例免责的三段纪律。本章示例均为写法示意,参数名以官方文档为准。
Agent 循环默认的动作空间是浏览器动作(点击、填写、导航、滚动)。Controller 机制允许注册浏览器之外的动作:写文件、查数据库、调内部接口、请求人工确认——每个自定义动作注册后进入模型的动作空间,模型按需调用。语法三件套:装饰器注册(带一句功能描述,模型靠它决定何时调用)、类型化参数(模型按签名传参)、ActionResult 返回(内容回灌进历史,模型下一步能看见):
# custom_actions.py —— 自定义动作:确认门与结果落盘(写法示意,以官方文档为准) import asyncio from browser_use import ActionResult, Agent, Controller from langchain_openai import ChatOpenAI controller = Controller() @controller.action("高危操作前的人工确认,用户拒绝则不得继续提交") def confirm_dangerous(reason: str) -> ActionResult: answer = input(f"是否允许执行该操作?原因:{reason} [y/N] ") allowed = answer.strip().lower() == "y" return ActionResult(extracted_content=f"人工{'允许' if allowed else '拒绝'}:{reason}") @controller.action("把文本结果追加写入本地文件") def save_result(text: str, filename: str = "out.txt") -> ActionResult: with open(filename, "a", encoding="utf-8") as f: f.write(text + "\n") return ActionResult(extracted_content=f"已写入 {filename}") async def main() -> None: agent = Agent( task=( "打开 http://127.0.0.1:8080/demo_todo.html,抽取全部待办文本;" "调用高危确认说明即将保存结果,确认通过后把待办写入 out.txt," "最后报告写入结果。" ), llm=ChatOpenAI(model="gpt-4o"), controller=controller, ) result = await agent.run() print(result.final_result()) asyncio.run(main())
三条设计要领:描述写给模型看——「用户拒绝则不得继续提交」这句约束会被模型读到并遵守,动作描述是软策略的载体;动作要幂等或可说明——save_result 重复调用会重复追加,生产实现应在描述里写明或内部去重;出口即闸门——任何不想让模型直接做的事(花钱、发请求、改数据),都可以收进带确认的自定义动作里,比试图用任务文本约束模型可靠得多。
系统提示是循环的「宪法」:模型如何理解任务、遵循什么格式、什么时候自报完成,都由它规定。browser-use 允许替换或关闭默认系统提示,但先想清楚要改什么:
| 场景 | 建议 |
|---|---|
| 领域约束(只操作某区域、语言偏好) | 优先写进 task 文本,不动系统提示 |
| 输出格式(结果必须是 JSON、必须附来源) | 可定制系统提示,或在循环外做后处理 |
| 循环纪律、动作格式、终止语义 | 不要动——默认提示承载这些,改坏的症状是循环失控 |
经验法则:任务特性进 task,行为契约才进系统提示。默认系统提示是框架与模型之间调试了无数轮的产物,盲目重写相当于拆掉出厂调校。确实要定制时,从默认提示出发做增量修改(复制后增删段落),并准备一组回归任务对比改前改后的行为——回归任务集的做法见第 6 章。
browser-use 通过 langchain 生态接入多种模型。选择维度四个,按重要性排序:
| 维度 | 为什么重要 | 观察方法 |
|---|---|---|
| 结构化输出可靠性 | 动作是结构化的,格式错误等于循环卡死 | 用同一组靶场任务对比格式错误率 |
| 延迟 | 循环串行,每轮延迟直接乘以步数 | 靶场任务计时 |
| 成本 | 同上,乘法关系 | 计费面板或 token 统计 |
| 上下文长度 | 决定长任务的压缩压力 | 长任务对比完成率 |
两条实践:主备搭配——主模型跑日常,备用模型在主模型超时或格式连续失败时接管(第 6 章的重试策略会给出切换点设计);小模型先试——不少「简单页面加短任务」的场景,中小模型就够,成本差一个量级,先用靶场任务实测再定,不唯参数论。模型切换后必须重跑回归任务集:不同模型对同一系统提示的服从度不同,这属于第 11 章生产化的「模型变更流程」。
常用会话配置集中在浏览器会话对象上(构造参数随版本有变,以官方文档为准):运行形态(headless 无头还是有头——调试期建议有头,肉眼看着循环转,问题减半)、窗口尺寸(部分页面按宽度渲染不同布局,固定尺寸让感知产物可复现)、会话复用(复用已登录的浏览器上下文,避免每次重新登录——登录态管理的完整话题在第 7 章)。配置形态示意:
# session_options.py —— 常用会话选项(写法示意,参数以官方文档为准) import asyncio from browser_use import Agent, Browser, BrowserConfig from langchain_openai import ChatOpenAI async def main() -> None: config = BrowserConfig( headless=False, # 调试期建议有头,肉眼看着循环转 viewport={"width": 1280, "height": 800}, # 固定视口,感知可复现 ) agent = Agent( task="打开 http://127.0.0.1:8080/demo_todo.html 并报告待办条数。", llm=ChatOpenAI(model="gpt-4o"), browser=Browser(config=config), ) result = await agent.run() print(result.final_result()) asyncio.run(main())
一段顺手的调试经验:会话选项里最容易被忽视的是窗口尺寸——同一页面在窄窗口下折叠菜单、隐藏元素,感知清单随之变化,你以为的「模型行为不稳定」,有时只是两次运行的视口不同。这也是第 5.1 节视觉定位「固定视口」纪律的同源问题:先让页面长得一样,再谈行为一致。
一类选项本书刻意点到为止:stealth(隐身伪装)类选项,涉及指纹与身份呈现的修改,其技术细节与合规讨论统一归第 8 章《反检测与合规边界》。这里只立一条原则:默认以真实身份、可被识别的方式访问,stealth 只在你拥有或获得明确授权的站点上有讨论余地。
browser-use 的迭代速度在开源圈名列前茅(写作口径 2026-10:v0.13.13,2026-10-15 发布,接近日更),且历史上经历过 3.x 到 0.x 的重构式换代——版本号大步回退正是推倒重来的痕迹。这对使用者意味着:任何教程(包括本书)的示例代码都有保鲜期。三段纪律:
| 阶段 | 动作 |
|---|---|
| 锁定 | 依赖文件写死版本号(browser-use==0.13.13 形态);提交锁文件;不在生产环境追新 |
| 升级 | 先读官方更新日志(重点看重构与弃用条目);在隔离环境跑回归任务集(第 6 章);通过后再换版本 |
| 免责 | 示例代码标「写法示意」;参数名、导入路径、类名以官方文档为准;给团队留「官方文档对账」的升级清单 |
一个诚实的判据:当你发现书里的示例与官方文档冲突时,信官方文档——这不是客套,而是本书对快迭代依赖的正确姿态。值得学的从来不是某个参数拼法,而是循环结构(2.1)、信任边界(2.2)与定制思路(本节)这些慢变量;API 是方言,结构是语言。
browser-use 把「全自主循环」推到了极致;但第 1.3 节的对照表早就提示了另一条路——绝大多数生产任务是「稳定流程加少量不确定步骤」。下一章讲 Stagehand 的相反哲学:代码优先,Agent 只做兜底。