browser-use
一句话定位
browser-use 是一个 104k star 的开源自主浏览器操作 agent:通过 CDP(Chrome DevTools Protocol)直接驱动真实 Chromium,把「索引化的可交互 DOM 元素 + 截图」喂给通用 LLM,LLM 每步输出结构化 JSON(thinking / evaluation_previous_goal / memory / next_goal / action[]),逐动作执行。与 Anthropic computer-use 的核心分野在于它不是纯像素点击:给每个可交互元素编号 [index],动作用 click(index) 按元素定位,截图仅作 vision ground-truth 校验——因此对 vision 精度依赖低,甚至可在 use_vision=False 下靠纯 DOM 文本运行。它是单 agent 架构,配一条自研浏览器专用微调模型链路(bu-2-0)与闭源云侧(sync/skills/sandbox/微调)。本文所有源码引用基于 commit f78585575905b11692186783c770f5f3f2feeb9a。
核心架构总览(目录结构关键路径 + 引用的 commit)
分析基于 commit f78585575905b11692186783c770f5f3f2feeb9a(2026-07-09 11:17:12 -0700 Restructure README quickstart: CLI and Python library paths (#5176),git clone --depth 1 浅克隆)。纯 Python,browser_use/ 包约 65k 行。
关键路径:
browser_use/
agent/
service.py # Agent 主类(4144 行):run/step 主循环、multi_act、judge、pause/resume、rerun
prompts.py # SystemPrompt 模板选择 + AgentMessagePrompt(每步 user message 组装)
views.py # AgentSettings、AgentOutput schema、ActionResult
judge.py # LLM-as-judge trace 评估(225 行)
system_prompts/system_prompt.md # 默认 system prompt(另有 8 个变体)
message_manager/service.py # 上下文/记忆管理、压缩、sensitive data 过滤(597 行)
tools/
service.py # Tools 类:26 个内置 action + act() dispatch(2313 行)
registry/service.py # Registry:@action 装饰器、动态 param model、execute_action(611 行)
skills/service.py # 云端 hosted skills 拉取/执行(285 行)
sandbox/sandbox.py # @sandbox 装饰器,cloudpickle 远程执行(669 行)
mcp/{server,client,controller}.py # MCP 双角色(server 1287 行)
sync/service.py + telemetry/service.py # 云 sync + PostHog 遥测
browser/watchdogs/security_watchdog.py # allowed_domains 导航拦截
browser/profile.py # allowed/prohibited_domains、block_ip_addresses 配置
llm/ # 15+ provider 统一 BaseChatModel;llm/browser_use/ 为自研 bu-2-0
dom/serializer/ + dom/views.py # CDP DOM 快照 → 带 [index] 的 XML 文本(llm_representation)
skills/ # 顶层:给编码 agent 用的 Anthropic-style Skill 文档(≠运行时能力)
另有 browser_use/beta/service.py(并行的新版 agent 实现,复用同一 judge/message_manager);一手文档还含仓库根 AGENTS.md(38KB)、CLAUDE.md(11KB)、CLOUD.md(75KB)。
Agent Loop(主循环 / 何时继续何时停)
入口 Agent.run(max_steps=500)(agent/service.py:2493),while self.state.n_steps <= max_steps(:2590)逐步调 _execute_step → step()。
单步 step()(service.py:1027)三阶段:
- Phase 0 captcha 等待(
:1038,captcha 由 watchdog 自动解)。 - Phase 1
_prepare_context(:1079):取 browser state(DOM + 截图)、更新 page-specific action models、message_manager 组装 state message、注入各种 nudge(loop 检测 / replan / exploration)。 - Phase 2
_get_next_action(LLM 调用,带llm_timeout超时,:1167)→_execute_actions→multi_act。 - Phase 3
_post_process(下载检查、loop 检测、失败计数)。
何时停(:2600 一带):
- LLM 主动调
doneaction(is_done=True)→ break。 consecutive_failures >= max_failures(默认 5) + int(final_response_after_failure)(1),即连续失败达阈值(:2600,阈值计算见:1289 max_total_failures)。state.stopped(外部 stop)。- 达到
max_steps(追加一条 error history)。
强制收尾:_force_done_after_last_step(:1560)在最后一步把可用工具限制为仅 done(切换 self.AgentOutput = self.DoneAgentOutput);_force_done_after_failure(:1571,逻辑在 :1574)失败达上限后同样强制 done 做「最后一次回复」(msg = 'You failed N times. Therefore we terminate the agent.')。
单步内多动作 / 批处理:multi_act(:2720)一步可执行多个 action,但有两层 page-change guard(源码注释在 :2724)——(1) 静态标记 terminates_sequence=True(navigate / search / go_back / switch),执行后跳过队列剩余动作(判定在 :2806);(2) 运行时对比动作前后 URL + focus target,变了就中断剩余。done 只允许作为单动作。
失败恢复:_handle_step_error(:1250)区分 InterruptedError / 连接类错误(尝试 reconnect,:1261)/ 普通错误(记为 ActionResult(error) 并 consecutive_failures += 1,:1291);成功一步则清零(:1232-1234)。
记忆与上下文管理(压缩、长期记忆、会话持久化)
核心设计不是无限追加消息列表。每步 message_manager 重建 单条 system message + 单条 state message + 若干 context message(message_manager/service.py 的 _set_message_with_type / get_messages)。历史以文本描述形式塞进 state message 的 <agent_history>,而非多轮对话累积。
agent_history_items:每步一个HistoryItem(含eval_previous_goal / memory / next_goal / action_results),agent_history_description(:150)拼成文本;超过max_history_items时保留首项 +[... N previous steps omitted ...]+ 最近 N-1 项(:162-186)。- 压缩:
maybe_compact_messages(:213)双闸门触发——step 间隔compact_every_n_steps+ 字符下限trigger_char_count(默认 40000)。用一个 compaction LLM(可单配,默认page_extraction_llm或主 llm)把旧历史总结成<compacted_memory>块,保留首项 + 最近keep_last_items项。压缩 prompt 强调「只有见到显式成功确认才标 completed,否则标 IN-PROGRESS,禁止推断完成」(:259-267);压缩记忆在 prompt 里带免责注释「treat as unverified」(:155-160)。 - 模型自管上下文(LLM 主动记忆):Agent 持有一个持久
FileSystem(browser_use/filesystem/file_system.py),system prompt 引导模型用todo.md(checklist)、results.md累积结果;write_file/read_file/replace_file都是 action。这是「让模型自己决定什么留在 context」的显式机制(system prompt<file_system>段 + AGENTS.md 强调)。 - read_state:
extract/read_file的一次性输出放<read_state>,只在当前步展示,图片放read_state_images(:313-330)。 - 只带当前截图:默认不堆叠历史截图,
create_state_messages只放当前步截图(use_vision=True时),历史步靠文本(:446-472)。 - 会话持久化 / 恢复:
AgentState/MessageManagerState可序列化;save_history/load_and_rerun(:3862,:3892);add_new_task(:188)支持在已有会话上追加 follow-up 任务(包成<follow_up_user_request>)。跨 run 的长期经验库不存在(记忆只在单 run 内)。
工具体系(定义/调用协议/注册/权限)
注册:Registry.action(description, param_model=None, domains=None, terminates_sequence=False) 装饰器(tools/registry/service.py:291)。_normalize_action_function_signature(:75)把任意签名规范化,区分「action 业务参数」(自动生成或显式 pydantic param_model)与「特殊注入参数」(browser_session / cdp_client / page_extraction_llm / file_system / available_file_paths / has_sensitive_data / page_url / extraction_schema,见 _get_special_param_types :57)。用户可注册任意 Python 函数为 action。
调用协议:LLM 用结构化输出返回 action: [{tool_name: {params}}]。create_action_model(:517)把所有已注册 action 拼成一个 pydantic Union schema 塞给 LLM 的 structured output / tool calling。Tools.act(tools/service.py:2164)按 model_dump(exclude_unset=True) 取 action 名 + params → registry.execute_action(:331)→ pydantic 校验 → 注入特殊 context → 调用。每 action 有 action_timeout(默认 180s,可用 BROWSER_USE_ACTION_TIMEOUT_S 调)。
26 个内置 action(tools/service.py,按 @self.registry.action 顺序):search、navigate、go_back、wait、input、upload_file、switch(tab)、close(tab)、extract(LLM 抽取整页)、search_page、find_elements(CSS)、scroll、send_keys、find_text、screenshot、save_as_pdf、dropdown_options、select_dropdown、write_file、replace_file、read_file、evaluate(任意 JS)、done(thinking / no-thinking 两版)、click(两版)。
权限 / 过滤:action 可声明 domains(allowed_domains 别名),get_prompt_description(page_url) 按当前 URL 过滤出「page-specific actions」,只在匹配页面暴露给 LLM(_prepare_context 用之);exclude_actions 可禁用 action。
结果类型:统一 ActionResult(extracted_content / long_term_memory / error / is_done / success / attachments / include_extracted_content_only_once / images / metadata)。
Prompt 设计(系统提示结构、动态组装)
system prompt 9 个变体(agent/system_prompts/),由 SystemPrompt._load_prompt_template(prompts.py:60)按条件选:is_browser_use_model(用简化版 system_prompt_browser_use*.md,专给微调模型)、flash_mode(精简)、is_anthropic / Anthropic 4.5(需 ≥4096 token 命中 caching,_is_anthropic_4_5_model :17)、use_thinking。支持 override_system_message / extend_system_message;system message 带 cache=True。
默认 system_prompt.md 段落结构:<intro> <language_settings> <input> <user_request> <agent_history> <browser_state>(详述 [index]<tag/> XML 格式 + *[ 表新元素 + |SCROLL|/|SHADOW| 前缀)<browser_vision>(声明截图是 ground truth)<browser_rules> <file_system> <planning> <task_completion_rules>(含 <pre_done_verification> 6 步自检)<action_rules> <efficiency_guidelines>(动作分类:page-changing 必须放最后)<reasoning_rules> <examples> <output>(严格 JSON schema)<critical_reminders> <error_recovery>。
动态每步 user message(AgentMessagePrompt.get_user_message prompts.py:391)拼装顺序:<user_request> + <agent_history> + <agent_state>(file_system describe + todo_contents + plan + sensitive_data + available_file_paths)+ <browser_state>(page_stats + tabs + page_info「N pages above/below」+ 索引化交互元素文本 llm_representation + [Start/End of page] 标记)+ <read_state> + <page_specific_actions> + <step_info>(step 计数 + 日期,故意放末尾让前缀可缓存)。截图作为 ContentPartImageParam 附在文本后,带 vision_detail_level;整条 user message 也 cache=True。
输出 schema:AgentOutput(views.py:382)字段 thinking / evaluation_previous_goal / memory / next_goal / current_plan_item(opt) / plan_update(opt) / action[]。flash_mode 去掉 thinking + eval + next_goal(type_with_custom_actions_flash_mode :458)。
Router / 编排(任务分解、多 agent、子 agent)
单 agent 架构,无内建多 agent / 子 agent orchestration(grep subagent|orchestrat|delegate|multi.?agent 在 browser_use/ 无实现命中)。
任务分解靠单 agent 内的轻量 planning:system prompt <planning> 段引导模型输出 plan_update(3-10 个 todo item)+ current_plan_item 指针;plan 状态标记 [x]/[>]/[ ]/[-] 回注 <plan>(_render_plan_description / _update_plan_from_model_output)。这是「模型自己在 context 里维护 todo」,不是代码层多 agent。
子任务并行 / 多 agent 编排属于 Browser Use Cloud(CLOUD.md 里的 subagent guide skills/cloud/references/guides/subagent.md),开源库本体不含。
Skill / 插件体系
两套「skill」概念,别混淆:
- 顶层
skills/(browser-use / cloud / open-source / qa / remote-browser / x402,每个含 SKILL.md)——这是给**编码 agent(如 Claude Code)**用 browser-use 的 Anthropic-style Skill 文档,不是 agent 自身运行时能力。 browser_use/skills/(运行时 SkillService)——从 Browser Use 云 API 拉取 hosted skills(browser_use_sdk),skill_ids=['*']或指定 id。Agent._register_skills_as_actions(service.py:828)在 run 开始时把每个 skill 动态注册成一个 agent action(slug 作 action 名,skill.parameters_pydantic作 param model),handler 调SkillService.execute_skill(带 browser cookies)。skill 缺 cookie 时_get_unavailable_skills_info(:916)把「不可用 skill + 需要哪些 cookie」注入 prompt 提示模型。
插件扩展:主要靠 Tools / Registry.action 自定义 action(用户注册任意 Python 函数)+ MCP(见「沙箱与执行隔离」旁述,mcp/ 双角色:既作 MCP server 暴露 browser-use,也作 MCP client 接外部工具)。无独立 plugin 加载框架。
自进化能力(自我改进 / 学习型记忆 / eval 驱动纠错)
无训练层自进化 / 跨会话学习记忆(memory 仅限单 run 内 FileSystem + compacted_memory,不跨 run 沉淀经验库)。
eval 驱动(离线 / 事后):judge.py 的 construct_judge_messages 是 LLM-as-judge,Agent._judge_trace(service.py:1585)/ _judge_and_log(:1620)在 done 后对整条 trace(task + final_result + agent_steps + 最多 10 张截图 + 可选 ground_truth)打 verdict(true/false) + impossible_task + reached_captcha。关键设计:judge 结果不覆盖 agent 自报 success,两者都进遥测供 eval 平台对比(注释 :1621-1625)。这是评测,不是在线自纠错。
在线纠错在 prompt / loop 层:<pre_done_verification> 自检、consecutive_failures 计数、loop / replan / exploration nudge、evaluation_previous_goal 强制每步判定上一步成败(截图为 ground truth)。
结论:eval 基础设施完备(judge + ground_truth + 双写遥测),但没有把 trajectory 反哺进模型 / 记忆的开源闭环(那部分在云侧微调,见下)。
可观测性(日志 / trace 格式)
- 本地日志:大量 emoji 结构化 logger(step / action 彩色打印,
_log_action:2840);save_conversation_path(:169,:1718)把每步「input messages + model output」落盘。 - Laminar (lmnr) tracing:
browser_use/observability.py提供@observe/@observe_debug装饰器,未装 lmnr 则 no-op;Tools.act给每个 action 开 Laminar span(span_type='TOOL',tools/service.py:2189)。 - 事件总线(bubus EventBus):run 中 dispatch
CreateAgentSessionEvent/CreateAgentTaskEvent/CreateAgentStepEvent/UpdateAgentTaskEvent/CreateAgentOutputFileEvent(cloud_events.py)。 - 云 sync:
sync/service.py的CloudSync把上述 event POST 到 Browser Use cloud(需 device auth,sync/auth.py),CONFIG.BROWSER_USE_CLOUD_SYNC控制。 - 匿名遥测:
telemetry/service.py的ProductTelemetry→ PostHog(phc_...,eu.i.posthog.com),匿名 device_id。 - 产物:
generate_gif(:2694)把整条 history 渲成agent_history.gif;token 用量走token_cost_service.get_usage_summary。
安全与权限(审批门、密钥管理)
- 无交互式人工审批门(no human-in-the-loop approval gate):动作直接执行,靠 domain 白名单而非逐步确认(对比 Claude Code 的 permission prompt——browser-use 没有)。
- 域名 gating:
SecurityWatchdog(browser/watchdogs/security_watchdog.py)拦截导航——_is_url_allowed(:176)对照browser_profile.allowed_domains/prohibited_domains/block_ip_addresses(profile.py:617)。被拦截的导航重定向到 about:blank(:60-69),或对显式 navigate action 抛 ValueError;支持 glob(会 warn)。 - 敏感数据:
sensitive_data({domain: {key: value}}或{key: value})。LLM 只见占位符名,用<secret>name</secret>标签;Registry._replace_sensitive_data(:427)在执行时按当前 URL 域匹配才替换真值(match_url_with_domain_pattern),且只对inputaction 暴露(execute_action:378)。2FA:占位符后缀bu_2fa_code时用pyotp.TOTP现算验证码(:474)。发往 LLM 的 state message 反向_filter_sensitive_data(message_manager:573)把真值 redact 回占位符。 - 其它 watchdog 安全面:permissions_watchdog、crash_watchdog、popups_watchdog(自动关 JS dialog)、captcha_watchdog(自动等 captcha)。
- 密钥:API key 走环境变量(
.env.example、各 llm provider);BROWSER_USE_API_KEY给 SkillService / cloud。
沙箱与执行隔离
- 本地:默认在本机启动 / 连接真实 Chromium(
browser/chrome.py、local_browser_watchdog),通过 CDP over WebSocket。不是进程级沙箱——就是普通子进程 Chromium,隔离靠 browser profile(独立 user data dir / storage_state)。 - 远程沙箱(云):
sandbox/sandbox.py的@sandbox装饰器(:215)——用cloudpickle序列化被装饰函数 + 其引用的 imports(_get_imports_used_in_function:65,AST 去装饰器:50),POST 到远程 sandbox 服务,SSE 流式回传 log / result / browser-created 事件(views.py SSEEvent)。即「把一段 browser 自动化代码整体丢到云端隔离沙箱里跑」,是 Browser Use Cloud 的隔离执行路径,非本地默认。 - Docker:仓库带
Dockerfile/Dockerfile.fast/docker/,容器化部署(非 per-task 沙箱)。
与模型的协同设计
- 通用模型优先:
browser_use/llm/有 15+ provider(anthropic / openai / google / groq / aws / azure / deepseek / mistral / ollama / openrouter / cerebras / vercel / litellm / oci …),统一BaseChatModel+ structured output。 - 自研微调模型
ChatBrowserUse(llm/browser_use/chat.py):默认 modelbu-2-0,走 Browser Use cloud API,「optimized models and prompts for browser automation」。配套system_prompt_browser_use*.md(简化 prompt)+request_type('agent'/'judge',见service.py:1606-1608:仅 ChatBrowserUse 传该参,其它 provider 不支持)+session_id。→ 一条「自研浏览器专用模型 + 专用简化 prompt + 服务端优化」的协同链路。 - prompt / 模型适配:按 provider 切 system prompt 变体(Anthropic caching 需 4096 token;flash_mode 精简;no_thinking 变体给不支持 / 不需要 reasoning 的模型);截图 vision detail、
llm_screenshot_sizeresize、include_tool_call_examples均可按模型调。 - DOM→模型接口:核心协同是「索引化可交互元素」——
dom/serializer/把 CDP DOM 快照简化成带[index]的 XML 文本(dom/views.py的llm_representation),截图上叠 bounding box + index 标号(browser/python_highlights.py),让模型用 index 而非坐标操作,大幅降低对 vision 精度依赖(与 computer-use 纯坐标点击的关键分野)。
轨迹利用(session/trajectory 是否反哺训练/评测)
- 评测(明确):trajectory 直接喂 judge;ground_truth 支持监督式评测;judge verdict + 自报 success 双写遥测供 eval 平台对比。
- 训练反哺(推断,闭源不可见):开源库本体不含训练代码;但轨迹经 CloudSync 上传(
CreateAgentStepEvent含每步 model output + 截图),配合自研bu-2-0,强烈暗示服务端用采集轨迹微调浏览器专用模型(request_type='agent'、system_prompt_browser_use.md面向 fine-tuned 模型佐证),但该训练闭环在闭源云侧,仓库不可见。 - rerun / 复用:
rerun_history(service.py:3093)/load_and_rerun(:3862)可重放历史动作序列(AI step 回退用get_ai_step_system_prompt),用于确定性回归 / 复现,属轨迹复用的一种。
与同类 harness 的关键差异(1-3 条)
- 元素索引 vs 像素坐标:给每个可交互元素编号
[index],动作click(index)按元素定位,截图仅作 ground-truth;对 vision 精度依赖低、更稳,可在use_vision=False下靠纯 DOM 文本运行。而 Anthropic computer-use / 通用桌面 agent 输出屏幕坐标点击。 - CDP 全页语义 vs 纯截屏:走 CDP 能读整页 DOM/HTML、执行任意 JS(
evaluate)、CSS 选择器(find_elements)、结构化extract、直接读 shadow DOM/iframe——信息比像素截图丰富得多。 - 浏览器专属生态 + 自研模型链路:tab / download / pdf / captcha / cookie / 域名白名单等浏览器专属 watchdog 与 action,配自研
bu-2-0微调模型 + 云执行 / 隔离沙箱 / hosted skills,是同类 GUI agent 中少见的「开源库 + 闭源云 + 专用模型」三段式。
原始源码定位
- repo: https://github.com/browser-use/browser-use
- commit/version analyzed:
f78585575905b11692186783c770f5f3f2feeb9a(2026-07-09,--depth 1浅克隆,克隆日期 2026-07-11) - 关键文件列表(相对仓库根):
browser_use/agent/service.py(4144 行)browser_use/agent/prompts.py(588 行)browser_use/agent/system_prompts/system_prompt.md(+ 8 个变体)browser_use/agent/message_manager/service.py(597 行)browser_use/agent/views.py(1000 行)browser_use/agent/judge.py(225 行)browser_use/tools/service.py(2313 行,26 个 action)browser_use/tools/registry/service.py(611 行)browser_use/skills/service.py(285 行)browser_use/sandbox/sandbox.py(669 行)browser_use/mcp/{server.py(1287),client.py(548),controller.py(264)}browser_use/sync/service.py(161)+browser_use/telemetry/service.py(141)browser_use/browser/watchdogs/security_watchdog.py、browser_use/browser/profile.pybrowser_use/llm/browser_use/chat.py(自研 bu-2-0)、browser_use/dom/serializer/+browser_use/dom/views.py- 仓库根文档:
AGENTS.md、CLAUDE.md、CLOUD.md
一手源存档(sources/)
保存于 /Users/zhao/projects/self-wiki/ai-research/sources/harness/browser-use/:
NOTES.md— 第一阶段源码级调研笔记(本 dossier 唯一输入)service.py(Agent 主循环 / multi_act / judge,163KB)prompts.pytools_service.py(26 个 action,92KB)registry_service.pymessage_manager_service.pysystem_prompt.md(默认 system prompt)judge.pyskills_service.pysandbox.pymcp_server.py