ARTICLE · 1022891
坏了,坏了,微信里可以白嫖-钢铁侠的AI助手了
CodeBuddy连接微信,绑定ima,推送天气预报
把 Docker 容器,变成 24 小时在线的私人助理:能用微信跟它说话,能把产出自动沉淀进 ima 知识库,还能每天早上 7 点准时给你发天气预报。
本文记录的是一次真实落地过程,所有路径和命令都来自实际跑通的容器环境。
一、最终效果
• 在微信里直接给机器人发消息,它就是一个常驻的 CodeBuddy Code 会话 • 跟它说"把这篇写到 ima",文章自动进你的 ima 知识库 • 每天北京时间 07:00,微信收到天气预报(天气、气温、体感、降水、风力、湿度、日出日落 + 生活提示)
二、环境准备
我用的是官方 node 镜像容器。先确认基础环境:
node -v # v26.8.2npm -v # 12.0.2python3 -V # Python 3.13.5选 node 镜像的原因很直接:CodeBuddy Code 本身就是 Node 包,ima 官方技能包也是 Node 脚本,一个镜像全搞定。后面写推送脚本用 Python,Debian 基础镜像自带,不用额外装。
创建容器时建议做两件事:
1. 勾选「启用自动重新启动」——NAS 重启后容器能自己起来 2. 存储空间先随便挂一个目录,后面第四节会讲为什么要挂 /root/.codebuddy
三、安装 CodeBuddy Code
npm install -g @tencent-ai/codebuddy-codewhich codebuddy # /usr/local/bin/codebuddy装完后在容器里直接跑 codebuddy 就能进入交互式会话。为了让它在后台长期可用,用常驻方式启动,需要时用客户端连进去。
内置文档在这里,遇到问题先翻它:
ls /usr/local/lib/node_modules/@tencent-ai/codebuddy-code/dist/web-ui/docs/四、连接微信
4.1 建立长连接
在 CodeBuddy 会话里执行:
/remote-control会输出类似 Connected wechat:xxxxaxxx 的结果,表示微信通道已连上。
连接凭据落在容器的 /root/.codebuddy/channels/wechat/instances.json,长这样(关键字段):
{ "credentials": { "apiBaseUrl": "https://ilinkai.weixin.qq.com", "token": "...", "userId": "..." }}4.2 主动推送的最大坑
如果你写脚本想主动给用户发消息(不是回复),直接调接口:
POST https://ilinkai.weixin.qq.com/ilink/bot/sendmessageHeader: AuthorizationType: ilink_bot_token Authorization: Bearer <token> X-WECHAT-UIN: <随机9位数字的base64>Body: { "msg": { "to_user_id": "<userId>", "client_id": "cbc-<时间戳>-<随机数>", "message_type": 2, "message_state": 2, "item_list": [{"type": 1, "text_item": {"text": "你要发的内容"}}] }, "base_info": {"channel_version": "cbc-1.0.0"} }坑在这里:如果这个机器人从来没收到过微信消息,主动推送会返回:
{"ret": -2, "..."} // prepare failed解决办法只有一个:先让用户在微信里给机器人发任意一条消息,激活会话。激活之后,不带 context_token 也能主动推送。以后如果反馈"收不到推送",第一个查这个。
五、绑定 ima 知识库
5.1 装官方技能包
ima 提供了官方 OpenAPI 技能包,直接下载解压到 skills 目录:
mkdir -p /root/.codebuddy/skills/imacurl -L -o /tmp/ima-skills.zip \ https://app-dl.ima.qq.com/skills/ima-skills-1.1.10.zipunzip -o /tmp/ima-skills.zip -d /root/.codebuddy/skills/ima5.2 配置凭证
去 https://ima.qq.com/agent-interface 拿 Client ID 和 API Key,写进文件:
mkdir -p ~/.config/imaecho '你的ClientID' > ~/.config/ima/client_idecho '你的APIKey' > ~/.config/ima/api_keychmod 600 ~/.config/ima/client_id ~/.config/ima/api_key也支持环境变量 IMA_OPENAPI_CLIENTID / IMA_OPENAPI_APIKEY,优先级更高。
5.3 验证是否通
curl -s -X POST https://ima.qq.com/openapi/note/v1/list_notebook \ -H "ima-openapi-clientid: $(cat ~/.config/ima/client_id)" \ -H "ima-openapi-apikey: $(cat ~/.config/ima/api_key)" \ -H "Content-Type: application/json" \ -d '{"cursor":"0","limit":20}'返回 {"code":0,...} 就成了。
两个容易踩的点:
• 鉴权头是 ima-openapi-clientid/ima-openapi-apikey,不是常见的X-API-Key• 列表类接口必须带 limit(1~20),不带会报code:51参数错误,很容易误判成鉴权失败
5.4 一个关键概念:写文章走 notes,不走 knowledge-base
ima 的 OpenAPI 分两个模块:
| 模块 | 能干什么 |
|---|---|
notes/ | import_doc、追加 append_doc、搜索、读取 |
knowledge-base/ |
写纯文本文章,必须走 notes 模块:先用 import_doc 建笔记(Markdown,content_format: 1),再把它关联进知识库。
# 1) 建笔记node /root/.codebuddy/skills/ima/ima_api.cjs \ "openapi/note/v1/import_doc" \ '{"content_format":1,"content":"# 标题\n\n正文"}'# 返回 note_id# 2) 关联到指定知识库(media_type=11 表示笔记)node /root/.codebuddy/skills/ima/ima_api.cjs \ "openapi/wiki/v1/add_knowledge" \ '{"media_type":11,"note_info":{"content_id":"<note_id>"},"title":"标题","knowledge_base_id":"<kb_id>"}'知识库 ID 不是固定的,用这个接口按名字查最新值:
node /root/.codebuddy/skills/ima/ima_api.cjs \ "openapi/wiki/v1/get_addable_knowledge_base_list" '{"limit":20}'5.5 给机器人定好"往哪写"
这一步很值得做,否则每次都要被追问一遍。我给自己定的规则是:
1. ima 里置顶/指定的目录 → 优先 2. 其他 → 默认「文章」
把规则写进项目记忆文件(例如 ~/.codebuddy/projects/memory/),机器人就会默认照做。
六、每天 07:00 推送天气预报
6.1 为什么不用 crontab
两个原因:
1. 容器里没有 crontab,也没有 systemd 2. 容器时区是 UTC,配 cron 还得先改时区
另外 CodeBuddy 内置的 CronCreate 循环任务 3 天后自动失效,做不了长期调度。
所以最省事的方案:写一个 Python 常驻进程,自己算下次触发时间。
6.2 脚本要点
数据源用 wttr.in,免注册免 key:
url = f"https://wttr.in/{location}?format=j1"req = urllib.request.Request(url, headers={"User-Agent": "curl/8.0"})几个实现细节:
• 时区:用 ZoneInfo("Asia/Shanghai"),别依赖容器本地时区• 城市:改成经纬度字符串,比城市名稳
CITIES = [("杭州滨江", "30.209,120.217"),...]• 天气码翻译:wttr.in 返回的是数字 code 和英文描述,做个 WEATHER_CODE_ZH映射表,中文可读性差很多• 日出日落:返回的是 05:44 AM,用strptime(t, "%I:%M %p")转成 24 小时制• 兜底告警:三地全失败时,主动给微信发一条"天气推送异常",而不是静默失败 • 补发机制:进程重启后若发现今天已过推送点却没推成功过,立即补发一条
调度主循环:
def next_run_time(now): target = now.replace(hour=7, minute=0, second=0, microsecond=0) if now >= target: target += timedelta(days=1) return targetwhile True: target = next_run_time(datetime.now(TZ)) time.sleep(max(1.0, (target - datetime.now(TZ)).total_seconds())) if not already_pushed_today(datetime.now(TZ)): push_once()6.3 启动脚本
nohup 拉起,做幂等判断:
#!/bin/shcd "$(dirname "$0")" || exit 1if [ -f weather_push.pid ]; then OLD=$(cat weather_push.pid) if kill -0 "$OLD" 2>/dev/null; then echo "已在运行 pid=$OLD" exit 0 fi rm -f weather_push.pidfinohup python3 weather_push.py >> weather_push.log 2>&1 &echo $! > weather_push.pidecho "已启动 pid=$(cat weather_push.pid)"调格式时先 --dry-run 看文案,确认没问题再实发:
python3 weather_push.py --dry-run # 只打印,不发送python3 weather_push.py --once # 立即实发一次sh start.sh # 进常驻模式最终推到微信长这样:
【每日天气】9月16日 周三[杭州滨江]阴 19~27℃ 体感 27℃降水 8% | 东东北风 14km/h | 湿度 51%日出 05:44 日落 18:04 | 紫外线 8提示:昼夜温差大,早晚添件外套;紫外线偏强,注意防晒七、踩坑清单
| 现象 | 原因 | 解决 |
|---|---|---|
ret:-2 prepare failed | ||
code:51 | limit(1~20) | |
code:20004 | ima-openapi-clientid / ima-openapi-apikey | |
HTTP 500 | ||
ZoneInfo 自调度 | ||
/root/.codebuddy 挂到 NAS 目录 |
八、小结
整套搭下来,核心就四件事:
1. 选对底座:node 镜像 + 自动重启,一个容器覆盖 CodeBuddy、ima 技能、Python 脚本三种运行时 2. 微信激活:主动推送前必须先收一条消息,这个是硬门槛 3. ima 走对模块:写文章用 notes 的 import_doc,再add_knowledge关联知识库4. 持久化 + 自调度:挂 /root/.codebuddy保命,用常驻进程绕开容器没有 cron 的限制
做完这些,你就拥有了一个住在 NAS 里、随时能微信对话、还能主动给你发消息的私人助理。下一步可以加的:RSS 摘要推送、NAS 硬盘健康日报、定时抓取行业新闻进 ima 知识库——套路都是一样的。