1. LangChain与AgentRun Browser Sandbox集成概述
在当今AI技术快速发展的背景下,智能体(AI Agent)需要与真实世界进行交互的能力变得越来越重要。浏览器作为连接虚拟世界与现实世界的重要桥梁,为智能体提供了丰富的交互可能性。AgentRun Browser Sandbox正是为解决这一需求而设计的云原生无头浏览器沙箱服务。
Browser Sandbox基于阿里云函数计算(FC)构建,为智能体提供了安全、高性能且免运维的浏览器执行环境。通过这项服务,AI Agent可以真正具备"上网"能力——从简单的网页抓取、信息提取,到复杂的表单填写、自动化操作,一切皆可实现。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. AgentRun Browser Sandbox核心特性解析
2.1 无头浏览器能力
Browser Sandbox内置了最新版本的Chromium/Chrome浏览器,支持完整的Web标准。这意味着智能体可以访问和操作绝大多数现代网页,而不用担心兼容性问题。更重要的是,它原生兼容Puppeteer、Playwright等主流浏览器自动化框架,开发者可以使用熟悉的工具和API来控制浏览器行为。
技术实现上,Browser Sandbox通过标准的Chrome DevTools Protocol (CDP)提供远程控制能力。CDP是Chrome开发者工具使用的底层协议,提供了对浏览器几乎所有功能的细粒度控制。这种设计使得Browser Sandbox既保持了强大的功能,又能与现有工具链无缝集成。
2.2 实时可视化与调试支持
Browser Sandbox内置了VNC服务,支持实时查看浏览器界面。这一特性对于调试和监控智能体的操作过程特别有用。开发者可以通过noVNC客户端在网页中直接观看浏览器的实时操作,就像在本地运行一样。
此外,Browser Sandbox还提供了操作录制功能。当智能体执行复杂的网页操作时,开发者可以回放整个过程,精确分析每个步骤的执行情况。这对于排查问题和优化操作流程非常有帮助。
2.3 安全与隔离机制
安全是Browser Sandbox设计的核心考量之一。每个沙箱实例都运行在独立的容器环境中,文件系统和进程空间完全隔离。这种隔离机制确保了不同智能体的操作不会相互干扰,也防止了潜在的恶意代码传播。
数据传输方面,Browser Sandbox支持WSS(WebSocket Secure)加密传输,确保操作指令和页面内容在传输过程中不会被窃听或篡改。对于处理敏感数据的应用场景,这一特性尤为重要。
2.4 Serverless架构优势
Browser Sandbox采用Serverless架构,具有按需创建、按量付费的特点。开发者无需提前预置资源,也无需担心服务器维护问题。系统能够根据负载自动弹性伸缩,轻松应对高并发场景。
这种架构特别适合AI Agent的应用场景,因为智能体的浏览器操作需求往往是突发性和间歇性的。传统方案需要长期维持浏览器实例,而Browser Sandbox可以在任务到来时快速启动,任务完成后自动释放资源,显著降低成本。
3. 环境准备与SDK安装
3.1 系统要求
在使用AgentRun SDK之前,请确保您的开发环境满足以下要求:
- Python 3.10或更高版本
- pip包管理工具
- 稳定的网络连接
- 阿里云账号(用于访问AgentRun服务)
3.2 SDK安装
安装AgentRun SDK及其依赖项非常简单,只需执行以下命令:
bash复制pip install agentrun-sdk[playwright,server]>=0.0.8
这个命令会安装核心SDK以及Playwright集成支持。Playwright是一个流行的浏览器自动化库,我们将使用它来控制Browser Sandbox中的浏览器实例。
注意:安装完成后,建议运行
playwright install命令来确保所有必要的浏览器组件都已就绪。虽然Browser Sandbox本身不需要本地浏览器,但Playwright的某些功能可能需要这些组件。
3.3 环境变量配置
为了使用AgentRun服务,您需要配置以下环境变量。创建一个名为.env的文件,内容如下:
ini复制# 阿里云百炼平台的API Key
DASHSCOPE_API_KEY=sk-your-bailian-api-key
# 阿里云账号的访问凭证
ALIBABA_CLOUD_ACCESS_KEY_ID=your-ak
ALIBABA_CLOUD_ACCESS_KEY_SECRET=your-sk
ALIBABA_CLOUD_ACCOUNT_ID=your-main-account-id
ALIBABA_CLOUD_REGION=cn-hangzhou
# Browser Sandbox模板名称
BROWSER_TEMPLATE_NAME=sandbox-your-template-name
# AgentRun服务端点
AGENTRUN_CONTROL_ENDPOINT=agentrun.cn-hangzhou.aliyuncs.com
AGENTRUN_DATA_ENDPOINT=https://${your-main-account-id}.agentrun-data.cn-hangzhou.aliyuncs.com
这些凭证可以从阿里云控制台获取。请确保不要将这些敏感信息提交到版本控制系统。
4. Browser Sandbox模板创建指南
4.1 控制台操作步骤
在使用Browser Sandbox之前,您需要在AgentRun控制台创建一个沙箱模板。以下是详细步骤:
- 登录AgentRun控制台
- 在顶部菜单栏选择"运行时与沙箱"
- 在左侧边栏选择"Sandbox沙箱"
- 点击右上角"创建沙箱模板"按钮
- 在弹出的对话框中选择"浏览器"类型
- 配置模板参数:
- 名称:为您的模板起一个描述性名称
- 规格:选择适合您需求的资源配置(CPU、内存等)
- 网络:配置VPC和交换机(如有需要)
- 空闲超时:设置沙箱实例在无操作时的自动销毁时间
- 点击"创建浏览器"按钮完成创建
4.2 模板参数详解
创建模板时,有几个关键参数需要特别注意:
-
规格选择:不同的业务场景对浏览器性能要求不同。简单的网页抓取可能只需要基础配置,而复杂的Web应用操作可能需要更高的CPU和内存分配。
-
网络配置:如果您的智能体需要访问内网资源,或者需要通过特定的网络出口访问互联网,可以在这里配置VPC和交换机。对于大多数公开网站访问,使用默认网络配置即可。
-
空闲超时:这个参数决定了沙箱实例在没有操作时能保持多久。设置太短可能导致频繁重建,设置太长则可能浪费资源。建议根据业务特点调整,通常300-1800秒是合理的范围。
-
浏览器版本:AgentRun默认提供最新稳定版的Chromium浏览器。如果您有特定的版本需求,可以在高级设置中指定。
5. 基础使用示例
5.1 创建和销毁Sandbox
让我们从一个最基本的示例开始,展示如何创建和使用Browser Sandbox:
python复制from agentrun.sandbox import Sandbox, TemplateType
from playwright.sync_api import sync_playwright
# 创建Browser Sandbox实例
sandbox = Sandbox.create(
template_type=TemplateType.BROWSER,
template_name="your-template-name",
sandbox_idle_timeout_seconds=300
)
# 获取CDP连接URL
cdp_url = sandbox.get_cdp_url()
# 使用Playwright连接并操作浏览器
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(cdp_url)
page = browser.contexts[0].pages[0]
# 导航到示例网站
page.goto("https://www.example.com")
# 截取屏幕截图
page.screenshot(path="screenshot.png")
# 关闭浏览器
browser.close()
# 销毁Sandbox实例
sandbox.delete()
这个示例展示了Browser Sandbox的基本生命周期:创建实例→连接操作→销毁实例。在实际应用中,您可能会重复使用同一个Sandbox实例来执行多个操作,以减少创建销毁的开销。
5.2 实时可视化操作
Browser Sandbox的一个强大功能是支持实时可视化。以下代码展示了如何获取VNC URL并在浏览器中查看操作过程:
python复制# 获取VNC URL
vnc_url = sandbox.get_vnc_url()
print(f"VNC Viewer URL: {vnc_url}")
# 使用Playwright操作浏览器
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(cdp_url)
page = browser.new_page()
# 导航到目标网站
page.goto("https://www.aliyun.com")
# 在页面上执行一些操作
page.fill("#search-input", "函数计算")
page.click(".search-button")
# 保持页面打开一段时间,方便在VNC中查看
page.wait_for_timeout(5000)
browser.close()
在实际应用中,您可以自动打开系统默认浏览器访问VNC URL,实现真正的实时监控。这对于调试复杂的网页操作特别有用。
6. LangChain集成实战
6.1 项目结构设计
为了将Browser Sandbox与LangChain有效集成,我们采用模块化设计,将代码分为以下几个部分:
code复制langchain-demo/
├── sandbox_manager.py # Sandbox生命周期管理
├── langchain_agent.py # LangChain工具和Agent定义
├── main.py # 主程序入口
├── requirements.txt # 依赖列表
└── .env # 环境变量配置
这种结构确保了代码的高内聚和低耦合,便于维护和扩展。
6.2 Sandbox管理器实现
sandbox_manager.py负责封装Browser Sandbox的创建、管理和销毁逻辑:
python复制import os
from typing import Optional, Dict, Any
from dotenv import load_dotenv
load_dotenv()
class SandboxManager:
"""管理Browser Sandbox生命周期的工具类"""
def __init__(self):
self._sandbox = None
self._sandbox_id = None
self._cdp_url = None
self._vnc_url = None
def create(self, template_name: Optional[str] = None, idle_timeout: int = 3000) -> Dict[str, Any]:
"""创建新的Browser Sandbox实例"""
try:
from agentrun.sandbox import Sandbox, TemplateType
if self._sandbox is not None:
return self.get_info()
template_name = template_name or os.getenv("BROWSER_TEMPLATE_NAME", "sandbox-browser-demo")
self._sandbox = Sandbox.create(
template_type=TemplateType.BROWSER,
template_name=template_name,
sandbox_idle_timeout_seconds=idle_timeout
)
self._sandbox_id = self._sandbox.sandbox_id
self._cdp_url = self._get_cdp_url()
self._vnc_url = self._get_vnc_url()
return self.get_info()
except ImportError as e:
raise RuntimeError("请安装agentrun-sdk: pip install agentrun-sdk[playwright,server]")
except Exception as e:
raise RuntimeError(f"创建Sandbox失败: {str(e)}")
# 其他方法省略...
这个管理器类实现了单例模式,确保在整个应用生命周期中只有一个Sandbox实例被创建和使用。它还提供了完善的错误处理和资源清理机制。
6.3 LangChain工具定义
在langchain_agent.py中,我们定义了一系列LangChain工具,使Agent能够操作Browser Sandbox:
python复制from langchain.tools import tool
from pydantic import BaseModel, Field
from sandbox_manager import SandboxManager
manager = SandboxManager()
class NavigateInput(BaseModel):
"""导航操作的输入参数"""
url: str = Field(..., description="要访问的URL")
wait_until: str = Field("load", description="等待条件: load, domcontentloaded, networkidle")
timeout: int = Field(30000, description="超时时间(毫秒)")
@tool(args_schema=NavigateInput)
def navigate_to_url(url: str, wait_until: str = "load", timeout: int = 30000) -> str:
"""导航到指定URL"""
try:
if not manager.is_active():
return "错误: 请先创建sandbox"
if not url.startswith(("http://", "https://")):
return f"错误: 无效的URL格式: {url}"
cdp_url = manager.get_cdp_url()
if not cdp_url:
return "错误: 无法获取CDP URL"
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(cdp_url)
page = browser.contexts[0].pages[0] if browser.contexts else browser.new_page()
page.goto(url, wait_until=wait_until, timeout=timeout)
title = page.title()
return f"已导航到: {url}\n页面标题: {title}"
except Exception as e:
return f"导航失败: {str(e)}"
# 其他工具定义省略...
每个工具都有详细的参数说明和错误处理,确保Agent能够正确使用它们。我们还使用了Pydantic模型来定义工具的参数结构,这有助于LangChain生成准确的工具调用指令。
6.4 Agent创建与配置
在同一个文件中,我们创建LangChain Agent并配置相关工具:
python复制from langchain_openai import ChatOpenAI
from langchain.agents import create_agent
def create_browser_agent():
"""创建集成了Browser Sandbox工具的LangChain Agent"""
# 配置大语言模型
llm = ChatOpenAI(
model="qwen-plus",
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
temperature=0.7
)
# 工具列表
tools = [
create_browser_sandbox,
get_sandbox_info,
navigate_to_url,
take_screenshot,
destroy_sandbox,
]
# 系统提示词
system_prompt = """你是一个浏览器自动化助手,可以使用sandbox来访问和操作网页。
操作流程:
1. 首先创建sandbox(如果还没有)
2. 使用navigate_to_url导航到目标网页
3. 执行请求的操作
4. 需要时截取截图
注意事项:
- 创建sandbox后会返回VNC URL,可用于实时查看操作
- sandbox可以在多轮对话中复用,不要在一轮对话后就销毁
- 只有在明确要求时才使用destroy_sandbox工具"""
# 创建Agent
return create_agent(
model=llm,
tools=tools,
system_prompt=system_prompt,
)
这个配置确保Agent能够理解何时以及如何使用Browser Sandbox工具。系统提示词提供了清晰的操作指南,帮助Agent做出正确的决策。
7. 高级功能与最佳实践
7.1 会话状态管理
在实际应用中,合理管理Sandbox的生命周期非常重要。以下是一些最佳实践:
-
会话级复用:在同一个用户会话中复用Sandbox实例,避免频繁创建销毁带来的延迟和资源浪费。
-
超时设置:根据业务特点设置合理的空闲超时时间。对于交互式应用,可以设置较短超时(如300秒);对于后台任务,可以设置较长超时(如1800秒)。
-
异常恢复:实现自动恢复机制,当Sandbox意外终止时能够重新创建并恢复之前的操作状态。
python复制class ResilientSandboxManager:
"""具有自动恢复能力的Sandbox管理器"""
def __init__(self):
self._sandbox = None
self._last_known_state = None
def execute_operation(self, operation_callback):
"""执行浏览器操作,自动处理Sandbox异常"""
max_retries = 3
for attempt in range(max_retries):
try:
if not self._sandbox or not self._sandbox.is_active():
self._sandbox = SandboxManager().create()
return operation_callback(self._sandbox)
except Exception as e:
print(f"操作失败(尝试{attempt+1}/{max_retries}): {str(e)}")
self._sandbox = None
if attempt == max_retries - 1:
raise
time.sleep(1)
7.2 复杂网页操作
对于需要登录或交互复杂的网站,可以考虑以下策略:
-
Cookie管理:保存和恢复会话Cookie,避免每次都需要重新登录。
-
操作录制与回放:使用Playwright的录制功能生成操作脚本,然后让Agent基于脚本执行。
-
元素等待策略:合理使用
wait_for_selector、wait_for_function等方法,确保页面元素加载完成后再操作。
python复制def login_to_website(page, username, password):
"""执行网站登录流程"""
page.goto("https://example.com/login")
# 等待登录表单加载
page.wait_for_selector("#login-form", state="visible")
# 填写登录信息
page.fill("#username", username)
page.fill("#password", password)
# 提交表单
page.click("#submit-button")
# 等待登录成功
page.wait_for_selector(".user-profile", state="visible")
# 保存Cookies供后续使用
cookies = page.context.cookies()
return cookies
7.3 性能优化技巧
-
并行操作:对于大量独立的任务,可以创建多个Sandbox实例并行处理。
-
资源复用:在同一个Sandbox实例中复用浏览器上下文和页面,减少初始化开销。
-
操作批处理:将多个操作合并为一个任务,减少网络往返。
python复制def batch_operations(sandbox, operations):
"""批量执行浏览器操作"""
cdp_url = sandbox.get_cdp_url()
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(cdp_url)
context = browser.new_context()
results = []
for op in operations:
page = context.new_page()
try:
result = execute_operation(page, op)
results.append(result)
finally:
page.close()
context.close()
return results
8. 常见问题与解决方案
8.1 连接问题排查
-
CDP连接失败:
- 检查Sandbox实例是否仍然活跃(未超时或被销毁)
- 验证网络连接是否正常,特别是防火墙设置
- 确保使用的是最新的SDK版本
-
VNC无法连接:
- 确认VNC服务已在Sandbox模板中启用
- 检查本地网络是否阻止了WebSocket连接
- 尝试使用不同的noVNC客户端
8.2 操作执行问题
-
元素找不到或操作失败:
- 增加等待时间,确保页面完全加载
- 使用更稳定的选择器(如data-testid属性)
- 考虑页面可能有iframe或shadow DOM,需要特殊处理
-
页面响应缓慢:
- 检查Sandbox资源配置是否足够
- 优化操作顺序,减少不必要的页面刷新
- 考虑使用
page.evaluate直接执行JavaScript来提高效率
8.3 资源管理问题
-
Sandbox泄漏:
- 确保每个create都有对应的destroy
- 使用上下文管理器(with语句)或try/finally块
- 实现定期清理机制
-
费用意外增加:
- 检查空闲超时设置是否合理
- 监控Sandbox使用情况,设置预算告警
- 考虑使用更小的实例规格
python复制def monitor_sandbox_usage():
"""监控Sandbox使用情况的示例"""
from agentrun.sandbox import list_sandboxes
active_sandboxes = list_sandboxes(status="ACTIVE")
print(f"当前活跃Sandbox数量: {len(active_sandboxes)}")
for sb in active_sandboxes:
print(f"ID: {sb.sandbox_id}, 创建时间: {sb.create_time}, 模板: {sb.template_name}")
# 自动清理长时间空闲的实例
if sb.idle_time > datetime.timedelta(hours=1):
sb.delete()
print(f"已清理空闲Sandbox: {sb.sandbox_id}")
9. 实际应用场景示例
9.1 网页数据提取
Browser Sandbox非常适合动态网页的数据抓取任务。以下是一个提取电商产品信息的示例:
python复制def scrape_product_info(url):
"""提取电商产品信息"""
sandbox = SandboxManager().create()
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(sandbox.get_cdp_url())
page = browser.new_page()
# 导航到产品页面
page.goto(url, wait_until="networkidle")
# 提取产品信息
product = {
"title": page.text_content(".product-title"),
"price": page.text_content(".price"),
"description": page.text_content(".description"),
"rating": page.get_attribute(".rating", "data-score"),
"image_url": page.get_attribute(".main-image", "src")
}
# 处理分页评论
reviews = []
while True:
page.wait_for_selector(".review-item")
items = page.query_selector_all(".review-item")
for item in items:
reviews.append({
"user": item.text_content(".user-name"),
"content": item.text_content(".review-content"),
"date": item.text_content(".review-date")
})
# 尝试翻页
next_button = page.query_selector(".next-page")
if not next_button or "disabled" in next_button.get_attribute("class"):
break
next_button.click()
page.wait_for_timeout(1000) # 等待页面加载
browser.close()
return {"product": product, "reviews": reviews}
9.2 自动化测试
Browser Sandbox可以用于Web应用的自动化测试:
python复制def run_web_app_tests():
"""执行Web应用自动化测试"""
sandbox = SandboxManager().create()
test_results = []
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(sandbox.get_cdp_url())
context = browser.new_context()
# 测试登录功能
page = context.new_page()
try:
page.goto("https://yourapp.com/login")
page.fill("#username", "testuser")
page.fill("#password", "password123")
page.click("#login-button")
page.wait_for_selector(".dashboard", timeout=5000)
test_results.append(("登录测试", "通过"))
except Exception as e:
test_results.append(("登录测试", f"失败: {str(e)}"))
finally:
page.close()
# 测试表单提交功能
page = context.new_page()
try:
page.goto("https://yourapp.com/form")
page.fill("#name", "测试用户")
page.select_option("#gender", "male")
page.click("#submit")
page.wait_for_selector(".success-message", timeout=3000)
test_results.append(("表单提交测试", "通过"))
except Exception as e:
test_results.append(("表单提交测试", f"失败: {str(e)}"))
finally:
page.close()
context.close()
sandbox.delete()
return test_results
9.3 内容生成与报告
结合大语言模型,可以自动生成基于网页内容的报告:
python复制def generate_content_report(url, llm):
"""生成网页内容分析报告"""
sandbox = SandboxManager().create()
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(sandbox.get_cdp_url())
page = browser.new_page()
page.goto(url, wait_until="networkidle")
# 提取主要内容
content = {
"title": page.title(),
"headings": page.evaluate("""() => {
return Array.from(document.querySelectorAll('h1, h2, h3'))
.map(h => ({text: h.innerText, level: h.tagName}));
}"""),
"main_text": page.text_content("main") or page.text_content("body"),
"links": page.evaluate("""() => {
return Array.from(document.querySelectorAll('a'))
.map(a => ({text: a.innerText, href: a.href}));
}""")
}
# 使用LLM生成报告
prompt = f"""
请根据以下网页内容生成一份分析报告:
标题:{content['title']}
主要章节:
{content['headings']}
主要内容:
{content['main_text'][:2000]}...
请总结网页的核心主题、关键信息和结构特点。
"""
report = llm.invoke(prompt)
browser.close()
sandbox.delete()
return report
