ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

OpenClaw 函数定义实战:龙虾智能体自定义函数的创建与调用方法

OpenClaw 函数定义实战:龙虾智能体自定义函数的创建与调用方法 1. OpenClaw 函数定义到底解决什么问题OpenClaw 函数定义说白了就是给龙虾智能体装上一双能干活的手。默认的智能体只会聊天、只会根据上下文生成文字但你要让它查数据库、调天气接口、算一段业务逻辑、把结果写回工单系统就必须靠自定义函数把外部能力挂进去。OpenClaw 的函数定义机制就是描述“这个函数叫什么、接收什么参数、返回什么结构、什么时候该被模型调用”的一整套声明。它适合谁适合已经跑通 OpenClaw 基础对话、想让智能体从“会说”变成“会做”的开发者。典型场景有三类一是数据类比如根据订单号查状态、根据用户 ID 拉画像二是动作类比如创建工单、发送通知、写入表格三是计算类比如汇率换算、日期推算、规则校验。这些能力如果全靠提示词硬编模型会不稳定写成函数定义后模型只在需要时调用参数由框架校验结果结构化返回整条链路可控得多。我试过把一个“查库存”的逻辑塞进系统提示词里模型十次有三次会编造库存数字。改成函数定义后模型只负责判断“用户问的是库存”真正数字由函数返回准确率立刻上来了。这就是函数定义的核心价值把不确定的语言生成收敛到确定的代码执行。这一篇会带你走完从函数注册到实际调用的闭环并且用 TaoToken 统一 Key 和 API 通道来承接模型侧请求避免你在多个平台之间来回切换配置。2. 接入前的准备TaoToken 统一 Key 与通道在写函数之前先把模型调用这条链路理顺。OpenClaw 的函数调用依赖模型返回结构化的 tool call 指令所以模型通道必须稳定、兼容 OpenAI 风格的接口。TaoToken 在这里的角色是统一入口你只需要一个 Key就能通过同一套 API 地址访问不同模型函数定义里的模型配置不用为每个供应商单独改。先到官网了解整体能力https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。注册后在控制台创建 Key控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 。Key 的管理页面在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 建议给 OpenClaw 单独建一个 Key方便按项目统计用量和随时吊销。API 基础地址统一用 https://taotoken.net/api 注意这个地址不带任何查询参数直接作为 base_url 填进配置即可。如果你要确认某个模型是否支持函数调用tool use可以到模型对话页面先手动试一轮https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。不是所有模型都支持 tool call选之前先确认否则函数定义写了也不会被触发。注意函数调用能力取决于具体模型配置前先在模型对话里发一条带 tools 的请求验证能返回 tool_calls 字段的才可用。环境变量建议这样组织避免 Key 硬编码进代码export TAOTOKEN_API_KEYsk-你的Key export TAOTOKEN_BASE_URLhttps://taotoken.net/apiPython 侧读取时用 os.environ不要写死在函数定义文件里。这一步做完模型通道就通了接下来才是函数本身的创建。3. 可复制的函数定义配置骨架OpenClaw 的函数定义通常由三部分组成函数元信息name、description、参数 schemaJSON Schema 描述、实际执行体Python 函数。元信息决定模型“什么时候调”schema 决定“参数怎么传”执行体决定“真正做什么”。三者缺一不可description 写得越清楚模型误调用的概率越低。先看一个最小可用的函数定义骨架保存为functions/inventory.pyimport os import json from openclaw import Agent, FunctionRegistry registry FunctionRegistry() registry.define( namequery_inventory, description根据商品SKU查询当前可用库存数量用户询问某商品是否有货时调用, parameters{ type: object, properties: { sku: { type: string, description: 商品SKU编码例如 SKU-10023 }, warehouse: { type: string, description: 仓库代码可选默认全部仓库, enum: [BJ, SH, GZ, ALL] } }, required: [sku] } ) def query_inventory(sku: str, warehouse: str ALL) - dict: # 这里替换成你真实的查询逻辑 mock_db { SKU-10023: {BJ: 12, SH: 0, GZ: 5}, SKU-10088: {BJ: 0, SH: 30, GZ: 0}, } stock mock_db.get(sku, {}) if warehouse ALL: total sum(stock.values()) return {sku: sku, available: total, detail: stock} return {sku: sku, available: stock.get(warehouse, 0), warehouse: warehouse}关键点有三个。第一description要写成“用户问什么时调用”而不是“这个函数做了什么”模型是靠这句话做路由的。第二parameters用标准 JSON Schemarequired明确哪些必填enum限制取值范围能大幅减少模型传错参数。第三执行体返回 dict框架会自动序列化成模型能读的 JSON。再定义一个动作类函数演示多函数注册registry.define( namecreate_ticket, description当用户明确要求提交问题或报修时创建一条工单记录, parameters{ type: object, properties: { title: {type: string, description: 工单标题}, priority: {type: string, enum: [low, medium, high]}, detail: {type: string, description: 问题详细描述} }, required: [title, priority] } ) def create_ticket(title: str, priority: str, detail: str ) - dict: ticket_id fT{abs(hash(title)) % 100000:05d} return {ticket_id: ticket_id, status: created, priority: priority}把函数注册进智能体并接上 TaoToken 通道agent Agent( name龙虾助手, modelgpt-4o-mini, api_keyos.environ[TAOTOKEN_API_KEY], base_urlos.environ[TAOTOKEN_BASE_URL], functionsregistry )到这里函数定义配置骨架就完整了。registry负责收集所有函数Agent初始化时把 registry 传进去模型侧就能看到这些工具。4. 调用验证从注册到实际触发配置写完必须验证否则你不知道模型到底有没有调用函数。验证分两步先看函数是否被正确注册再看模型是否真的触发调用。第一步打印注册表内容print(json.dumps(registry.list_specs(), ensure_asciiFalse, indent2))正常输出应该包含query_inventory和create_ticket两个条目每个都有 name、description、parameters。如果这里为空说明装饰器没生效或者 registry 没传进 Agent。第二步发一条会触发函数的消息resp agent.chat(帮我查一下 SKU-10023 还有多少库存) print(resp.content) print(resp.tool_calls)预期结果是resp.tool_calls里出现query_inventory参数为{sku: SKU-10023}然后框架执行函数并把结果回传给模型最终resp.content会是一句自然语言回答比如“SKU-10023 当前总库存 17 件其中北京 12 件、广州 5 件、上海 0 件”。再验证动作类函数resp2 agent.chat(我这边打印机坏了帮我提个高优先级工单标题写打印机故障) print(resp2.tool_calls) print(resp2.content)预期tool_calls里出现create_ticketpriority 为 high。如果模型没调用而是直接编了一段“已为你创建工单”说明 description 不够明确或者模型本身不支持 tool call回到模型对话页面换一个支持函数调用的模型再试。提示验证阶段建议把debugTrue打开OpenClaw 会打印每次 tool call 的原始请求和返回排障时非常省事。5. 本篇常见错误排查函数定义写完后最常见的报错集中在三类注册失败、参数校验失败、模型不调用。注册失败通常表现为FunctionRegistry里没有目标函数。原因多是装饰器顺序写错或者registry.define写在了staticmethod下面。检查方式是单独 import 该模块并打印registry.list_specs()。另一个坑是函数名重复两个函数用了同一个 name后注册的会覆盖前一个日志里一般有 warning别忽略。参数校验失败会返回类似invalid arguments for query_inventory: sku is a required property。这多半是模型传参时漏了必填字段或者类型不对。解决办法是在 description 里把参数含义写得更具体同时在执行体开头加一层兜底def query_inventory(sku: str, warehouse: str ALL) - dict: if not sku or not isinstance(sku, str): return {error: sku 参数无效, received: str(sku)} ...模型不调用函数是最隐蔽的问题。表现是模型直接回答tool_calls为空。排查顺序先确认模型支持 tool call再确认functionsregistry确实传进了 Agent最后检查 description 是否写成了“查询库存”这种模糊描述改成“用户询问商品是否有货、库存数量时调用”这类触发条件描述。如果还不行在系统提示里加一句“涉及库存和工单的问题必须调用对应函数不要自行编造”通常能解决。还有一个容易踩的坑是 base_url 写错。有人把https://taotoken.net/api写成了带路径的地址导致请求 404。记住 API 地址就是https://taotoken.net/api不要自己拼/v1之类的后缀框架会处理。6. 继续深入与通道选择函数定义跑通之后下一步通常是两类需求一类是函数越来越多需要分类管理和权限控制另一类是智能体要长期跑编码、Agent 类任务对调用稳定性和额度有更高要求。前者靠 registry 分组和命名规范解决后者可以考虑 Coding Plan地址是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 适合需要持续调用、批量任务的场景。如果你在接入过程中遇到 Key 或通道问题直接看接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有针对 OpenClaw 这类框架的 base_url 和鉴权说明。需要新建或轮换 Key 时去 API Keys 页面操作https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。想先确认某个模型对函数调用的支持情况用模型对话快速试一轮最省时间https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。函数定义这件事写第一个能跑通之后后面就是复制骨架、改 description、改执行体。真正决定成败的不是代码多复杂而是 description 有没有写清楚“什么时候该调”。把这句话当成给模型看的接口文档来写调用准确率会明显不一样。
返回列表