AI操作网页,不必每一步都盯着截图猜坐标。Ego Lite向Agent提供页面快照、填写、点击和结果读取等能力:模型先获得页面里有哪些控件,再调用工具操作浏览器,最后读取页面变化,决定是否继续。
下面用一个无账号、无外部请求的学习表单演示这条链路。目标很具体:输入“缓存”,点击查找,确认页面显示“找到1条资料”,而不是停在“点击命令已发出”。
Space、Page和快照各负责什么
图:CitroLabs在ego-lite仓库提供的架构原图,仓库内容采用MIT许可。它展示Agent、连接层和多个Space的关系;图中的宣传性命名不作为速度、成本或安全效果的实测结论。
Space负责组织这次浏览器任务的页面和控制权;Page对应其中一个页面。快照把页面里的标题、文本、输入框、按钮等变成结构化描述,供模型选择操作目标。它不是一张截图,也不等于页面全部底层数据。
| 对象 | 在这个例子里的用途 |
|---|---|
| TaskSpace | 保存“查找学习资料”任务及其页面;后续调用继续使用同一个Space |
Pagep1 | 打开学习表单、填写关键词、读取结果 |
| Snapshot | 告诉Agent页面有“关键词”输入框、“查找资料”按钮及当前状态 |
| Action | 执行fill、click等浏览器操作 |
| 回读 | 检查状态文字和结果区,判断目标是否实现 |
Space把任务页面组织起来,并不意味着每个Space都有完全独立的网站账号或操作系统权限。作者README里的性能对比也有特定测试条件,不能直接推成你自己的任务一定更快、更省。
从一个能看见结果的页面开始
图:独立学习表单的实际截图,尚未输入或提交。页面不是产品界面仿图,也没有使用私人账号后台。
要复现一个最小版本,可以把下面内容保存为C:\ego-demo\index.html。它只在本页显示匹配结果,不发送网络请求。
<!doctype html><meta charset="utf-8"> <h1>学习资料检索</h1> <form id="search"> <label>关键词 <input placeholder="例如:缓存" required></label> <button>查找资料</button> </form> <p id="status" role="status">尚未检索</p> <section id="results"></section> <script> const items = ['提示缓存', 'Git分支', '工具调用']; document.querySelector('#search').onsubmit = e => { e.preventDefault(); const word = document.querySelector('input').value.trim(); const rows = items.filter(x => x.includes(word)); document.querySelector('#status').textContent = `检索完成:${word},找到 ${rows.length} 条资料`; document.querySelector('#results').textContent = rows.join('、'); }; </script>在终端启动一个只监听本机的临时服务;这个例子需要Python和已经配置好的ego-browser,不涉及模型账号安装教程。
python -m http.server 8767 --bind 127.0.0.1 --directory C:\ego-demo第一轮:打开页面并观察
在已支持ego-browser的Agent环境中,先运行ego-browser skill读取当前用法,再执行下面的浏览器脚本。一个任务只建一个Space,后续轮次继续使用它。
const task = await taskSpace('learning-form-demo'); console.log('Space ID:', task.spaceId); const page = task.page('p1'); await page.goto('http://127.0.0.1:8767/index.html'); console.log(await page.snapshot());例如把这段脚本保存为C:\ego-demo\round-1.mjs,在PowerShell执行下面的命令;第二轮同样保存为round-2.mjs,换成对应文件名执行。.mjs文件中的浏览器辅助方法由ego-browser运行环境提供,不能直接用普通node命令运行。
ego-browser nodejs -e "await import('file:///C:/ego-demo/round-1.mjs')"本文实际演示页的快照包含关键词输入框、按钮和“尚未检索”状态。它还给控件分配了当前引用,例如ref=1与ref=2,并为输入框提供input[placeholder="例如:缓存"]定位线索。
textbox [ref=1, loc=css:input[placeholder="例如:缓存"]] button [ref=2] text "查找资料" status text "尚未检索"这些引用属于当时的页面观察结果,不能把别人的@1复制后当作任何页面都适用的按钮编号。页面导航或内容变化后,应重新观察;如果选择器匹配多个对象,就进一步限定目标。
第二轮:继续同一个任务,操作后再读结果
const task = await taskSpace('learning-form-demo'); const page = task.page('p1'); console.log(await page.snapshot()); await page.fill('input[placeholder="例如:缓存"]', '缓存'); await page.click('text="查找资料"'); await page.waitForFunction(() => document.querySelector('#status').textContent === '检索完成:缓存,找到 1 条资料' ); console.log(await page.snapshot()); await task.finish({ keep: [] });图:同一任务跨两轮后,实际页面显示关键词“缓存”、完成状态和“提示缓存”资料。截图来自实际浏览器操作;这里验证的是表单查找流程,不是工具对任意网站的通用成功率。
click返回,只能说明动作已经发出。实际网站可能还在校验、等待网络响应,或者显示了错误。这里用状态文字作为完成条件,真实任务也应选择可观察的结果,例如保存成功提示、列表出现新增记录或错误信息消失。
从源码能追到哪一步
公开仓库的package/ego-browser/src/driver/observe.ts中,snapshot()调用浏览器侧快照能力,并将返回的refs写入引用映射。它解释了为什么快照描述能与后续控件操作衔接。
这份文件是连接层证据,不是整个浏览器引擎的源码。Ego Lite的API也不是完整Playwright:名称类似,不代表可以直接调用locator()或任意Playwright方法;具体方法与参数仍要以当前skill为准。
做网页任务时,可以沿着“观察当前页面→执行一个明确动作→等待可见变化→读取结果”的顺序组织脚本。先把一次查找、一次保存做完整,再扩展到多个页面,通常比只写一串点击更容易发现失败发生在哪一步。
来源:CitroLabs《ego-lite项目》及仓库observe.ts;架构图版权归CitroLabs,按仓库MIT许可使用,许可原文见仓库LICENSE。