# 在 LLM 智能体中集成 VisionL > 让 LLM 通过 HTTP API 工具调用操控 VisionL 浏览器。 ## 原理 VisionL daemon 提供完整的 REST API。LLM 将 API 调用注册为工具/函数(Function Calling), 在需要浏览网页时生成对应的 HTTP 请求。所有接口返回结构化 JSON,LLM 直接解析。 ## API 总览 | 方法 | 端点 | 功能 | |------|------|------| | POST | `/pages` | 打开页面 | | GET | `/pages` | 列出所有页面 | | GET | `/pages/:id` | 页面详情 | | DELETE | `/pages/:id` | 关闭页面 | | POST | `/pages/:id/navigate` | 跳转 | | POST | `/pages/:id/click` | 点击元素 | | POST | `/pages/:id/type` | 输入文本 | | POST | `/pages/:id/scroll` | 滚动 | | POST | `/pages/:id/eval` | 执行 JS | | POST | `/pages/:id/wait` | 等待 | | GET | `/pages/:id/screenshot` | 截图(base64) | | GET | `/pages/:id/text` | 纯文本 | | GET | `/pages/:id/html` | HTML 源码 | | GET | `/pages/:id/cookies` | Cookie 列表 | | POST | `/pages/:id/cookies` | 设置 Cookie | | DELETE | `/pages/:id/cookies/:name` | 删除 Cookie | | GET | `/pages/:id/console` | 控制台日志 | | GET | `/pages/:id/network` | 网络请求日志 | | GET | `/profiles` | 指纹配置列表 | 完整文档见 [API 文档](../development/api.md)。 ## 集成方式 ### 方式一:Function Calling(推荐) 注册 `visionl_api` 工具,LLM 直接生成 HTTP 请求: ```json { "type": "function", "function": { "name": "visionl_api", "description": "通过 VisionL 浏览器操控网页。支持打开页面、点击、输入、截图、提取文本、执行JS、管理Cookie、查看网络请求等。", "parameters": { "type": "object", "properties": { "method": { "type": "string", "enum": ["GET", "POST", "DELETE"], "description": "HTTP 方法" }, "path": { "type": "string", "description": "API 路径,如 /pages、/pages/baidu/text" }, "body": { "type": "object", "description": "请求体(仅 POST 需要)" } }, "required": ["method", "path"] } } } ``` ### 使用流程 1. LLM 决策需要访问网页 2. LLM 调用 `visionl_api`:`POST /pages` 打开 baidu.com 3. 宿主程序执行 HTTP 请求,将 JSON 结果返回 LLM 4. LLM 解析结果,获得页面 ID `p_xxx` 5. LLM 继续:`GET /pages/p_xxx/text` 读取内容 6. 或:`POST /pages/p_xxx/click` 点击搜索 ### 方式二:多工具注册 将每个操作注册为独立工具(更细粒度): ```json [ { "name": "visionl_open", "description": "打开网页", "parameters": { "url": { "type": "string" }, "alias": { "type": "string" } } }, { "name": "visionl_text", "description": "获取页面文本内容", "parameters": { "page_id": { "type": "string" } } }, { "name": "visionl_click", "description": "点击页面元素", "parameters": { "page_id": { "type": "string" }, "selector": { "type": "string" } } } ] ``` ### 方式三:LangChain 集成 ```python from langchain.tools import BaseTool import requests class VisionLTool(BaseTool): name = "visionl" description = "浏览器操控工具。API 基础 URL: http://127.0.0.1:9527" def _run(self, method: str, path: str, body: dict = None) -> str: url = f"http://127.0.0.1:9527{path}" resp = requests.request(method, url, json=body) return resp.text ``` ## LLM 系统提示词建议 ``` 你可以使用 visionl_api 工具操控浏览器: 打开页面: POST /pages {"url":"...","alias":"..."} 页面文本: GET /pages/{id}/text 页面截图: GET /pages/{id}/screenshot (返回 base64) 点击元素: POST /pages/{id}/click {"selector":"#id"} 输入文本: POST /pages/{id}/type {"selector":"#id","text":"..."} 执行 JS: POST /pages/{id}/eval {"code":"..."} 滚动页面: POST /pages/{id}/scroll {"deltaY":300} 等待加载: POST /pages/{id}/wait {"ms":2000} 查看Cookie: GET /pages/{id}/cookies 网络日志: GET /pages/{id}/network 关闭页面: DELETE /pages/{id} 所有接口返回 {"ok":true,"data":{...}} 或 {"ok":false,"error":{...}}。 打开页面后记录返回的 page_id,后续操作使用该 id。 页面在被显式 kill 之前永远存活,可跨多轮对话复用。 ``` ## 多页面并行管理 LLM 同时打开多个页面,通过别名区分: ``` LLM: POST /pages {"url":"https://docs.python.org","alias":"py"} → {"ok":true,"data":{"id":"p_aaa",...}} LLM: POST /pages {"url":"https://developer.mozilla.org","alias":"mdn"} → {"ok":true,"data":{"id":"p_bbb",...}} LLM: GET /pages/py/text # 读 Python 文档 LLM: GET /pages/mdn/text # 读 MDN 文档 ``` ## 错误处理 ```json // 失败示例 {"ok":false,"error":{"code":"PAGE_NOT_FOUND","message":"页面 py 不存在"}} ``` 常见错误码及处理: | 错误码 | HTTP | 处理建议 | |--------|------|---------| | `PAGE_NOT_FOUND` | 404 | 页面已关闭,重新打开 | | `DAEMON_UNREACHABLE` | 502 | 启动 daemon 或稍后重试 | | `TIMEOUT` | 408 | 页面加载慢,重试或增加等待 | | `ALIAS_EXISTS` | 409 | 换别名或直接用 page_id | ## 反检测能力 VisionL 内置多层反检测,使自动化访问尽可能不被简单人机验证拦截: - `navigator.webdriver` → `false` - 真实 Chrome User-Agent 和请求头 - Canvas/WebGL/Audio 指纹加噪 - 屏幕分辨率和视口合理性 - 权限状态模拟 - 3 套指纹模版可切换 详见 [反检测设计文档](../development/anti-detection.md)。