自然语言驱动的浏览器自动化 Agent
用一句自然语言描述目标,Agent 自主操控真实浏览器完成:把页面提炼成紧凑文本快照喂给模型,模型每步返回一个原子动作,错误作为反馈进入下一轮。
角色 独立开发(四个阶段:Agent 闭环 / 工程化 / 前端工作台 / 评测打磨)
用户输入一句中文或英文目标(例如「帮我登录这个系统并检查未读消息」),AI 自主操控真实 Chromium 浏览器完成任务。核心是「观察 → 决策 → 执行 → 自检」循环:把页面 DOM 提炼成紧凑文本快照喂给 LLM,模型每步返回一个工具调用。
工具集包含 click / type_text / select / navigate / scroll / wait / done / fail 共 8 种原子动作,执行结果——包括错误——会回传模型进入下一轮。配套 API + Redis 队列 + Worker 执行、PostgreSQL 全过程持久化、React 实时工作台与 Docker 一键部署,并用自建评测集计量成功率与 token 成本。
浏览器里的重复操作(搜索、填表、跨页取信息)很难用固定脚本覆盖:页面结构一变、出现弹窗或新标签页、SPA 局部重渲染,选择器脚本就失效。
把整页 HTML 直接喂给 LLM 成本高(100KB+ HTML、上万 token)、噪声大(90% 是样式与结构),模型行为也不稳定。
Agent 任务动辄几十秒且可能崩溃,放在 Web 请求里同步执行既拖垮接口也丢任务。
让用户只用一句自然语言就能完成浏览器任务,Agent 自主决策、失败能自恢复、不会卡死。
把页面观察压缩到可控 token(单步约 3K),让成本与稳定性都可控。
工程化可交付:API 与执行分离、任务 / 步骤 / 成本全量落库、可视化回放、评测集、Docker 一键部署。
观察层不传整页 HTML,只提炼「可见交互元素编号 + 页面大纲」,把单步输入压到约 3K token,成本与稳定性同时受益。
动作定位不依赖快照序号:用元素指纹做跨步骤映射,SPA 重渲染后仍能命中目标;指纹歧义时保守报错而不是误点。
任务通过 Redis Streams 可靠队列交给独立 Worker 执行,API 只负责入队与查询,并把每一步的思考、动作、耗时与截图落库供回放。
用户 / 工作台 → FastAPI:POST /api/tasks(可选 Bearer 鉴权 + URL 白名单校验)写入 Redis Stream;GET /api/tasks/{id}/events 通过 SSE 实时推送步骤与状态(前端弱网自动降级轮询);查询与回放接口只读。Worker 为独立进程,以 Redis Streams 消费者组 XREADGROUP 消费,内部包含并发信号量(默认 3)、浏览器池(单 Chromium 进程 + 每任务独立 Context 做 Cookie / localStorage 隔离)、Agent 循环(DOM 快照 → LLM 工具调用 → Playwright 执行 → 结果或错误回传),任务终态落库后才 XACK,启动时用 XAUTOCLAIM 认领崩溃遗留的 pending 任务重跑。每步 thought / 动作 / 耗时 / JPEG 截图实时落 PostgreSQL。
不把整页 HTML 喂模型,而是提炼「交互元素编号 + 页面大纲」,单步输入约 3K token,成本与稳定性同时受益。
动作异常格式化为工具结果回传,模型自行调整策略——实测 GitHub 搜索框 fill 超时后,模型自主降级为直接构造搜索 URL 完成任务。
FNV-1a 指纹持久映射;信息论上不可解的情形(完全同指纹元素)保守报错而非误点。
滑动窗口 + 旧步骤浓缩摘要(触发:估算字符 > 24K 或消息数 > 26),实测 bing 用例 prompt token 35,488 → 13,949(-61%)、github 33,752 → 21,924(-35%)。
Redis Streams 消费者组 + XACK + XAUTOCLAIM,并用集成测试验证「执行中强杀 Worker 后重启,任务被认领重跑并 success」。
API / Worker 分离、Docker 五服务编排、API Token 鉴权(常量时间比较)、URL 白名单(防前缀绕过与非 http(s) scheme)、提示注入缓解边界如实写明。
截图改 JPEG q70,单张从平均 116,455 B 降到 17,107 B(-85%);截图目录只保留最近 50 个任务;token 计量用于驱动后续优化决策。
页面观察方式
选了 提炼交互元素编号 + 页面大纲,而不是 把整页 HTML 交给模型 —— 整页 HTML 噪声大、token 高,模型行为不稳定。
代价:需要自己维护观察层,并确保快照真实反映运行时状态。
元素定位策略
选了 元素指纹映射 + 歧义时报错,而不是 直接按快照序号点击 —— 重渲染后序号会漂移,误点比报错代价更高。
代价:完全同指纹的情形无法自动区分,只能让模型重新观察。
截图格式
选了 JPEG q70 + 仅保留最近 50 个任务,而不是 PNG 全量保留 —— 回放只需要可用画质,体积与磁盘更重要。
代价:历史任务超过 50 个后早期截图会被清理。
评测成功率:自建 6 用例(4 本地 fixture + 2 外网),跨多次运行累计 13/14 通过(92.9%);其中 DeepSeek 单轮全量 6/6 全过(2026-09-02 记录),外网 GitHub 用例 4/5(80%,受外部页面变化影响)。
执行效率:平均 4–6 步完成任务;单任务耗时 6–52 秒(含 LLM 延迟),本地 fixture 类约 6–10 秒。
token 成本:单任务约 4K–28K prompt + 220–560 completion token;全量 6 用例一轮合计 58,162 prompt + 2,146 completion token,成本可精确核算。
优化效果(有前后对比):上下文压缩使 bing 用例 prompt token -61%、github -35%;截图改 JPEG q70 后单张平均体积从 116,455 B 降至 17,107 B(-85%)。
质量门禁:后端 pytest 28 项全绿(本次实测收集 28 项),覆盖 Mock LLM 闭环、浏览器观察与指纹、上下文窗口、LLM 重试、持久化、弹窗与新标签、安全校验、SSE、截图清理。
交付:Docker Compose 一键拉起 5 个服务(postgres 17 / redis 7 / api / worker / frontend + nginx);两个真实任务回放页已发布到 GitHub Pages,可直接查看;工作台前端另有一台自建服务器实例(http://8.138.161.154:18080/)在运行,因只提供 http 访问所以没有作为链接收录。
「快照必须反映运行时状态」值得固化为设计约束:属性读取方式的一个细节差异(getAttribute 与运行时 property)足以让模型陷入重复操作的循环。
错误应该作为反馈传回模型,而不是终止任务:把异常格式化成工具结果后,模型能够自行降级(例如改用直接构造 URL 完成搜索)。
不确定时保守报错比猜着点击更安全:在无法区分的歧义场景里,让模型重新观察页面比误操作代价更低。



