一、项目定位与核心思想
weixin-agent-sdk 是一个非官方的微信 AI Agent 桥接框架,其代码由 @tencent-weixin/openclaw-weixin 改造而来,仅供学习交流。它解决了一个非常实际的问题:如何让任意 AI Agent(Claude Code、Codex、kimi-cli、OpenAI 等)快速接入微信,变成可用的微信机器人。
框架将微信的复杂协议细节完全封装,向上暴露一个极简的 Agent 接口。开发者只需实现一个 chat(request) → response 的异步函数,即可让 AI 具备收/发微信消息的能力。这种设计哲学类似于「适配器模式」——底层对接微信私有协议,上层对接任意 AI 服务。
整个项目采用 Monorepo 结构,包含三个核心包:
packages/sdk/—— weixin-agent-sdk:核心微信桥接 SDK,提供登录、消息收发、主动发送等能力packages/weixin-acp/—— ACP 适配器:面向已兼容 ACP(Agent Client Protocol)协议的 Agent,实现零代码接入packages/example-openai/—— OpenAI 示例:完整的 OpenAI Agent 实现,展示多轮对话与图片输入
二、ACP 零代码接入:最快路径
ACP(Agent Client Protocol)是一个开放的 Agent 通信协议。如果你的 AI 工具已经兼容 ACP(如 Claude Code、Codex、kimi-cli),那么接入微信完全不需要写任何代码。
2.1 接入 Claude Code
npx weixin-acp claude-code
这条命令会直接启动 weixin-acp,以内建方式对接 Claude Code。执行后会弹出微信扫码登录,登录成功后 Claude Code 即成为微信机器人。
2.2 接入 Codex
Codex 的接入方式与 Claude Code 类似,框架已内置支持。
2.3 接入任意 ACP Agent(以 kimi-cli 为例)
npx weixin-acp start -- kimi acp
这里的 -- 是关键的参数分隔符,后面的 kimi acp 就是启动 ACP server 的命令。weixin-acp 会自动以子进程方式启动它,并通过 JSON-RPC over stdio 进行双向通信。这种设计非常巧妙:
- 子进程隔离:Agent 进程与 weixin-acp 进程独立,一方崩溃不影响另一方
- stdio 通信:利用标准输入输出传输 JSON-RPC,无需网络端口,避免防火墙问题
- 协议标准化:只要 Agent 实现 ACP 协议,即可无缝接入
三、自定义 Agent 开发
当现有 ACP Agent 无法满足需求,或者你需要深度定制行为时,可以直接使用 SDK 开发自己的 Agent。SDK 的 API 设计极其精简,只导出三样东西:
实现 chat(request) 方法,处理微信消息并返回回复。这是唯一必须实现的东西。
触发微信扫码登录,建立与微信服务器的会话。
启动消息循环,返回 Bot 实例,支持主动发消息和等待退出。
3.1 Agent 接口详解
Agent 接口是整个框架的灵魂。它定义了 AI 与微信之间的「契约」:
interface Agent {
chat(request: ChatRequest): Promise<ChatResponse>;
}
interface ChatRequest {
conversationId: string; // 用户标识,可用于维护多轮对话上下文
text: string; // 文本内容(微信侧语音转文字也会落到此处)
media?: { // 附件(图片/语音/视频/文件)
type: "image" | "audio" | "video" | "file";
filePath: string; // 本地文件路径(SDK 已自动下载解密)
mimeType: string;
fileName?: string;
};
}
interface ChatResponse {
text?: string; // 回复文本(支持 markdown,发送前自动转纯文本)
media?: { // 回复媒体
type: "image" | "video" | "file";
url: string; // 本地路径或 HTTPS URL
fileName?: string;
};
}
这个接口设计有几个值得注意的点:
- conversationId 替代 username:不直接暴露微信用户的身份标识,而是用抽象的会话 ID,既保护了隐私,又便于维护多轮对话状态
- media 自动下载解密:微信的媒体文件通过 CDN 传输且 AES-128-ECB 加密,SDK 在传入 Agent 前已完成解密并保存到本地,Agent 直接读取即可
- Markdown 自动转换:Agent 可以返回 Markdown 格式的 text,SDK 会自动转换为微信支持的纯文本,降低 Agent 的实现负担
- 媒体回复支持远程 URL:如果回复的 media.url 是 HTTPS 链接,SDK 会自动下载后上传到微信 CDN
3.2 最简示例:Echo Bot
以下是一个最简的 Agent 实现,只返回用户发送的内容:
import { login, start, type Agent } from "weixin-agent-sdk";
const echo: Agent = {
async chat(req) {
return { text: `你说了: ${req.text}` };
},
};
await login();
const bot = start(echo);
await bot.wait();
代码非常直观:先登录,再启动,最后等待消息循环结束。整个流程不超过 10 行。
3.3 完整示例:自己管理对话历史
实际应用中,Agent 通常需要维护多轮对话上下文。以下示例展示了如何手动管理对话历史:
import { login, start, type Agent } from "weixin-agent-sdk";
const conversations = new Map<string, string[]>();
const myAgent: Agent = {
async chat(req) {
const history = conversations.get(req.conversationId) ?? [];
history.push(req.text);
// 调用你的 AI 服务...
const reply = await callMyAI(history);
history.push(reply);
conversations.set(req.conversationId, history);
return { text: reply };
},
};
await login();
const bot = start(myAgent);
await bot.wait();
这里用 Map<conversationId, string[]> 维护每个用户的对话历史。需要注意的是:对话历史存储在内存中,进程重启会丢失。生产环境应考虑使用 Redis 等外部存储持久化。
四、主动发送消息
除了被动回复微信消息,SDK 还支持主动推送。这是实现定时提醒、系统通知、主动播报等场景的关键能力。
4.1 基本用法
start() 会立即返回 Bot 实例,无需等待消息循环结束:
import { login, start, type Agent } from "weixin-agent-sdk";
const agent: Agent = {
async chat(req) {
if (req.text === "ping") {
return { text: "pong" };
}
return { text: `收到:${req.text}` };
},
};
await login();
const bot = start(agent);
// 每分钟主动发送一次提醒
setInterval(() => {
void bot.sendMessage("定时提醒:记得查看最新状态");
}, 60_000);
await bot.wait();
4.2 发送多媒体消息
主动发送不仅限于文本,还可以发送文件、图片、视频:
await bot.sendMessage({
text: "这是最新报表",
media: {
type: "file",
url: "./reports/daily.pdf",
fileName: "daily.pdf",
},
});
4.3 主动发送的限制条件
- 依赖 context_token:主动发送依赖微信服务器下发的
context_token - 需先收到过消息:在
start()运行期间,当前账号至少要收到过一条入站消息,才能获取有效的 context_token - Token 有时效:
context_token有效期约为 24 小时,过期后需要再次收到新消息才能恢复主动发送能力
这些限制源于微信私聊协议的安全设计,不是 SDK 的缺陷。在设计主动推送场景时,必须考虑「冷启动」和「Token 续期」的问题。
五、OpenAI 示例:开箱即用的完整实现
packages/example-openai/ 是一个生产级的参考实现,支持多轮对话和图片输入,展示了如何把一个真实的 LLM 服务接入微信。
5.1 快速启动
pnpm install
# 扫码登录微信
pnpm run login -w packages/example-openai
# 启动 bot(需要设置 OpenAI API Key)
OPENAI_API_KEY=sk-xxx pnpm run start -w packages/example-openai
5.2 环境变量配置
| 变量 | 必填 | 说明 |
|---|---|---|
OPENAI_API_KEY | 是 | OpenAI API Key |
OPENAI_BASE_URL | 否 | 自定义 API 地址(兼容 OpenAI 接口的第三方服务,如国内的代理或中转站) |
OPENAI_MODEL | 否 | 模型名称,默认 gpt-5.4 |
SYSTEM_PROMPT | 否 | 系统提示词,可定义机器人的性格和行为准则 |
这个示例的实用价值很高:只需设置一个 API Key,就能让 GPT 在微信里可用。对于国内用户,通过 OPENAI_BASE_URL 可以无缝切换到国内兼容 OpenAI 接口的中转服务。
六、消息类型全矩阵
SDK 对微信消息类型的支持非常全面,覆盖了日常聊天中几乎所有的媒体形式。
6.1 接收(微信 → Agent)
| 类型 | media.type | 说明 |
|---|---|---|
| 文本 | — | request.text 直接拿到文字内容 |
| 图片 | image | 自动从微信 CDN 下载并解密,filePath 指向本地文件 |
| 语音 | audio | SILK 格式自动转换为 WAV(需安装 silk-wasm 依赖) |
| 视频 | video | 自动下载解密 |
| 文件 | file | 自动下载解密,保留原始文件名 |
| 引用消息 | — | 被引用的文本拼入 request.text,被引用的媒体作为 media 传入 |
| 语音转文字 | — | 微信侧已转写的文字直接作为 request.text 传入,Agent 无需处理语音识别 |
特别值得注意的是引用消息的处理方式:SDK 没有让 Agent 自己去解析引用结构,而是智能地把引用内容合并到当前消息的 text 中。这种设计让 Agent 的实现更简单——它不需要理解微信的引用消息格式,只需要处理纯文本即可。
6.2 发送(Agent → 微信)
| 类型 | 用法 |
|---|---|
| 文本 | 返回 { text: "..." } |
| 图片 | 返回 { media: { type: "image", url: "/path/to/img.png" } } |
| 视频 | 返回 { media: { type: "video", url: "/path/to/video.mp4" } } |
| 文件 | 返回 { media: { type: "file", url: "/path/to/doc.pdf" } } |
| 文本 + 媒体 | text 和 media 同时返回,文本作为附带说明发送 |
| 远程图片 | url 填 HTTPS 链接,SDK 自动下载后上传到微信 CDN |
| 主动发送 | 通过 bot.sendMessage(...) 发送 |
七、内置斜杠命令
SDK 内置了两个调试用的斜杠命令,方便在开发阶段快速验证通道状态:
直接回复输入的内容(不经过 Agent 处理),并附带通道耗时统计。用于验证消息链路是否通畅。
开关 debug 模式。启用后,每条回复的末尾会追加全链路耗时信息,方便排查性能瓶颈。
八、技术细节与架构设计
8.1 长轮询消息接收
SDK 使用 长轮询(long-polling) 方式接收消息,通过 getUpdates 接口持续向微信服务器拉取新消息。这种方式的优势在于:
- 无需公网服务器:不需要配置 webhook 或公网 IP,本地运行即可
- 无防火墙问题:出向 HTTP 请求通常不会被防火墙拦截
- 连接稳定:长轮询比短轮询更高效,比 WebSocket 更简单
8.2 媒体文件安全传输
微信的媒体文件通过 CDN 中转,传输过程使用 AES-128-ECB 加密。SDK 在下载后自动完成解密,Agent 拿到的已经是明文文件。
8.3 断点续传与持久化
SDK 将 get_updates_buf(消息拉取游标)持久化到 ~/.openclaw/ 目录。这意味着:
- 进程重启后,会从上次的位置继续拉取,不会丢失消息
- 支持异常退出后的断点续传
8.4 会话管理与自动重连
- 单账号模式:每次
login会覆盖之前的账号状态,同一时间只能登录一个微信账号 - 自动重连:当服务端返回 errcode -14(会话过期)时,SDK 会自动进入 1 小时冷却期,之后尝试恢复连接
8.5 Node.js 版本要求
项目要求 Node.js ≥ 22,这是一个相对较新的版本要求,说明项目充分使用了现代 Node.js 特性(如原生的 Promise、fetch、AbortController 等)。
九、整体架构图
十、使用建议与注意事项
10.1 适用场景
- 个人微信 AI 助手(知识问答、日程管理)
- 小团队的客服机器人
- AI 实验和原型验证
- 定时通知与信息播报
- 多媒体内容处理(图片分析、文件解读)
- 非官方项目,存在协议变更导致失效的风险
- 仅用于学习交流,不建议用于生产关键业务
- 主动发送有 24h context_token 限制
- 单账号模式,无法同时管理多个微信
- 对话历史默认内存存储,重启丢失
10.2 生产环境建议
- 持久化对话历史:将
Map替换为 Redis 或数据库存储 - 异常监控:监听 SDK 的错误事件,接入 Sentry 等监控平台
- Token 续期策略:主动发送场景下,设计定时任务定期「唤醒」context_token
- 限流保护:Agent 层面增加请求频率限制,避免触发微信风控
- 日志脱敏:对话日志中避免记录敏感信息,符合数据合规要求
十一、总结
weixin-agent-sdk 是一个非常精巧的桥接框架,它在「微信私有协议」和「AI Agent 生态」之间搭了一座桥。其设计哲学可以概括为三个关键词:
只需实现一个 chat() 函数,10 行代码跑通微信机器人。
ACP 协议让 Claude Code、Codex、kimi-cli 等工具零代码接入。
自动处理加密、解密、CDN 下载,向上暴露干净的本地文件接口。
断点续传、自动重连、持久化游标,最大限度保证消息不丢。
对于想把 AI 能力快速对接到微信生态的开发者来说,这个框架提供了一个非常优雅的起点。无论是「零代码」的 ACP 接入,还是「深度定制」的 SDK 开发,都能找到合适的路径。当然,作为非官方项目,在使用时需要关注微信协议变更的风险,并做好相应的降级预案。