ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

手把手教你创建 OpenClaw Skill:微信自动发送消息实战(TaoToken 统一 Key 接入版)

手把手教你创建 OpenClaw Skill:微信自动发送消息实战(TaoToken 统一 Key 接入版) 1. 为什么要在 OpenClaw 里做一个微信自动发消息 SkillOpenClaw Skill 是一套把「本地能力」封装成 AI 可调用工具的机制简单说就是让 AI 助手从「只会聊天」变成「能动手干活」。微信自动发送消息这个场景特别典型你每天可能要重复给同事发日报提醒、给客户发进度同步、给群里发固定格式通知这些动作机械、重复、容易忘但偏偏又必须做。把它做成 Skill 之后你只需要对 OpenClaw 说一句「给小明发消息今天下午三点开会」剩下的窗口切换、联系人搜索、内容粘贴、回车发送全部自动完成。这个 Skill 适合三类人一是经常需要批量触达微信联系人的运营和销售二是想把日常重复操作交给 AI 的开发者三是正在学习 OpenClaw Skill 开发、想找一个完整可跟做案例的同学。它不需要你懂微信协议也不需要任何第三方登录手段纯粹基于本地已登录的微信桌面端做 UI 自动化风险可控、链路透明。技术上有几个真实的坑必须提前说清楚。微信桌面端在新版本里大量使用 UWP 容器WeChatAppEx传统的FindWindow拿不到标准窗口句柄SendKeys直接发中文还会因为输入法干扰变成乱码。我试过用 VBS 的SendKeys模拟 Win 键组合结果完全不生效因为 VBS 的 SendKeys 语法根本不支持 Win 键。最后稳定跑通的方案是用keybd_event模拟 Win数字切到任务栏固定位置的微信用win32clipboard剪贴板粘贴绕过输入法再用回车完成发送。整套逻辑用 Python pywin32 ctypes 实现封装成 OpenClaw Skill 后由模型决定什么时候调用。而模型调用的那一环我用 TaoToken 统一 Key 接入一个 Key 就能走通对话模型通道不用在多个平台之间来回切换配置。下面从环境准备开始一步步把这条链路搭起来。2. TaoToken 统一 Key 与 OpenClaw 环境前置准备在写 Skill 之前先把两件事准备好模型调用通道和本地 Python 环境。很多人卡在第一步不是因为技术难而是因为 Key 和 Base URL 配错导致 Skill 里调用模型时一直 401。TaoToken 的定位是统一模型接入通道你可以在它的控制台创建一个 API Key然后所有兼容 OpenAI 协议的客户端都能用同一个 Key 和同一个 Base URL 去请求不同模型。对 OpenClaw Skill 来说这意味着你的 Skill 里如果需要模型做意图解析、联系人名称归一化、消息内容润色都可以直接复用这套通道不用为每个模型单独维护一套鉴权。先拿 Key。打开控制台页面https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite登录后在 API Keys 页面创建一个新 Key复制出来形如sk-xxxxxxxx。这个 Key 只显示一次建议先存到本地环境变量里不要硬编码进脚本。https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewriteBase URL 统一用https://taotoken.net/api注意这个地址后面不加 UTM 参数它是给程序调用的接口地址。模型 ID 按你实际要用的填比如claude-sonnet-4-5或gpt-4o这类具体以控制台模型列表为准。本地环境这边你需要 Python 3.9 以上然后装两个包pip install pywin32 requestspywin32提供剪贴板操作requests用来调 TaoToken 的接口。装完之后验证一下python -c import win32clipboard; print(clipboard ok)如果这条命令报ImportError说明 pywin32 没装好重装一次并确认 Python 版本匹配。Windows 上有时需要以管理员身份运行一次python Scripts/pywin32_postinstall.py -install来注册 DLL。环境变量建议这样设PowerShell 里$env:TAOTOKEN_API_KEYsk-你的key $env:TAOTOKEN_BASE_URLhttps://taotoken.net/api这样 Skill 脚本里用os.environ.get(TAOTOKEN_API_KEY)读取既安全又方便切换。前置准备做完接下来进入 Skill 目录结构和可复制配置。3. OpenClaw Skill 目录结构与可复制配置OpenClaw Skill 的本质是一个带SKILL.md的文件夹SKILL.md里的description字段决定模型在什么场景下触发这个 Skill。目录结构建议这样组织wechat-messenger/ ├── SKILL.md ├── README.md ├── scripts/ │ ├── wechat_send_win9.py │ ├── wechat_send.ps1 │ └── model_client.py └── config/ └── settings.jsonSKILL.md是核心它的 frontmatter 必须写清楚触发条件。下面这份可以直接复制注意description要覆盖用户可能说的各种说法--- name: wechat-messenger description: WeChat auto-messaging skill. Send messages to WeChat contacts via local Windows client. Triggers when user asks to: send WeChat message, message someone on WeChat, chat with a contact, 给某人发微信, 微信发消息. Supports single and batch messages. Uses clipboard paste to bypass IME issues. --- # WeChat Messenger ## Prerequisites - WeChat Windows client running and logged in - WeChat pinned to taskbar position 9 - Python with pywin32: pip install pywin32 ## Usage Call scripts/wechat_send.ps1 -Contact name -Message contentconfig/settings.json放模型调用配置这样 Skill 里调 TaoToken 时不用改代码{ base_url: https://taotoken.net/api, api_key_env: TAOTOKEN_API_KEY, model_id: claude-sonnet-4-5, timeout: 30, retry: 2 }model_client.py负责读这份配置并调用模型用于把用户口语化的指令解析成结构化的联系人和消息内容import os import json import requests CONFIG_PATH os.path.join(os.path.dirname(__file__), .., config, settings.json) def load_config(): with open(CONFIG_PATH, r, encodingutf-8) as f: return json.load(f) def parse_intent(user_text): cfg load_config() api_key os.environ.get(cfg[api_key_env]) if not api_key: raise RuntimeError(TAOTOKEN_API_KEY not set) headers { Authorization: fBearer {api_key}, Content-Type: application/json } payload { model: cfg[model_id], messages: [ {role: system, content: Extract contact and message from user input. Return JSON: {\contact\: \\, \message\: \\}}, {role: user, content: user_text} ] } resp requests.post( f{cfg[base_url]}/v1/chat/completions, headersheaders, jsonpayload, timeoutcfg[timeout] ) resp.raise_for_status() content resp.json()[choices][0][message][content] return json.loads(content)这里三件套要记牢Base URL 是https://taotoken.net/apiKey 从环境变量读Model ID 写在 settings.json 里。三者缺一调用就会失败。配置写好后下一节进入核心的窗口定位与消息注入代码。4. pywin32 窗口定位与消息注入完整实现微信桌面端不能用传统FindWindow定位所以这里走任务栏快捷键方案把微信固定在任务栏第 9 个位置用Win9切过去。这个方案的好处是不依赖窗口标题也不受微信版本更新影响只要位置固定就能用。核心脚本wechat_send_win9.py完整如下可以直接复制import ctypes import time import sys import win32clipboard VK_LWIN 0x5B VK_CONTROL 0x11 VK_V 0x56 VK_F 0x46 VK_ENTER 0x0D VK_9 0x39 user32 ctypes.windll.user32 def key_down(vk): user32.keybd_event(vk, 0, 0, 0) def key_up(vk): user32.keybd_event(vk, 0, 2, 0) def press_combo(modifier, key): key_down(modifier) time.sleep(0.05) key_down(key) time.sleep(0.05) key_up(key) key_up(modifier) def set_clipboard(text): win32clipboard.OpenClipboard() win32clipboard.EmptyClipboard() win32clipboard.SetClipboardText(text, win32clipboard.CF_UNICODETEXT) win32clipboard.CloseClipboard() def send_wechat(contact, message): # 1. Win9 切到微信 key_down(VK_LWIN) time.sleep(0.05) key_down(VK_9) time.sleep(0.05) key_up(VK_9) key_up(VK_LWIN) time.sleep(0.8) # 2. CtrlF 打开搜索 press_combo(VK_CONTROL, VK_F) time.sleep(0.8) # 3. 粘贴联系人姓名 set_clipboard(contact) press_combo(VK_CONTROL, VK_V) time.sleep(1.5) # 4. 回车进入聊天 key_down(VK_ENTER) time.sleep(0.05) key_up(VK_ENTER) time.sleep(0.8) # 5. 粘贴消息内容 set_clipboard(message) press_combo(VK_CONTROL, VK_V) time.sleep(0.5) # 6. 回车发送 key_down(VK_ENTER) time.sleep(0.05) key_up(VK_ENTER) print(fMessage sent to {contact}) if __name__ __main__: if len(sys.argv) 3: print(Usage: python wechat_send_win9.py contact message) sys.exit(1) send_wechat(sys.argv[1], sys.argv[2])几个关键点解释一下。keybd_event的第三个参数 0 表示按下2 表示抬起这是 Windows API 的约定。set_clipboard里用CF_UNICODETEXT是为了保证中文不乱码这一点比默认的SetClipboardText更稳。每一步之间的time.sleep不是随便写的微信 UI 响应有延迟切窗口后至少等 0.8 秒搜索后等 1.5 秒让结果列表渲染出来否则回车可能进错聊天。PowerShell 封装脚本wechat_send.ps1负责把参数透传给 Pythonparam( [Parameter(Mandatory$true)][string]$Contact, [Parameter(Mandatory$true)][string]$Message ) $pyScript Join-Path $PSScriptRoot wechat_send_win9.py $python python $python $pyScript $Contact $Message如果你用 conda 环境把$python换成绝对路径比如D:\anaconda3\python.exe。这样 OpenClaw 调用 Skill 时只需要传联系人和消息两个参数内部细节全部封装好。5. 验证请求与常见报错排查写完代码先别急着接 OpenClaw单独跑一遍验证链路。先测模型调用是否通python -c from scripts.model_client import parse_intent; print(parse_intent(给小明发消息今天下午三点开会))正常应该返回类似{contact: 小明, message: 今天下午三点开会}。如果这里报错对照下面几个真实错误排查。报错一401 Unauthorizedrequests.exceptions.HTTPError: 401 Client Error: Unauthorized for url: https://taotoken.net/api/v1/chat/completions原因通常是 Key 没读到或者写错了。检查TAOTOKEN_API_KEY环境变量是否在当前终端生效PowerShell 里用echo $env:TAOTOKEN_API_KEY确认。注意 Key 不要带引号也不要有多余空格。报错二local proxy failedrequests.exceptions.ProxyError: HTTPSConnectionPool ... local proxy failed这是本地代理配置干扰了请求。检查系统环境变量里有没有HTTP_PROXY/HTTPS_PROXY如果有就临时清掉Remove-Item Env:HTTP_PROXY -ErrorAction SilentlyContinue Remove-Item Env:HTTPS_PROXY -ErrorAction SilentlyContinue报错三reading choices 时 KeyErrorKeyError: choices说明返回体结构不对多半是 Base URL 写成了带/v1的完整路径又拼了一次或者模型 ID 不存在。确认 Base URL 是https://taotoken.net/api代码里拼/v1/chat/completions模型 ID 从控制台复制。报错四微信没反应或发错人如果脚本跑完没报错但消息没发出去先确认微信是否固定在任务栏第 9 位。手动按Win9看能不能切到微信不能的话调整固定位置或改脚本里的VK_9。如果发错人多半是搜索后等待时间不够把time.sleep(1.5)加到 2 秒再试。报错五中文乱码如果消息内容变成问号或方块检查set_clipboard是否用了CF_UNICODETEXT。用SendKeys直接发中文在搜狗五笔等输入法下必然乱码剪贴板方案是唯一稳定的绕过方式。排查完这些再跑一次完整发送.\scripts\wechat_send.ps1 -Contact 文件传输助手 -Message 测试消息用文件传输助手测试最安全不会打扰别人。看到消息出现在聊天窗口说明整条链路通了。6. 接入 OpenClaw 与长期使用建议Skill 本地跑通后把它放到 OpenClaw 的 skills 目录重启 Gateway 就能被识别。之后你在 OpenClaw 里说「给小明发消息今天下午三点开会」模型会先调parse_intent解析出联系人和内容再调wechat_send.ps1完成发送。如果你打算长期用这套东西建议把模型调用走 Coding Plan 通道这样日常编码和 Skill 里的模型请求可以共用一套额度管理起来更省心https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite需要调试模型返回时可以用模型对话页面直接测 prompthttps://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite接入文档在这里遇到协议细节可以对照https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite最后说几个实战经验。第一任务栏位置不要写死 9如果你经常变动图标顺序可以在脚本启动时用pygetwindow扫描一次微信窗口并记录位置或者干脆固定一个专用任务栏槽位。第二批量发送时每条之间至少间隔 3 秒太快会被微信风控盯上。第三消息内容里如果有换行剪贴板方案能正常处理但SendKeys不行这也是选剪贴板的另一个理由。第四把发送结果写日志失败时记录联系人和时间方便重试。这套 Skill 我跑了一段时间最实用的场景是每天定时给几个群发固定格式的提醒省下来的时间比搭它的时间多得多。
返回列表