示例:基于SDK的浏览器工具开发与应用实践
本示例介绍如何完全通过编写代码脚本,一次性自动完成浏览器沙箱的创建与Agent的开发。
示例中分为两个阶段,先通过agentarts sdk创建浏览器沙箱,再创建Agent并调用沙箱完成任务。
基于SDK的工具开发与应用实践
- 安装python。请确保Python 3.10及以上版本已安装。 大多数Linux发行版(如Ubuntu)都预装了Python,您可以先通过python3 --version检查。如未安装,可以使用如下命令安装:
sudo apt update sudo apt install python3
- 创建虚拟环境。 执行以下命令创建虚拟环境(建议在Python虚拟环境中安装,以避免与系统包产生冲突)。
# 创建并激活虚拟环境 (linux) python3 -m venv venv source venv/bin/activate
- 安装必要的库。在您的Linux服务器的终端中,运行以下命令安装agentarts-sdk、langgraph、langchain_openai包。
# 安装agentarts-sdk包 pip install agentarts-sdk # 安装langgraph包 pip install langgraph # 安装langchain_openai包 pip install langchain-openai
- 配置管理面环境变量。
# === 用于通过代码创建浏览器沙箱 === export HUAWEICLOUD_SDK_AK="您的华为云AK" export HUAWEICLOUD_SDK_SK="您的华为云SK" export AGENTARTS_CONTROL_ENDPOINT="https://agentarts.cn-southwest-2.myhuaweicloud.com"
- 创建浏览器沙箱脚本。
新建一个Python文件,用于创建浏览器沙箱(例如browser_sandbox.py)并填写以下代码。
导入浏览器工具及其他包:
import json import os from typing import Annotated, TypedDict from langchain_core.messages import AIMessage, BaseMessage, HumanMessage, SystemMessage from langchain_core.tools import tool from langchain_openai import ChatOpenAI from langgraph.graph import END, StateGraph from langgraph.graph.message import add_messages from langgraph.prebuilt import ToolNode from agentarts.sdk import AgentArtsRuntimeApp from agentarts.sdk.tools import browser_session app = AgentArtsRuntimeApp()
继续填写如下代码,用于创建浏览器沙箱(创建的浏览器入站身份方式为API Key认证):
from agentarts.sdk.tools import Browser def create(): print("开始创建浏览器沙箱,请稍等...") client = Browser(region="cn-southwest-2", auth_type="API_KEY") browser = client.create_browser( name="填写一个浏览器名称", auth_type="API_KEY", api_key_name="填写一个API Key的名称", description="浏览器沙箱工具描述", execution_agency_name="填写IAM委托名称", agent_gateway_id="填写Agent Gateway ID", network_config={"network_mode": "PUBLIC"}, ) print("浏览器沙箱创建成功!快去控制台刷新看看吧。") # 打印出创建结果的详细信息 print(browser) if __name__ == '__main__': create()代码中的参数说明:
- 浏览器名称:以小写字母开头,小写字母或数字结尾,中间可包含数字、小写字母、中划线。字符数:2-40。
- API Key名称:只能包含英文字母、数字、下划线(_)或中划线(-),长度1-64。
- execution_agency_name:IAM委托名称,请根据您的实际配置填写。
- agent_gateway_id:Agent Gateway的ID,可在AgentArts平台的网关管理页面获取。
- network_config:网络模式,PUBLIC为公网访问,VPC为私网访问。
- 执行创建脚本。
执行python browser_sandbox.py创建浏览器沙箱。
浏览器沙箱工具创建需要时间拉起,拉起时间大约为5s。创建完成后,可以在AgentArts平台看到创建好的浏览器沙箱工具。

- 获取浏览器沙箱信息。
浏览器沙箱创建完成后,在列表可查看已创建的浏览器沙箱的名称。记录该名称,并获取该沙箱工具的域名、API Key。
沙箱工具的域名、API Key获取方法如下:
- 单击沙箱工具名称。
- 进入"配置信息"页面后,获取域名。 图1 获取沙箱域名
- 单击"URN"链接,在弹出的窗口中获取沙箱的API Key。 图2 URN链接
图3 获取沙箱API Key
- 配置环境变量。
export AGENTARTS_BROWSER_DATA_ENDPOINT="http://您的浏览器沙箱域名" export MODEL_API_KEY="您的大模型API密钥" export BASE_URL="https://api.modelarts-maas.com/openai/v1"
其中,AGENTARTS_BROWSER_DATA_ENDPOINT请配置为http://{浏览器沙箱域名},获取方法请参考前面的步骤。
由于示例中使用华为云MaaS服务中的模型,因此需要登录MaaS服务创建API Key。
https://api.modelarts-maas.com/openai/v1表示使用OpenAI兼容接口。
- 新建一个Python代码文件(例如browser_app.py)将以下步骤的代码脚本按照顺序组合进去。
导入浏览器工具及其他包:
import json import os from typing import Annotated, TypedDict from langchain_core.messages import AIMessage, BaseMessage, HumanMessage, SystemMessage from langchain_core.tools import tool from langchain_openai import ChatOpenAI from langgraph.graph import END, StateGraph from langgraph.graph.message import add_messages from langgraph.prebuilt import ToolNode from agentarts.sdk import AgentArtsRuntimeApp from agentarts.sdk.tools import browser_session app = AgentArtsRuntimeApp()
- 编写工具包装代码。
代码文件中填写如下脚本。用于将"连接浏览器沙箱并浏览网页"这一操作包装成一个标准的函数工具。当Agent中的大模型发现需要浏览网页时,会将目标网址传递给这个工具,工具会将网址发送到浏览器沙箱执行导航,再把页面信息拿回来给大模型。
@tool def browse_webpage(url: str, description: str = "") -> str | None: """Browse a webpage and retrieve its page information in the browser sandbox""" api_key = "替换为获取的浏览器沙箱API Key" # your api key with browser_session( "cn-southwest-2", "替换为创建的浏览器沙箱名称", "agent-browser-session", api_key=api_key, verify_ssl=False, ) as browser_client: browser_client.navigate(url=url, api_key=api_key) page_info = browser_client.get_page_info(api_key=api_key) return json.dumps(page_info) - 编写系统提示词。
代码文件中添加如下代码,用于编写系统提示词。
SYSTEM_PROMPT = """你是一个AI助手,可以使用浏览器工具来浏览网页并获取信息。 可用工具: - browse_webpage(url: str, description: str): 在浏览器沙箱中打开网页并获取页面信息 使用原则: 1. 当用户需要获取网页内容、查看页面信息时使用此工具 2. 简单问题直接回答,无需工具验证 3. 工具调用最多1-2次,避免重复访问 4. 获得结果后立即返回答案 """
- 定义Agent。
代码文件中添加如下代码,用于定义一个Agent并集成浏览器沙箱。
示例中使用deepseek-v4-flash模型,如果需要更换其他模型,请登录MaaS服务,获取模型接口的model参数值(注意代码使用了OpenAI格式的调用方法,需获取对应格式的model参数值)。
图4 获取MaaS服务model参数值
# 创建Agent llm = ChatOpenAI( model="deepseek-v4-flash", api_key=os.environ.get("MODEL_API_KEY", ""), base_url=os.environ.get("BASE_URL", ""), max_tokens=1000, temperature=0.7, ) # 创建工具列表 tools = [browse_webpage] # 工具绑定Agent llm = llm.bind_tools(tools) # 定义graph状态 class AgentState(TypedDict): messages: Annotated[list[BaseMessage], add_messages] def call_model(state: AgentState): """调用模型并返回响应""" if not state["messages"] or all( not isinstance(msg, SystemMessage) for msg in state["messages"] ): messages = [SystemMessage(content=SYSTEM_PROMPT)] + state["messages"] else: messages = state["messages"] response = llm.invoke(messages) return {"messages": [response]} def should_continue(state): """判断是否继续使用工具""" last_message = state["messages"][-1] if isinstance(last_message, AIMessage): has_tool_calls = bool(last_message.tool_calls) if has_tool_calls: return "tools" return END # 创建LangGraph工作流 workflow = StateGraph(AgentState) workflow.add_node("agent", call_model) workflow.add_node("tools", ToolNode(tools)) # 设置入口 workflow.set_entry_point("agent") # 添加边 workflow.add_conditional_edges("agent", should_continue, {"tools": "tools", "__end__": "__end__"}) workflow.add_edge("tools", "agent") agent = workflow.compile() - 拼接服务器代码。
拼接以下代码,用于使用Agent启动一个本地服务器,并提供一个对外接收提问的接口。
@app.entrypoint def agent_chat(payload: dict): query = "帮我访问 https://example.com 并告诉我页面标题" # 运行Agent result = agent.invoke({ "messages": [HumanMessage(content=query)] }) return result["messages"][-1].content if __name__ == '__main__': app.run() - 运行并测试。
在服务器中执行python browser_app.py命令运行示例代码(如果在创建Python代码文件时使用了其他名称,请按实际名称执行)。
- 打开一个新的终端窗口(保持原窗口运行),使用curl命令进行测试。测试完成后,可以使用Ctrl + C停止运行的进程。
上述步骤中已经在代码里面内置了问题"帮我访问 https://example.com 并告诉我页面标题",Agent会将该浏览网页的过程放到浏览器沙箱中运行,并返回页面信息结果。
curl --location http://localhost:8080/invocations --data-raw "{}"