MultiOn提供了一套API让AI Agent能直接操控浏览器,自动完成网页点击、填表、下单、数据抓取等操作,适合做自动化Agent。这篇文章带你了解它的工作原理、API怎么调用、和传统Selenium爬虫比有啥优势、有哪些限制、怎么处理验证码,适合做浏览器自动化和Agent工具调用的开发者参考。
需要学习MultiOn网页自动化API,了解AI开发工具才能设计技术课程。本篇涵盖LangChain/RAG/Agent、API集成、向量数据库,帮助你构建AI应用系统能力。
目录
可视化演示
\u53ef\u89c6\u5316\u5c55\u793aMultiOn API\u9a71\u52a8\u6d4f\u89c8\u5668\u81ea\u52a8\u5316\u7684\u5b8c\u6574\u6d41\u7a0b\uff0c\u5305\u62ecAPI\u8c03\u7528\u94fe\u8def\u3001\u7f51\u9875\u64cd\u4f5c\u7c7b\u578b\u4e0e\u4e0e\u4f20\u7edfSelenium\u7684\u8303\u5f0f\u5bf9\u6bd4\uff0c\u4ea4\u4e92\u5207\u6362\u89c2\u5bdf\u81ea\u52a8\u5316\u67b6\u6784\u8bbe\u8ba1\u3002
本节配有交互动效(进入视口后自动加载,约 3KB)。
API\u8c03\u7528\u94fe\u8def\u6d41\u7a0b Agent\u53d1\u9001\u81ea\u7136\u8bed\u8a00\u4efb\u52a1\u63cf\u8ff0\u81f3API \u4e91\u7aef\u6d4f\u89c8\u5668\u6267\u884c\u5e76\u8fd4\u56de\u7ed3\u679c Agent \u2192 API \u2192 Browser \u2192 Web \u70b9\u51fb\u6b65\u9aa4\u5207\u6362\u67e5\u770b\u64cd\u4f5c\u7c7b\u578b
MultiOn总览与API驱动架构
MultiOn是一个云端API驱动的浏览器自动化服务,它让AI Agent能够通过简单的HTTP请求来操控浏览器完成各种网页任务。你不需要自己搭建浏览器环境、不需要维护复杂的自动化脚本、不需要处理各种浏览器兼容性问题——只需要调用API描述你想做什么,MultiOn就会在云端帮你执行并返回结果。这就像叫外卖:你不用自己买菜做饭,只需在手机上下单描述想吃什么,餐厅做好后送来给你,省时省力但要付服务费。
MultiOn的架构分为三层。最上层是API网关层,负责接收开发者的HTTP请求、做身份认证和限流、管理会话状态。中间层是Agent决策层,这是MultiOn的核心——它理解你用自然语言描述的任务目标,然后自动规划需要执行哪些操作步骤,比如先点击哪个按钮、再填什么表单、最后怎么提取结果。最底层是浏览器执行层,在云端的真实浏览器中按照规划好的步骤执行操作,并把执行结果和页面状态反馈给决策层。
这种API即服务的模式最大的价值是大幅降低了浏览器自动化的开发门槛。传统方式下,做网页自动化需要你懂Selenium或Playwright、会写选择器、要处理各种页面加载等待、要维护浏览器驱动版本、要解决反爬检测。用MultiOn的话,这些底层的复杂性都被屏蔽了,你只需要关注业务逻辑本身——告诉它你要做什么,它帮你搞定怎么做。对于AI Agent开发者来说,这意味着你可以快速把网页操作能力集成到Agent中,而不需要成为浏览器自动化专家。
当然,这种便利也是有代价的。因为所有操作都在云端执行,所以会有网络延迟,执行速度不如本地运行的Selenium快。而且你依赖第三方服务,服务稳定性和数据隐私都不在自己掌控中。另外,API调用是按量付费的,高频使用的话成本可能不低。所以它最适合的场景是对灵活性和开发速度要求高、对执行速度要求不那么极端的网页自动化任务,比如电商比价、信息收集、表单自动填写这类。
API调用方式与核心接口设计
MultiOn的API采用RESTful设计风格,调用方式简单直接。你只需要发送一个HTTP POST请求,在请求体中用自然语言描述你想完成的任务和目标网址,API就会返回执行结果。请求需要带上你的API密钥做身份认证,响应是JSON格式,包含任务状态、执行结果、提取的数据等信息。整个流程就像调用普通的第三方API一样,没有任何特殊的SDK依赖,任何能发HTTP请求的语言都能用。
核心接口主要有四个。第一个是创建会话接口,用来启动一个新的浏览器会话,你可以指定初始URL、会话参数等。第二个是执行任务接口,这是最常用的——你传入任务描述,MultiOn就会在当前会话中执行这个任务。第三个是查询状态接口,因为有些任务可能需要执行一段时间,你可以用这个接口轮询任务执行进度。第四个是获取结果接口,任务完成后用它获取结构化的执行结果和提取的数据。这四个接口配合起来就能完成从启动到执行到获取结果的完整流程。
调用模式有同步和异步两种。同步调用就是你发请求后一直等着,API执行完直接返回结果,优点是简单直接,适合短任务。异步调用是你发请求后立刻拿到一个任务ID,然后你自己去轮询任务状态,等任务完成了再取结果,优点是不会阻塞你的程序,适合长任务。实际用的时候看任务复杂度来选——简单的信息提取用同步,复杂的多步骤操作用异步。
会话管理也是一个重要的设计。MultiOn支持在同一个浏览器会话中连续执行多个任务,保持登录状态和页面上下文。比如你先调用登录任务,登录成功后会话里就有了登录态,接下来的任务都在已登录的状态下执行。这对于需要登录的网站特别重要。会话有超时机制,一段时间不活动会自动关闭释放资源,你也可以主动关闭会话。用好会话管理可以减少重复登录的开销,提高多步骤任务的执行效率。
import requestsimport time class MultiOnClient: """MultiOn API 客户端示例""" def __init__(self, api_key: str): self.api_key = api_key self.base_url = "https://api.multion.ai/v1" self.headers = { "X-MULTION-API-KEY": api_key, "Content-Type": "application/json" } def create_session(self, url: str) -> str: """创建新的浏览器会话,返回会话ID""" response = requests.post( f"{self.base_url}/session", headers=self.headers, json={"url": url} ) response.raise_for_status() return response.json()["session_id"] def execute_task( self, session_id: str, task: str, mode: str = "standard" ) -> dict: """在指定会话中执行任务(同步模式)""" response = requests.post( f"{self.base_url}/session/{session_id}/task", headers=self.headers, json={ "task": task, "mode": mode } ) response.raise_for_status() return response.json() def close_session(self, session_id: str): """关闭会话""" requests.delete( f"{self.base_url}/session/{session_id}", headers=self.headers ) # 使用示例client = MultiOnClient("your-api-key-here")session_id = client.create_session("https://example.com")result = client.execute_task( session_id, "找到页面上的所有产品名称和价格,以JSON格式返回")print(f"提取结果: {result.get('extracted_data')}")client.close_session(session_id)
网页操作执行与任务自动化能力
MultiOn能执行的网页操作类型非常丰富。最基本的是点击操作——它能理解你说的“点击搜索按钮”是什么意思,自动找到页面上对应的按钮并点击。然后是表单填写——你告诉它“在用户名框输入xxx”,它就能找到对应的输入框填入内容。还有数据提取——你说“把表格里的产品名和价格提取出来”,它能识别表格结构并返回结构化的数据。这些操作组合起来就能完成很复杂的任务。
多步骤复杂流程是MultiOn的强项。比如电商比价任务:你说“在这五个电商网站上搜索iPhone 15,找出最便宜的那个”,MultiOn的Agent决策层会自动把这个大任务拆分成多个小步骤——先打开第一个网站、搜索商品、记录价格、再打开第二个网站重复,最后汇总比价。整个过程不需要你一步步指挥,它自己规划步骤自己执行。这种能力对于需要跨多个页面、多个网站的复杂任务特别有价值。
结果返回是结构化的。MultiOn不只是告诉你任务完成了,它还能根据你的要求返回特定格式的数据。比如你说“返回JSON格式,包含product_name、price、rating三个字段”,它就会真的返回一个结构工整的JSON对象,你可以直接存数据库或者展示给用户。这种结构化返回对于应用集成非常重要——你不需要自己去解析HTML或者从自然语言结果里抠数据,API直接给你能用的数据。
任务完成判断也是自动的。MultiOn的Agent会判断任务什么时候算做完了,而不是死板地执行固定步骤。比如你让它“找到最便宜的商品并下单”,它会比较价格、选择最低价、填写表单、确认订单,直到整个下单流程走完才返回完成。如果遇到意外情况,比如商品缺货、页面加载失败,它也会识别出来并在结果中告诉你出了什么问题。这种自主判断能力是传统脚本化自动化不具备的。
与传统Selenium爬虫的对比优势
MultiOn和传统的Selenium/Playwright自动化最大的区别在于开发范式。Selenium是指令式的——你得告诉它每一步具体怎么做:先找id为search的输入框、输入关键词、再找class为btn的按钮、点击它。网页一改版,选择器变了,你的脚本就挂了,得重新维护。MultiOn是目标式的——你只需要告诉它你想要什么结果,它自己决定怎么达到目标。就像自己开车和叫出租车的区别:自己开车需要会驾驶会保养,叫出租车说目的地就行,出租车更方便但速度可能不如自己开快。
第一个核心优势是无需维护选择器。传统Selenium脚本最大的维护成本就是选择器——网站前端一改版,你的CSS选择器或XPath就失效了,得一个个改。MultiOn用AI理解页面内容,它看的是页面上有什么元素、元素是做什么用的,而不是依赖固定的选择器。所以即使网站改版了,只要功能还在,MultiOn大概率还是能完成任务,不需要你改代码。这对于经常变化的网站来说,维护成本的差异是数量级的。
第二个核心优势是自然语言描述任务的低门槛。用Selenium你得是个会写代码、会选选择器、懂页面结构的开发者。用MultiOn的话,哪怕你不太懂编程,只要能用自然语言说清楚你想做什么,就能实现自动化。当然也不是完全零代码——你还是需要写API调用的代码、处理响应数据、设计业务逻辑,但相比Selenium,开发难度和所需的专业知识门槛确实低了很多。
代价也是有的。首先是速度,云端执行加上AI决策,MultiOn比本地Selenium慢,特别是复杂任务,可能要等几十秒甚至几分钟。其次是成本,API按调用量收费,大规模使用的话费用不低。再次是可控性,黑盒执行,你不知道它具体点了哪里、为什么失败了,调试起来不如自己写的脚本方便。还有数据隐私,你的操作数据和页面内容都会经过MultiOn的服务器,敏感场景要慎重。所以选择的时候要根据场景权衡——快速原型、低频复杂任务适合MultiOn,高性能高频简单任务还是Selenium更合适。
限制约束与验证码处理方案
MultiOn虽然强大,但也不是万能的,它有不少使用限制需要注意。首先是并发限制,免费版和基础版套餐对同时执行的任务数量有限制,不能无限并发。其次是单任务时长限制,每个任务有最长执行时间,超时会被强制终止,特别复杂的长任务可能需要拆分成多个小任务。还有使用频率限制,API调用有速率上限,不能无限制地高频调用。这些限制在使用之前要了解清楚,做技术选型的时候要评估是否满足你的业务需求。
验证码是网页自动化的老大难问题,MultiOn也不例外。它的处理策略是自动识别加人工接管的组合方式。简单的验证码比如图形验证码、简单的算术题,系统可以自动识别和填写。复杂的验证码比如Google reCAPTCHA、滑块验证、手机短信验证这些,MultiOn不会强行绕过——它会暂停任务,通知开发者需要人工介入,等人手动完成验证后任务再继续执行。这种设计既保证了基本场景的自动化能力,又遵守了网站的安全机制,不会去做恶意绕过的事情。
操作合规性是MultiOn非常强调的一点。平台明确禁止用它做恶意爬虫、账号批量注册、刷单炒信、抢票囤货这些违反网站服务条款的行为。它有检测机制来识别违规使用,发现了会封禁账号。这一点很重要——技术能力越强,越需要合规使用。开发者在集成MultiOn的时候,要确保你的使用场景符合目标网站的服务条款,也符合MultiOn的使用规范,不要踩到合规红线。
还有一些其他的边界限制需要了解。比如不是所有网站都能完美支持,一些特别小众的技术栈或者高度定制化的页面可能识别不准。比如需要浏览器插件或者特殊客户端证书的网站可能不支持。比如文件上传下载这类操作的支持程度可能有限。实际使用的时候,建议先拿你的目标网站做个POC验证,确认MultiOn能稳定完成你的任务再大规模投入开发。毕竟它是黑盒服务,具体能力边界还是要实测了才知道。
AI 应用场景
Agent工具调用集成网页操作
阶段:模型部署
解决的问题:AI Agent需要操控浏览器完成网页任务但自行搭建浏览器自动化环境复杂且维护成本高,需要开箱即用的API服务
具体案例:AI助手开发者将MultiOn API集成为Agent的一个工具调用,当用户要求帮我搜索并下单一本书时,Agent调用MultiOn API传入任务描述,MultiOn在云端自动打开图书电商网站搜索指定书名,比价后选择最低价商家自动填写收货信息下单,Agent收到结果后向用户确认订单详情,全程用户只需自然语言交互
批量网页数据抓取服务
阶段:数据工程
解决的问题:传统爬虫面对反爬机制和动态渲染页面时容易失效,且不同网站需要编写不同解析规则维护成本高
具体案例:市场调研团队使用MultiOn API批量抓取多个行业网站的最新产品信息,通过自然语言描述采集需求,MultiOn自动在各网站导航到产品页面提取名称、价格、规格等字段,遇到反爬机制自动调整策略,遇到验证码暂停等待人工处理,最终返回统一格式的结构化数据集供分析使用,新网站接入只需修改任务描述无需开发解析代码
Python 演示
# -*- coding: utf-8 -*-"""MultiOn API 客户端演示展示:会话管理、任务执行、状态轮询、结果提取、错误处理"""import requestsimport timefrom typing import Optional, Dict, Listfrom dataclasses import dataclass, fieldimport json @dataclassclass TaskResult: """任务执行结果""" success: bool status: str extracted_data: Dict = field(default_factory=dict) message: str = "" execution_time: float = 0.0 class MultiOnAPIClient: """MultiOn API 客户端封装(模拟实现,用于演示调用流程)""" def __init__(self, api_key: str, base_url: str = "https://api.multion.ai/v1"): self.api_key = api_key self.base_url = base_url self.session = requests.Session() self.session.headers.update({ "X-MULTION-API-KEY": api_key, "Content-Type": "application/json" }) self.active_sessions: Dict[str, Dict] = {} # 活跃会话记录 def create_session(self, initial_url: str, **kwargs) -> str: """创建新的浏览器会话 Args: initial_url: 初始打开的网址 kwargs: 其他会话参数(如视口大小、用户代理等) Returns: 会话ID """ payload = {"url": initial_url} payload.update(kwargs) try: response = self.session.post( f"{self.base_url}/session", json=payload, timeout=30 ) response.raise_for_status() data = response.json() session_id = data["session_id"] # 记录会话信息 self.active_sessions[session_id] = { "url": initial_url, "created_at": time.time(), "status": "active" } print(f"✓ 会话创建成功: {session_id}") return session_id except requests.exceptions.RequestException as e: print(f"✗ 会话创建失败: {e}") raise def execute_task_sync( self, session_id: str, task_description: str, output_format: Optional[str] = None, timeout: int = 120 ) -> TaskResult: """同步执行任务(等待完成后返回结果) Args: session_id: 会话ID task_description: 自然语言任务描述 output_format: 期望的输出格式(如json、table等) timeout: 超时时间(秒) Returns: TaskResult 对象 """ start_time = time.time() payload = {"task": task_description} if output_format: payload["output_format"] = output_format print(f" 执行任务: {task_description[:50]}...") try: response = self.session.post( f"{self.base_url}/session/{session_id}/task", json=payload, timeout=timeout ) response.raise_for_status() data = response.json() result = TaskResult( success=data.get("status") == "success", status=data.get("status", "unknown"), extracted_data=data.get("extracted_data", {}), message=data.get("message", ""), execution_time=time.time() - start_time ) status_icon = "✓" if result.success else "✗" print(f" {status_icon} 任务完成: {result.status} ({result.execution_time:.1f}s)") return result except requests.exceptions.Timeout: return TaskResult( success=False, status="timeout", message=f"任务执行超时({timeout}秒)" ) except requests.exceptions.RequestException as e: return TaskResult( success=False, status="error", message=f"请求失败: {str(e)}" ) def execute_task_async(self, session_id: str, task_description: str) -> str: """异步执行任务(立即返回任务ID,后续轮询状态) Returns: 任务ID """ response = self.session.post( f"{self.base_url}/session/{session_id}/task/async", json={"task": task_description} ) response.raise_for_status() task_id = response.json()["task_id"] print(f" 异步任务已提交: {task_id}") return task_id def get_task_status(self, session_id: str, task_id: str) -> Dict: """查询异步任务状态""" response = self.session.get( f"{self.base_url}/session/{session_id}/task/{task_id}" ) response.raise_for_status() return response.json() def wait_for_task( self, session_id: str, task_id: str, max_wait: int = 300, poll_interval: int = 3 ) -> TaskResult: """等待异步任务完成(轮询方式)""" start_time = time.time() while time.time() - start_time < max_wait: status_data = self.get_task_status(session_id, task_id) status = status_data.get("status") if status in ("success", "failed", "error"): return TaskResult( success=status == "success", status=status, extracted_data=status_data.get("extracted_data", {}), message=status_data.get("message", ""), execution_time=time.time() - start_time ) print(f" 任务进行中... ({status}) 已等待{time.time() - start_time:.0f}s") time.sleep(poll_interval) return TaskResult( success=False, status="timeout", message=f"等待任务超时({max_wait}秒)" ) def close_session(self, session_id: str) -> bool: """关闭会话""" try: self.session.delete( f"{self.base_url}/session/{session_id}", timeout=10 ) if session_id in self.active_sessions: del self.active_sessions[session_id] print(f"✓ 会话已关闭: {session_id}") return True except requests.exceptions.RequestException as e: print(f"✗ 会话关闭失败: {e}") return False def list_active_sessions(self) -> List[str]: """列出当前活跃会话""" return list(self.active_sessions.keys()) # ===================== 电商比价演示场景 ===================== def demo_ecommerce_price_comparison(): """演示:使用MultiOn API进行电商比价""" print("=" * 60) print(" MultiOn API 演示:电商比价场景") print("=" * 60) # 注意:实际使用时替换为真实API密钥 client = MultiOnAPIClient(api_key="your-api-key-here") # 模拟演示(因为没有真实API密钥,展示调用流程) print("\n【流程说明】") print(" 1. 创建浏览器会话") print(" 2. 依次访问各电商网站搜索商品") print(" 3. 提取商品名称、价格、评分等信息") print(" 4. 汇总比价结果,返回结构化数据") print() # 展示一个完整的多步骤任务示例 print("【示例:多步骤电商比价任务】") task_example = ''' 任务描述: 请在以下三个电商网站上搜索"无线蓝牙耳机": 1. 京东 (jd.com) 2. 淘宝 (taobao.com) 3. 拼多多 (pinduoduo.com) 对每个网站,提取前5个商品的: - 商品名称 - 价格 - 评分 - 销量 最后按价格从低到高排序,返回JSON格式结果。 ''' print(task_example) print("【返回结果示例】") sample_result = { "results": [ {"platform": "拼多多", "product": "XX无线蓝牙耳机", "price": 99.0, "rating": 4.5, "sales": "10万+"}, {"platform": "淘宝", "product": "YY无线蓝牙耳机", "price": 129.0, "rating": 4.7, "sales": "5万+"}, {"platform": "京东", "product": "ZZ无线蓝牙耳机", "price": 149.0, "rating": 4.8, "sales": "3万+"}, ], "cheapest": {"platform": "拼多多", "product": "XX无线蓝牙耳机", "price": 99.0} } print(json.dumps(sample_result, ensure_ascii=False, indent=2)) print(f"\n{'=' * 60}") print(" 核心要点") print(f"{'=' * 60}") print(" 1. 会话管理:创建/查询/关闭,保持状态连续性") print(" 2. 同步调用:简单任务直接等待返回") print(" 3. 异步调用:复杂任务轮询状态不阻塞") print(" 4. 自然语言:用自然语言描述任务,AI自动规划执行") print(" 5. 结构化输出:按指定格式返回数据,直接可用") print(" 6. 错误处理:超时、网络异常、任务失败的优雅处理") print(f"{'=' * 60}") def demo_integration_patterns(): """演示:常见集成模式""" print("\n" + "=" * 60) print(" 常见集成模式") print("=" * 60) patterns = [ { "模式": "Agent工具调用", "场景": "AI Agent需要网页操作能力时", "方式": "将MultiOn封装为LangChain Tool,Agent按需调用", "适用": "通用AI助手、自动化工作流" }, { "模式": "批量数据采集", "场景": "需要从多个网站提取结构化数据", "方式": "任务队列 + 异步调用 + 结果汇总", "适用": "市场调研、竞品分析、价格监控" }, { "模式": "表单自动填写", "场景": "需要重复填写各种在线表单", "方式": "传入表单数据和URL,自动填写提交", "适用": "报名、注册、订单提交" }, { "模式": "端到端测试", "场景": "Web应用的自动化测试", "方式": "用自然语言描述测试用例,自动执行验证", "适用": "快速测试验证、QA辅助" } ] for p in patterns: print(f"\n 【{p['模式']}】") print(f" 场景: {p['场景']}") print(f" 方式: {p['方式']}") print(f" 适用: {p['适用']}") print(f"\n{'=' * 60}") if __name__ == "__main__": demo_ecommerce_price_comparison() demo_integration_patterns()
class MultiOnAPIClient:定义MultiOn API客户端主类,封装所有API调用逻辑和会话管理self.session = requests.Session()使用requests.Session保持连接池和请求头,提高多次API调用的性能def create_session(self, initial_url: str, **kwargs) -> str:创建浏览器会话方法,指定初始URL,返回会话ID用于后续操作response = self.session.post(发送HTTP POST请求到API端点,这是REST API调用的标准方式response.raise_for_status()检查HTTP响应状态码,如果是4xx/5xx错误则抛出异常,统一错误处理def execute_task_sync(同步任务执行方法,发送任务描述后一直等待,执行完成直接返回结果result = TaskResult(将API响应封装为TaskResult数据类,提供结构化的结果访问接口except requests.exceptions.Timeout:捕获超时异常并优雅处理,返回明确的超时状态而非直接崩溃def execute_task_async(self, session_id: str, task_description: str) -> str:异步任务执行方法,提交任务后立即返回任务ID,不阻塞主程序def get_task_status(self, session_id: str, task_id: str) -> Dict:查询异步任务状态的方法,配合轮询实现异步等待def wait_for_task(等待异步任务完成的辅助方法,通过轮询机制实现,支持最大等待时间time.sleep(poll_interval)轮询间隔控制,避免请求过于频繁,减少API调用压力def close_session(self, session_id: str) -> bool:关闭会话方法,释放云端浏览器资源,养成用完就关的好习惯def list_active_sessions(self) -> List[str]:列出活跃会话的辅助方法,方便会话管理和资源监控def demo_ecommerce_price_comparison():电商比价演示函数,展示MultiOn API在实际业务场景中的典型应用流程
常见问答
MultiOn和Selenium有什么本质区别?
MultiOn真的完全不需要写代码吗?
MultiOn能绕过所有网站的验证码吗?
常见误区
误区MultiOn API可以无限制地高频调用执行任务
正解MultiOn对API调用有并发数和单任务时长等限制,高频批量调用需要合理规划请求频率和任务队列,超出限制会被限流或拒绝服务
为何常见:API服务通常以能力宣传为主,使用限制细节在文档深处,开发者初次使用时容易忽略速率限制
误区MultiOn能自动绕过所有网站的验证码和安全检测
正解MultiOn对复杂验证码采用人工接管而非自动绕过策略,且平台要求操作合规,不会无限制地突破网站安全机制,验证码仍是网页自动化的边界之一
为何常见:自动化工具常被误解为万能破解工具,加上部分同类产品宣传绕过能力,容易对合规边界产生错误预期
误区MultiOn API完全替代了Selenium无需任何代码开发
正解MultiOn降低了浏览器自动化的开发门槛但仍需要编写API调用代码、处理响应数据、设计任务逻辑等开发工作,它是简化而非消除了开发,复杂场景仍需编程能力
为何常见:自然语言描述任务的宣传容易让人以为完全免代码,实际只是将选择器维护工作转化为API调用开发
参考来源
- docMultiOn API DocumentationMultiOn官方API文档,介绍了浏览器自动化API的接口设计和使用方法。
- docSelenium DocumentationSelenium官方文档,传统浏览器自动化框架的参考标准,用于对比分析。
- docLangChain - MultiOn Tool IntegrationLangChain官方文档中MultiOn工具集成的说明,展示了Agent如何调用MultiOn。