资讯动态

企业微信API如何让机器人执行任务?从自然语言指令到工具调用

发布时间:2026/10/1 15:36:19 来源:尧图企业网站定制
最近做的企微二开业务方提了个需求销售在企微里发给张三打 VIP 标签机器人直接调接口打完标签回已打。之前的机器人是问答型问什么答什么现在要的是执行型——员工一句话机器人解析意图、挑出对应接口、传参、调用、把结果发回来。把这套链路落下来记一下踩的坑。底层用的是Eyun 平台开放的企微 API统一 POSTJSON鉴权用 App Token 加 appid请求头带Authorization: Bearer eyk_xxxx路径统一{BASE_URL}/wx-api/api/模块/动作响应封套{code, data, detail, message, time}code 为 0 成功。让机器人执行任务本质是把企微接口包装成大模型可调用的工具AI 负责解析意图和挑工具接口负责执行。第一步把企微接口注册成工具大模型 Function Calling 不能直接调企微接口要先把接口包装成工具描述。每个工具描述包含名字、说明、参数 schema。我们把常用的几类接口都注册成工具TOOLS [ { name: tag_customer, description: 给客户打标签。需要客户手机号或姓名 标签名。, parameters: { type: object, properties: { keyword: {type: string, description: 客户手机号或姓名}, labels: {type: array, items: {type: string}} }, required: [keyword, labels] } }, { name: search_customer, description: 按手机号或姓名搜客户档案, parameters: { type: object, properties: {keyword: {type: string}}, required: [keyword] } } ]工具描述越具体模型挑工具越准。早期写得太笼统执行业务操作模型经常挑错——比如把查客户误挑成 tag_customer。第二步消息进来——Webhook 收指令员工在企微发给张三打 VIP 标签消息通过 Webhook 进来。回调里带fromUin、content、appid。把消息原样喂给大模型让模型判断要不要调工具app.route(/wx-api/webhook/, methods[POST]) def webhook(): if request.headers.get(X-Eyun-Event) ! message: return ok data request.json[data] messages [ {role: system, content: 你是企业微信任务机器人按用户指令调用工具。}, {role: user, content: data[content]} ] call_llm_with_tools(data[appid], data[fromUin], messages) return okWebhook 路径/wx-api/webhook/首次创建返回 secret 用于验签。回调至少一次投递下游处理要幂等靠 delivery ID 去重——员工连发两次同样指令不能打两次标签。第三步参数提取和实体消解模型决定调 tag_customer 后要传张三和 [VIP] 这两个参数。但张三是名字不是 uin标签接口要的是 uin。这步要补一个工具链先调搜索接口拿 uin再调标签接口。落地时不要让模型一步到位让它分多步调def call_llm_with_tools(appid, from_uin, messages): resp requests.post(LLM_URL, json{ model: gpt-4, messages: messages, tools: TOOLS, tool_choice: auto }).json() msg resp[choices][0][message] if msg.get(tool_calls): for call in msg[tool_calls]: result dispatch_tool(appid, call[name], json.loads(call[arguments])) messages.append({role: tool, tool_call_id: call[id], content: json.dumps(result)}) # 把工具结果回喂给模型让它决定下一步或回答 return call_llm_with_tools(appid, from_uin, messages) # 模型不再调工具把最终回答发回企微 send_text(appid, from_uin, msg[content])模型自己决定调几个工具、按什么顺序调开发只负责 dispatch_tool 的具体实现。这一层多轮调用是把AI 编排和接口执行分开的关键。第四步工具执行——调真正的企微接口dispatch_tool 是工具描述名到企微接口的映射层。tag_customer 工具内部要先调 contact/search 拿 uin再调 label/updateLabeldef tag_customer(appid, keyword, labels): # 先搜客户拿 uin search_resp requests.post( f{BASE}/wx-api/api/contact/search, headersHEADERS, json{appid: appid, keyword: keyword} ) customers search_resp.json()[data].get(list, []) if not customers: return {success: False, message: f没搜到客户{keyword}} if len(customers) 1: return {success: False, message: f搜到多个客户请补手机号精确定位} uin customers[0][uin] # 调标签接口 resp requests.post( f{BASE}/wx-api/api/label/updateLabel, headersHEADERS, json{appid: appid, uin: uin, labels: labels} ) body resp.json() if body[code] 0: return {success: True, message: f已给 {keyword} 打标签 {labels}} return {success: False, message: body[message]}工具内部要处理一类常见错误搜到多个客户不能瞎选第一个让模型回问员工补信息接口返回 code 不是 0 时把 message 原样回给模型模型会自然把它转成自然语言告诉员工。第五步权限校验是硬边界不是所有员工都能让机器人执行所有工具。执行前按员工角色查权限def check_tool_permission(appid, from_uin, tool_name): profile requests.post( f{BASE}/wx-api/api/contact/getUserProfileDetail, headersHEADERS, json{appid: appid, uin: from_uin} ).json()[data] return tool_name in role_to_tools(profile.get(roles, []))无权限不调接口直接让模型回您没有权限使用此操作。权限白名单按岗位配不按个人——运营调整岗位定义后所有该岗位员工权限实时生效。这一层不做严员工用机器人绕过审批直接给客户打已退款标签是早晚的事。第六步执行留痕机器人执行类操作要留审计日志事后追溯谁让机器人给谁打了什么标签。日志结构记三件事触发指令员工原文、工具调用链调了哪些工具、传了什么参、返回什么、最终回发给员工的内容。审计日志和接口调用日志分开存——接口调用日志用于排障审计日志用于合规。几个落地要点工具描述要写细每个工具的 description 里写清什么场景用、什么场景不用模型挑工具的准确率从笼统描述的 70% 提到 90% 以上。工具粒度别太细最早把搜客户查客户档案打标签拆成三个工具让模型自己编排结果模型经常跳过搜直接调标签接口报错。后来把搜客户 打标签合并成 tag_customer 一个工具内部按步骤调多个接口模型只管调一次。兜底分支不能少模型置信度低时不要硬调工具让它回问员工您说的张三是指哪个张三。早期没做兜底模型瞎挑客户打错标签花了一周善后。写在最后让机器人执行任务这套本质是把企微接口包装成工具让大模型负责意图解析和编排、接口负责执行、消息接口负责把结果发回去。AI 在这套链路里是个调度员真正干活的是接口。把工具描述写细、权限边界守严、兜底分支留够机器人才能从问答型升级成执行型——员工一句话办成一件事不是和机器人聊半天。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑