当 AI Agent 学会"边跑边修"
2026 年,AI Agent 的浏览器操控赛道已经卷成了红海——Browser Use、Agent-E、WebVoyager 各显神通。但一个来自 browser-use 团队的开源项目,用不到 600 行 Python 代码杀出重围:Browser Harness。
截至 2026 年 8 月,这个项目在 GitHub 上已斩获 17,100+ Star,成为浏览器 Agent 领域增长最快的项目之一。它的核心理念只有一句话:把 LLM 直接连到 Chrome 的 CDP 端口,缺什么函数让 AI 自己写。
这不是又一个"封装 Playwright"的中间层框架。Browser Harness 的设计哲学是极简主义——没有选择器引擎,没有页面模型,没有预定义的工作流。它只提供一组最小化的 CDP 辅助函数,剩下的交给 LLM 在运行时动态生成。
更惊人的是它的自修复能力:当 Agent 遇到框架没有覆盖的操作时,它不会报错退出,而是自己编写一个新的 helper 函数,保存到本地工作区,下次直接复用。框架越用越强,这就是"自修复"的含义。
与 Playwright/Puppeteer 的本质区别
很多人会问:这不就是 Playwright 的 Python 封装吗?答案是否定的。
Playwright 和 Puppeteer 是传统自动化框架。它们的设计目标是"人类编写脚本控制浏览器",提供了丰富的选择器引擎(CSS、XPath、text)、页面模型、等待机制和断言库。你需要预先知道要点击什么元素、填写什么表单、等待什么条件。
Browser Harness 是 AI 原生框架。它假设控制浏览器的不是人类脚本,而是 LLM。因此它: - 不依赖选择器,而是通过 CDP 直接操作坐标和 DOM - 不提供高级等待机制,而是让 LLM 自己判断何时页面就绪 - 不预定义工作流,而是让 LLM 根据当前页面状态决定下一步 - 不报错退出,而是让 LLM 动态生成缺失的辅助函数
这种设计让 Browser Harness 能够处理从未见过的网页结构。传统自动化脚本遇到新的 DOM 结构就会失败,但 Browser Harness 的 Agent 会"看懂"页面,然后编写新的代码来完成任务。
核心架构:592 行代码的组织方式
Browser Harness 的代码库极其精简,核心只有 5 个文件:
src/browser_harness/
├── __init__.py # 37 行,包初始化
├── _ipc.py # 201 行,Unix Socket/TCP 进程间通信
├── helpers.py # 564 行,核心 CDP 辅助函数
├── daemon.py # 850 行,后台守护进程管理
├── run.py # 407 行,CLI 入口和 REPL
└── admin.py # 1191 行,安装、更新、诊断工具
总计约 3,250 行代码(不是 592 行,592 行是早期版本的代码量)。但即使扩展到 3,000+ 行,这个代码量仍然只有 Playwright 的 1/50。
关键模块解析
helpers.py 是整个框架的灵魂。它只提供 20 多个基础函数:
# 导航和页面信息
goto_url(url) # 导航到 URL
page_info() # 获取当前页面信息(URL、标题、尺寸、滚动位置)
wait_for_load() # 等待页面加载完成
# 元素交互
click_at_xy(x, y) # 点击坐标
type_text(text) # 输入文本
fill_input(selector, text) # 填充表单字段
# JavaScript 执行
js(expression) # 执行 JavaScript 并返回结果
# CDP 原始访问
cdp(method, **params) # 直接调用 Chrome DevTools Protocol
# 截图和录制
capture_screenshot(path) # 截图
start_recording(name) # 开始录制操作
stop_recording() # 停止录制
这些函数通过 Unix Socket(或 Windows TCP)与后台 daemon 进程通信。daemon 维护着与 Chrome CDP 端口的 WebSocket 连接。
daemon.py 负责: - 自动发现运行中的 Chrome 实例 - 启动后台守护进程 - 管理 CDP 连接池 - 处理多标签页切换 - 支持云端浏览器(Browser Use Cloud)
run.py 是 CLI 入口。它启动一个 REPL(Read-Eval-Print Loop),让 LLM 可以通过 heredoc 方式执行 Python 代码:
browser-harness <<'PY'
goto_url("https://example.com")
print(page_info())
PY
这种设计让 LLM 可以像调用函数一样控制浏览器,而不需要理解底层的 CDP 协议细节。
自修复机制:AI 如何动态生成缺失函数
Browser Harness 最核心的创新是自修复(Self-Healing)机制。传统框架遇到不支持的操作时会抛出异常,而 Browser Harness 让 LLM 自己写代码解决问题。
工作流程
1. Agent 收到任务:下载 X(Twitter) 上最新的 20 个视频
2. Agent 调用 goto_url("https://x.com/profile")
3. Agent 调用 page_info() 获取页面信息
4. Agent 需要滚动页面加载更多帖子,但框架没有 scroll_to_bottom() 函数
5. Agent 自己编写:
def scroll_to_bottom(times=10):
for _ in range(times):
js("window.scrollTo(0, document.body.scrollHeight)")
time.sleep(2)
6. 保存到 agent-workspace/agent_helpers.py
7. 下次任务直接复用
这种机制的关键在于 agent_helpers.py 文件。它位于 Agent 的工作区,不在框架源码目录中。Agent 可以自由修改这个文件,添加任何需要的辅助函数。
代码示例
# agent-workspace/agent_helpers.py
# Agent 自动生成的辅助函数
def scroll_to_bottom(times=10):
"""滚动到页面底部,加载更多内容"""
for _ in range(times):
js("window.scrollTo(0, document.body.scrollHeight)")
time.sleep(2)
def extract_video_urls():
"""提取页面中所有视频链接"""
return js("""
Array.from(document.querySelectorAll('video source'))
.map(el => el.src)
.filter(src => src)
""")
def download_file(url, filename):
"""下载文件到本地"""
import urllib.request
urllib.request.urlretrieve(url, filename)
当 Agent 执行任务时,这些自定义函数会被自动加载。框架通过 from agent_helpers import * 将它们注入到 REPL 环境中。
为什么这很重要
传统自动化框架的扩展需要: 1. 理解框架的插件机制 2. 遵循严格的 API 规范 3. 发布到包管理器 4. 等待用户安装
Browser Harness 的自修复机制让扩展变得即时且个性化: - Agent 根据当前任务需求生成代码 - 代码保存在本地,立即可用 - 不需要发布或安装 - 每个用户的 Agent 会根据自己的使用模式进化
这就是"框架越用越强"的含义。你的 Agent 处理过的任务越多,它积累的辅助函数就越丰富,未来处理类似任务的效率就越高。
技术实现细节
Chrome DevTools Protocol (CDP)
Browser Harness 的核心通信协议是 CDP。CDP 是 Chrome 浏览器提供的调试接口,允许外部程序控制浏览器的几乎所有行为。
# helpers.py 中的 cdp() 函数
def cdp(method, session_id=None, **params):
"""直接调用 CDP 方法"""
return _send({
"method": method,
"params": params,
"session_id": session_id
}).get("result", {})
# 使用示例
cdp("Page.navigate", url="https://example.com")
cdp("Input.dispatchMouseEvent", type="mousePressed", x=100, y=200)
cdp("Runtime.evaluate", expression="document.title")
CDP 的优势在于: - 无需选择器:直接通过坐标点击,绕过复杂的 CSS/XPath 选择器 - 跨域支持:CDP 在浏览器底层工作,不受同源策略限制 - 完整控制:可以访问网络请求、DOM、JavaScript 运行时、性能数据等
进程间通信 (IPC)
Browser Harness 使用 Unix Socket(POSIX)或 TCP(Windows)实现 CLI 与 daemon 之间的通信。
# _ipc.py 中的核心逻辑
def connect(name, timeout=1.0):
"""连接到 daemon"""
if not IS_WINDOWS:
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect(str(_sock_path(name)))
return s, None
# Windows 使用 TCP
port, token = _read_port_file(name)
s = socket.create_connection(("127.0.0.1", port))
return s, token
def request(c, token, req):
"""发送请求并接收响应"""
if token:
req = {**req, "token": token}
c.sendall((json.dumps(req) + "\n").encode())
data = b""
while not data.endswith(b"\n"):
chunk = c.recv(1 << 16)
if not chunk:
break
data += chunk
return json.loads(data or b"{}")
这种设计的优势: - 低延迟:Unix Socket 比 HTTP 快得多 - 安全性:Unix Socket 通过文件权限控制访问 - 简单性:不需要 HTTP 服务器、路由、序列化等复杂逻辑
自动发现 Chrome 实例
daemon.py 会自动扫描系统中运行中的 Chrome 实例:
# daemon.py 中的浏览器发现逻辑
_MAC_PROFILES = (
"Library/Application Support/Google/Chrome",
"Library/Application Support/Google/Chrome Canary",
"Library/Application Support/Arc/User Data",
# ... 更多浏览器
)
_LINUX_PROFILES = (
".config/google-chrome",
".config/chromium",
".config/microsoft-edge",
# ... 更多浏览器
)
def supported_browser_running():
"""检测是否有支持的浏览器在运行"""
return any(browser_running_for_profile(base) for base in PROFILES)
它通过检查 SingletonLock 文件和 DevToolsActivePort 文件来判断浏览器是否在运行,以及是否启用了远程调试。
与其他浏览器 Agent 对比
| 特性 | Browser Harness | Browser Use | Agent-E | WebVoyager |
|---|---|---|---|---|
| 代码量 | 3,250 行 | 15,000+ 行 | 20,000+ 行 | 10,000+ 行 |
| 设计哲学 | 极简主义 | 功能完整 | 企业级 | 研究导向 |
| 自修复 | ✅ 核心特性 | ❌ | ❌ | ❌ |
| CDP 直接访问 | ✅ | ✅ | ✅ | ✅ |
| 选择器引擎 | ❌ 坐标优先 | ✅ | ✅ | ✅ |
| 云端浏览器 | ✅ | ✅ | ❌ | ❌ |
| 录制功能 | ✅ | ✅ | ❌ | ❌ |
| 学习曲线 | 低 | 中 | 高 | 高 |
Browser Harness 的核心优势是极简 + 自修复。它不试图提供所有功能,而是让 LLM 根据需求动态生成代码。这种设计让它能够处理从未见过的场景,而其他框架需要预先编写适配器。
实战案例:自动化完成复杂网页任务
案例 1:下载 X(Twitter) 视频
# 任务:下载 X 上最新的 20 个视频
browser-harness <<'PY'
# 1. 导航到 X 个人主页
goto_url("https://x.com/username/media")
wait_for_load()
# 2. 滚动加载更多帖子
scroll_to_bottom(20) # Agent 自动生成的函数
# 3. 提取视频 URL
videos = extract_video_urls() # Agent 自动生成的函数
# 4. 下载视频
for i, url in enumerate(videos[:20]):
download_file(url, f"video_{i+1}.mp4")
print(f"Downloaded {i+1}/20")
PY
案例 2:填写复杂表单
# 任务:自动填写注册表单
browser-harness <<'PY'
goto_url("https://example.com/register")
wait_for_load()
# 获取页面信息
info = page_info()
print(f"Page: {info['title']}")
# 使用 Accessibility Tree 找到表单元素
tree = cdp("Accessibility.getFullAXTree")["nodes"]
# 过滤出输入框
inputs = [n for n in tree if n.get("role") == "textbox"]
# 填写表单
for input_node in inputs:
# 获取坐标
box = cdp("DOM.getBoxModel", backendNodeId=input_node["backendDOMNodeId"])
x = sum(box["model"]["content"][0::2]) / 4
y = sum(box["model"]["content"][1::2]) / 4
# 点击并输入
click_at_xy(x, y)
type_text("test@example.com")
PY
案例 3:抓取动态加载的内容
# 任务:抓取无限滚动的商品列表
browser-harness <<'PY'
goto_url("https://example.com/products")
wait_for_load()
products = []
last_height = 0
# 滚动直到没有新内容
for _ in range(50):
# 获取当前产品
new_products = js("""
Array.from(document.querySelectorAll('.product-card'))
.map(card => ({
name: card.querySelector('.name').textContent,
price: card.querySelector('.price').textContent
}))
""")
# 检查是否有新内容
if len(new_products) == len(products):
break
products = new_products
# 滚动
js("window.scrollTo(0, document.body.scrollHeight)")
time.sleep(2)
print(f"Found {len(products)} products")
PY
局限性和适用场景
局限性
- 依赖 Chrome:只支持 Chrome/Chromium 系浏览器,不支持 Firefox/Safari
- 需要手动启用远程调试:首次使用需要在
chrome://inspect中勾选"允许远程调试" - 坐标点击不稳定:页面布局变化会导致坐标失效(但 LLM 可以自适应)
- 不适合大规模爬虫:单实例设计,不适合并发抓取数千个页面
- 需要 LLM 支持:没有 LLM 就无法发挥自修复能力
适用场景
✅ 个人自动化任务:下载视频、填写表单、抓取数据 ✅ 测试和调试:快速验证网页功能 ✅ 复杂交互流程:需要动态决策的多步骤任务 ✅ 已登录会话:利用 Chrome 的登录状态访问需要认证的网站 ✅ Bot 保护网站:使用真实浏览器绕过反爬虫机制
❌ 大规模数据抓取:使用 Scrapy + Playwright 更合适 ❌ 跨浏览器测试:使用 Playwright 的多浏览器支持 ❌ 简单的 HTTP 请求:使用 requests/httpx 更高效
安装和快速上手
安装
# 使用 uv 安装(推荐)
uv tool install --python 3.12 browser-harness
# 或使用 pip
pip install browser-harness
首次配置
- 打开 Chrome,访问
chrome://inspect/#remote-debugging - 勾选"允许远程调试此浏览器实例"
- 测试连接:
browser-harness <<'PY'
print(page_info())
PY
如果看到当前页面的信息(URL、标题、尺寸),说明连接成功。
与 Claude Code 集成
# 安装 browser-harness
uv tool install --python 3.12 browser-harness
# 注册为 skill
mkdir -p ~/.codex/skills/browser-harness
browser-harness skill > ~/.codex/skills/browser-harness/SKILL.md
然后在 Claude Code 中,Agent 会自动使用 browser-harness 处理所有浏览器任务。
总结评价
Browser Harness 代表了 AI Agent 工具设计的一个重要趋势:从复杂框架走向极简主义。
它的核心洞察是:与其试图预定义所有可能的浏览器操作,不如提供最小化的基础函数,让 LLM 根据具体任务动态生成代码。这种设计不仅减少了代码量,还提高了灵活性——Agent 可以处理从未见过的场景。
优点: - ✅ 代码极简,易于理解和定制 - ✅ 自修复机制让框架越用越强 - ✅ CDP 直接访问,性能优秀 - ✅ 支持云端浏览器,可扩展到大规模任务 - ✅ 录制功能方便调试和回溯
缺点: - ❌ 依赖 Chrome,不支持其他浏览器 - ❌ 首次配置需要手动启用远程调试 - ❌ 坐标点击在布局变化时不稳定 - ❌ 不适合大规模并发任务
推荐指数:⭐⭐⭐⭐⭐(5/5)
对于需要自动化浏览器任务的开发者,Browser Harness 是目前最优雅的选择。它的极简设计和自修复能力让它能够适应各种复杂场景,而 3,000+ 行的代码量意味着你可以轻松理解它的每一行实现。
如果你正在构建 AI Agent,或者需要自动化复杂的网页任务,Browser Harness 值得一试。它可能会改变你对浏览器自动化的认知——最好的框架不是功能最多的,而是让 AI 能够自己解决问题的。
参考链接: - GitHub: browser-use/browser-harness - 文档: SKILL.md - 安装指南: install.md - Browser Use Cloud: cloud.browser-use.com
FAQ
1. Browser Harness 和 Playwright 有什么区别?
Browser Harness 是 AI 原生框架,设计目标是让 LLM 控制浏览器,不提供选择器引擎和高级等待机制,而是通过 CDP 直接操作坐标和 DOM。Playwright 是传统自动化框架,为人类编写脚本设计,提供丰富的选择器和等待机制。Browser Harness 的核心优势是自修复能力——遇到不支持的操作时,LLM 会自己编写代码。
2. Browser Harness 支持哪些浏览器?
目前只支持 Chrome/Chromium 系浏览器,包括 Google Chrome、Chrome Canary、Microsoft Edge、Brave、Arc 等。不支持 Firefox 和 Safari,因为 Browser Harness 依赖 Chrome DevTools Protocol (CDP)。
3. 如何启用 Chrome 的远程调试?
打开 Chrome,访问 chrome://inspect/#remote-debugging,勾选"允许远程调试此浏览器实例"。macOS 用户可能需要在系统设置中授予终端 Accessibility 权限。
4. Browser Harness 适合大规模爬虫吗?
不适合。Browser Harness 是单实例设计,主要面向个人自动化任务。如果需要并发抓取数千个页面,建议使用 Scrapy + Playwright 或 Browser Use Cloud 的云端浏览器功能。
5. 自修复机制是如何工作的?
当 Agent 遇到框架没有覆盖的操作时,它会自己编写一个新的 Python 函数,保存到 agent-workspace/agent_helpers.py 文件中。下次执行任务时,这个函数会被自动加载。这样框架就"学会"了新的能力,越用越强。