weixin-agent-sdk

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

weixin-agent-sdk

weixin-agent-sdk

Skill by ara.so — Daily 2026 Skills collection.
weixin-agent-sdk
is a TypeScript framework that bridges any AI backend to WeChat (微信) via the Clawbot channel. It uses long-polling to receive messages — no public server required — and exposes a minimal
Agent
interface so you can plug in OpenAI, Claude, or any custom logic in minutes.

ara.so提供的Skill——每日2026技能合集。
weixin-agent-sdk
是一款TypeScript框架,通过Clawbot渠道将任意AI后端与微信打通。它采用长轮询方式接收消息——无需公网服务器——并提供极简的
Agent
接口,让你能在几分钟内接入OpenAI、Claude或自定义逻辑。

Installation

安装

bash
undefined
bash
undefined

npm

npm

npm install weixin-agent-sdk
npm install weixin-agent-sdk

pnpm (monorepo)

pnpm (单仓库)

pnpm add weixin-agent-sdk

Node.js >= 22 required.

---
pnpm add weixin-agent-sdk

需要Node.js >= 22版本。

---

Quick Start

快速开始

1. Login (scan QR code once)

1. 登录(扫码一次即可)

typescript
import { login } from "weixin-agent-sdk";

await login();
// Credentials are persisted to ~/.openclaw/ — run once, then use start()
typescript
import { login } from "weixin-agent-sdk";

await login();
// 凭证会持久化到~/.openclaw/目录下——只需运行一次,之后即可使用start()

2. Implement the Agent interface

2. 实现Agent接口

typescript
import { login, start, type Agent } from "weixin-agent-sdk";

const echo: Agent = {
  async chat(req) {
    return { text: `You said: ${req.text}` };
  },
};

await login();
await start(echo);

typescript
import { login, start, type Agent } from "weixin-agent-sdk";

const echo: Agent = {
  async chat(req) {
    return { text: `You said: ${req.text}` };
  },
};

await login();
await start(echo);

Core API

核心API

Agent
Interface

Agent
接口

typescript
interface Agent {
  chat(request: ChatRequest): Promise<ChatResponse>;
}

interface ChatRequest {
  conversationId: string;   // Unique user/conversation identifier
  text: string;             // Message text content
  media?: {
    type: "image" | "audio" | "video" | "file";
    filePath: string;       // Local path (already downloaded & decrypted)
    mimeType: string;
    fileName?: string;
  };
}

interface ChatResponse {
  text?: string;            // Markdown supported; auto-converted to plain text
  media?: {
    type: "image" | "video" | "file";
    url: string;            // Local path OR HTTPS URL (auto-downloaded)
    fileName?: string;
  };
}
typescript
interface Agent {
  chat(request: ChatRequest): Promise<ChatResponse>;
}

interface ChatRequest {
  conversationId: string;   // 唯一的用户/会话标识符
  text: string;             // 消息文本内容
  media?: {
    type: "image" | "audio" | "video" | "file";
    filePath: string;       // 本地路径(已下载并解密)
    mimeType: string;
    fileName?: string;
  };
}

interface ChatResponse {
  text?: string;            // 支持Markdown;会自动转换为纯文本
  media?: {
    type: "image" | "video" | "file";
    url: string;            // 本地路径或HTTPS URL(会自动下载)
    fileName?: string;
  };
}

login()

login()

Triggers QR code scan and persists session to
~/.openclaw/
. Only needs to run once.
触发扫码登录,并将会话信息持久化到
~/.openclaw/
目录。只需运行一次。

start(agent)

start(agent)

Starts the message loop. Blocks until process exits. Automatically reconnects on session expiry.

启动消息循环。会阻塞进程直到退出。会话过期时会自动重新连接。

Common Patterns

常见模式

Multi-turn Conversation with History

多轮会话与历史记录

typescript
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(`user: ${req.text}`);

    const reply = await callMyAIService(history);

    history.push(`assistant: ${reply}`);
    conversations.set(req.conversationId, history);

    return { text: reply };
  },
};

await login();
await start(myAgent);
typescript
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(`user: ${req.text}`);

    const reply = await callMyAIService(history);

    history.push(`assistant: ${reply}`);
    conversations.set(req.conversationId, history);

    return { text: reply };
  },
};

await login();
await start(myAgent);

OpenAI Agent (Full Example)

OpenAI Agent(完整示例)

typescript
import OpenAI from "openai";
import { login, start, type Agent, type ChatRequest } from "weixin-agent-sdk";
import * as fs from "fs";

const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
  baseURL: process.env.OPENAI_BASE_URL, // optional override
});

const model = process.env.OPENAI_MODEL ?? "gpt-4o";
const systemPrompt = process.env.SYSTEM_PROMPT ?? "You are a helpful assistant.";

type Message = OpenAI.Chat.ChatCompletionMessageParam;
const histories = new Map<string, Message[]>();

const openaiAgent: Agent = {
  async chat(req: ChatRequest) {
    const history = histories.get(req.conversationId) ?? [];

    // Build user message — support image input
    const content: OpenAI.Chat.ChatCompletionContentPart[] = [];

    if (req.text) {
      content.push({ type: "text", text: req.text });
    }

    if (req.media?.type === "image") {
      const imageData = fs.readFileSync(req.media.filePath).toString("base64");
      content.push({
        type: "image_url",
        image_url: {
          url: `data:${req.media.mimeType};base64,${imageData}`,
        },
      });
    }

    history.push({ role: "user", content });

    const response = await client.chat.completions.create({
      model,
      messages: [
        { role: "system", content: systemPrompt },
        ...history,
      ],
    });

    const reply = response.choices[0].message.content ?? "";
    history.push({ role: "assistant", content: reply });
    histories.set(req.conversationId, history);

    return { text: reply };
  },
};

await login();
await start(openaiAgent);
typescript
import OpenAI from "openai";
import { login, start, type Agent, type ChatRequest } from "weixin-agent-sdk";
import * as fs from "fs";

const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
  baseURL: process.env.OPENAI_BASE_URL, // 可选的自定义地址
});

const model = process.env.OPENAI_MODEL ?? "gpt-4o";
const systemPrompt = process.env.SYSTEM_PROMPT ?? "You are a helpful assistant.";

type Message = OpenAI.Chat.ChatCompletionMessageParam;
const histories = new Map<string, Message[]>();

const openaiAgent: Agent = {
  async chat(req: ChatRequest) {
    const history = histories.get(req.conversationId) ?? [];

    // 构建用户消息——支持图片输入
    const content: OpenAI.Chat.ChatCompletionContentPart[] = [];

    if (req.text) {
      content.push({ type: "text", text: req.text });
    }

    if (req.media?.type === "image") {
      const imageData = fs.readFileSync(req.media.filePath).toString("base64");
      content.push({
        type: "image_url",
        image_url: {
          url: `data:${req.media.mimeType};base64,${imageData}`,
        },
      });
    }

    history.push({ role: "user", content });

    const response = await client.chat.completions.create({
      model,
      messages: [
        { role: "system", content: systemPrompt },
        ...history,
      ],
    });

    const reply = response.choices[0].message.content ?? "";
    history.push({ role: "assistant", content: reply });
    histories.set(req.conversationId, history);

    return { text: reply };
  },
};

await login();
await start(openaiAgent);

Send Image Response

发送图片响应

typescript
const imageAgent: Agent = {
  async chat(req) {
    return {
      text: "Here is your image:",
      media: {
        type: "image",
        url: "/tmp/output.png",       // local path
        // or: url: "https://example.com/image.png"  — auto-downloaded
      },
    };
  },
};
typescript
const imageAgent: Agent = {
  async chat(req) {
    return {
      text: "Here is your image:",
      media: {
        type: "image",
        url: "/tmp/output.png",       // 本地路径
        // 或者:url: "https://example.com/image.png"  —— 会自动下载
      },
    };
  },
};

Send File Response

发送文件响应

typescript
const fileAgent: Agent = {
  async chat(req) {
    return {
      media: {
        type: "file",
        url: "/tmp/report.pdf",
        fileName: "monthly-report.pdf",
      },
    };
  },
};

typescript
const fileAgent: Agent = {
  async chat(req) {
    return {
      media: {
        type: "file",
        url: "/tmp/report.pdf",
        fileName: "monthly-report.pdf",
      },
    };
  },
};

ACP (Agent Client Protocol) Integration

ACP(Agent客户端协议)集成

If you have an ACP-compatible agent (Claude Code, Codex, kimi-cli, etc.), use the
weixin-acp
package — no code needed.
bash
undefined
如果你有兼容ACP的Agent(Claude Code、Codex、kimi-cli等),可以使用
weixin-acp
包——无需编写代码。
bash
undefined

Claude Code

Claude Code

npx weixin-acp claude-code
npx weixin-acp claude-code

Codex

Codex

npx weixin-acp codex
npx weixin-acp codex

Any ACP-compatible agent (e.g. kimi-cli)

任意兼容ACP的Agent(例如kimi-cli)

npx weixin-acp start -- kimi acp

`weixin-acp` launches your agent as a subprocess and communicates via JSON-RPC over stdio.

---
npx weixin-acp start -- kimi acp

`weixin-acp`会以子进程方式启动你的Agent,并通过标准输入输出的JSON-RPC进行通信。

---

Environment Variables (OpenAI Example)

环境变量(OpenAI示例)

VariableRequiredDescription
OPENAI_API_KEY
YesOpenAI API key
OPENAI_BASE_URL
NoCustom API base URL (OpenAI-compatible services)
OPENAI_MODEL
NoModel name, default
gpt-5.4
SYSTEM_PROMPT
NoSystem prompt for the assistant

变量是否必填说明
OPENAI_API_KEY
OpenAI API密钥
OPENAI_BASE_URL
自定义API基础地址(兼容OpenAI的服务)
OPENAI_MODEL
模型名称,默认
gpt-5.4
SYSTEM_PROMPT
助手的系统提示词

Built-in Slash Commands

内置斜杠命令

Send these in WeChat chat to control the bot:
CommandDescription
/echo <message>
Echoes back directly (bypasses Agent), shows channel latency
/toggle-debug
Toggles debug mode — appends full latency stats to each reply

在微信聊天中发送以下命令来控制机器人:
命令说明
/echo <message>
直接返回消息内容(绕过Agent),显示渠道延迟
/toggle-debug
切换调试模式——每条回复会附加完整的延迟统计信息

Supported Message Types

支持的消息类型

Incoming (WeChat → Agent)

接收(微信→Agent)

Type
media.type
Notes
TextPlain text in
request.text
Image
image
Downloaded & decrypted,
filePath
= local file
Voice
audio
SILK auto-converted to WAV (requires
silk-wasm
)
Video
video
Downloaded & decrypted
File
file
Downloaded & decrypted, original filename preserved
Quoted messageQuoted text appended to
request.text
, quoted media as
media
Voice-to-textWeChat transcription delivered as
request.text
类型
media.type
说明
文本纯文本内容在
request.text
图片
image
已下载并解密,
filePath
为本地文件路径
语音
audio
SILK格式自动转换为WAV(需要
silk-wasm
依赖)
视频
video
已下载并解密
文件
file
已下载并解密,保留原始文件名
引用消息引用的文本附加到
request.text
,引用的媒体在
media
语音转文字微信识别的文字内容在
request.text

Outgoing (Agent → WeChat)

发送(Agent→微信)

TypeUsage
TextReturn
{ text: "..." }
ImageReturn
{ media: { type: "image", url: "..." } }
VideoReturn
{ media: { type: "video", url: "..." } }
FileReturn
{ media: { type: "file", url: "...", fileName: "..." } }
Text + MediaReturn both
text
and
media
together
Remote imageSet
url
to an HTTPS link — SDK auto-downloads and uploads to WeChat CDN

类型使用方式
文本返回
{ text: "..." }
图片返回
{ media: { type: "image", url: "..." } }
视频返回
{ media: { type: "video", url: "..." } }
文件返回
{ media: { type: "file", url: "...", fileName: "..." } }
文本+媒体同时返回
text
media
远程图片
url
设为HTTPS链接——SDK会自动下载并上传到微信CDN

Monorepo / pnpm Setup

单仓库/pnpm设置

bash
git clone https://github.com/wong2/weixin-agent-sdk
cd weixin-agent-sdk
pnpm install
bash
git clone https://github.com/wong2/weixin-agent-sdk
cd weixin-agent-sdk
pnpm install

Login (scan QR code)

登录(扫码)

pnpm run login -w packages/example-openai
pnpm run login -w packages/example-openai

Start the OpenAI bot

启动OpenAI机器人

OPENAI_API_KEY=$OPENAI_API_KEY pnpm run start -w packages/example-openai

---
OPENAI_API_KEY=$OPENAI_API_KEY pnpm run start -w packages/example-openai

---

Troubleshooting

故障排除

Session expired (
errcode -14
)
The SDK automatically enters a 1-hour cooldown and then reconnects. No manual intervention needed.
Audio not converting from SILK to WAV Install the optional dependency:
npm install silk-wasm
Bot not receiving messages after restart State is persisted in
~/.openclaw/get_updates_buf
. The bot resumes from the last position automatically.
Remote image URL not sending Ensure the URL is HTTPS and publicly accessible. The SDK downloads it before uploading to WeChat CDN.
login()
QR code not appearing
Ensure your terminal supports rendering QR codes, or check
~/.openclaw/
for the raw QR data.
会话过期(错误码-14) SDK会自动进入1小时冷却期,之后重新连接。无需手动干预。
音频无法从SILK转换为WAV 安装可选依赖:
npm install silk-wasm
重启后机器人无法接收消息 状态会持久化到
~/.openclaw/get_updates_buf
。机器人会自动从上次位置恢复。
远程图片URL无法发送 确保URL是HTTPS且可公开访问。SDK会先下载图片,再上传到微信CDN。
login()
二维码不显示
确保你的终端支持渲染二维码,或者查看
~/.openclaw/
目录下的原始二维码数据。