1.2 核心概念与分工:Agent、Browser 与 Controller 本节摘要:Browser-Use 的对象模型是一张指挥链:ChatLLM 是决策者,Agent 是参谋与调度,Browser 是战车,BrowserContext 是车厢里的作战环境(cookie、标签页、视口),Controller 是军械库(动作清单)。把这五者的"管与不管"摆正,是读懂后续所有代码的前提。 一处高频误会引出的问题 上一节的三件套代码里, 同时接收了 和 ,很多人由此推断"Agent 就是全部"。于是写出这样的困惑:想清个 cookie 找不到方法、想复用登录态不知道建在哪、想加个自己的动作不知道挂到谁身上。这些都是同一件事的症状——没分清指挥链上每一环的辖区。本节承接 1.
本节摘要:Browser-Use 的对象模型是一张指挥链:ChatLLM 是决策者,Agent 是参谋与调度,Browser 是战车,BrowserContext 是车厢里的作战环境(cookie、标签页、视口),Controller 是军械库(动作清单)。把这五者的"管与不管"摆正,是读懂后续所有代码的前提。
上一节的三件套代码里,Agent 同时接收了 llm 和 browser,很多人由此推断"Agent 就是全部"。于是写出这样的困惑:想清个 cookie 找不到方法、想复用登录态不知道建在哪、想加个自己的动作不知道挂到谁身上。这些都是同一件事的症状——没分清指挥链上每一环的辖区。本节承接 1.1 的分层图,把每个对象拆下来单独验货;下一节谈选型时,你会拿着这张编制表去对照"这些角色传统工具里谁在做"。
用命令台的比方说:ChatLLM 是司令(负责想),Agent 是参谋长(把司令的意图变成可执行的作战序列,管理战役节奏),Browser 是战车(一台真实浏览器进程),BrowserContext 是车厢(这趟任务里的环境配置:cookie、标签页、窗口尺寸),Controller 是军械库(登记了所有可用动作的清单,包括内置动作和你后面自定义的动作)。

对照到代码,管辖边界是这样落地的:
| 对象 | 管什么 | 不管什么 | 你最常问它的问题 |
|---|---|---|---|
| ChatLLM | 读页面简报、选下一步动作 | 执行、计时、容错 | 换哪个模型性价比高 |
| Agent | 组装情报、发动作、循环控制、产出结果 | 浏览器配置、动作注册 | 为什么它重复点同一个地方 |
| Browser | 浏览器进程生命周期、连接本机 Chrome | 页面内部状态 | 怎么省内存、怎么连真浏览器 |
| BrowserContext | cookie、标签页、视口、登录态 | 多浏览器进程隔离 | 登录态为什么丢了 |
| Controller | 内置与自定义动作的登记 | 何时调用动作(那是模型的事) | 怎么加我自己的动作 |
同样的三件套,这次按指挥链完整接线,注释标明每一环的辖区:
from browser_use import Agent, Browser, BrowserConfig, Controller from langchain_openai import ChatOpenAI # 军械库:先领一个默认装备齐全的 Controller controller = Controller() # 内置动作都已登记,后续可往上挂自定义动作 # 战车:进程级配置(无头与否、窗口大小)挂在 BrowserConfig 上 browser = Browser( config=BrowserConfig(headless=False) # 命令台调试期建议可见模式 ) # 司令:只管想,参数是温度、模型名这类"性格"设置 llm = ChatOpenAI(model="gpt-4o", temperature=0.1) # 越低越稳,操作任务别开高 # 参谋长:把上面三样接起来,并领作战目标 agent = Agent( task="打开示例站点,找到登录入口并停在登录页", llm=llm, browser=browser, controller=controller, # 不传也行,Agent 会自建一个默认军械库 ) result = agent.run(max_steps=15) # 节奏参数:最多十五拍,防绕圈
运行后留意输出里的层级感——先有情报行(页面状态摘要),后有决策行(模型选了什么动作),再是执行行(真实点击)。这个输出顺序就是指挥链的顺序。
第一处:Agent 与 Controller。动作"有哪些"是 Controller 的辖区,动作"什么时候被调用"是模型和 Agent 的辖区。你想禁用某个内置动作,去 Controller 找开关;你想让模型少绕路,调的是任务描述和 max_steps,不是 Controller。
第二处:Browser 与 BrowserContext。一台 Browser 可以开出多个 Context,就像一辆战车可以分出多个独立车厢——每个车厢有自己的 cookie 罐子,互不串味。要隔离多账号、要保登录态,都是 Context 层面的事。第 2 章第 3 节接管真实浏览器时,这条边界会反复用到。
验证理解的一个自测:如果老板要求"同一脚本里用两个账号同时巡检两个站点",你应该能立刻指出——一台 Browser、两个 BrowserContext、两个 Agent。答不出来就回上面那张表。
**坑一:配置挂错对象。**有人发现"温度调了没反应",排查半天发现他把参数传给了 Browser 的构造函数——温度是模型的性格,归 ChatLLM 管;窗口大小才是 Browser 的。装配期拿不准参数归谁,就回上面那张辖区表对号,不要靠猜。
**坑二:自建军械库却没挂上。**自定义动作注册在一个 Controller 上,但创建 Agent 时忘了传 controller 参数——Agent 会自建一个默认军械库,你的动作躺在没人领的仓库里,模型自然永远调不到。症状很典型:任务单里明说了要调的动作,日志里模型的动作清单里却没有它。遇到"模型看不见我的动作",第一反应查装配单。
# 自检脚本:三行确认装配是否挂对 print("同一个Controller?", agent.controller is controller) # 预期:True print("模型接上了?", agent.llm is not None) # 预期:True print("浏览器就绪?", browser is not None) # 预期:True
三行全 True,指挥链才算物理连通。把装配自检变成习惯,能把"跑不起来再回头查"的大额返工,压缩成十秒钟的例行确认——命令台交接班也要点名,道理相同。
概念表齐了。下一节换一个视角:把这些角色与传统工具里的对应物摆在一起比一比,判断什么活该派它上。