npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

langgraph-plugin-wecom

v1.0.0

Published

LangGraph adaptor plugin for Enterprise WeChat (WeCom) AI Bot / Agent API / Webhook integration

Readme

langgraph-plugin-wecom

Node.js TypeScript License npm GitHub WeCom

把企业微信(WeCom)的通信能力无缝接入你的 LangGraph Agent。支持智能机器人 WebSocket 长连接、自建应用 Agent API、群机器人 Webhook 三大通信方式,零业务耦合,即插即用

本项目从 openclaw-plugin-wecom 复用其企业微信通信实现,剥离了 OpenClaw 的 channel/runtime/plugin SDK 耦合,作为 LangGraph Agent 的企业微信传输层 独立发布。


特性

  • AI Bot 智能机器人 — 基于 wss://openws.work.weixin.qq.com 长连接,自动重连 / 心跳维持 / 消息去重
  • 流式推理输出 — 支持 sendReasoningStream,在企微端实时展示模型的思考过程(reasoning)和最终回复
  • Agent API 自建应用 — 主动发送文本 / markdown / 图片 / 语音 / 视频 / 文件
  • Webhook 群机器人 — 群通知 / 监控告警一键发送
  • LangGraph Tool 封装createWecomTools() 一行生成 LLM 可调用的企微工具集
  • 零业务耦合 — 不绑定任何 Agent 框架,StateGraph / MessageGraph / 自定义 Agent 均可使用
  • TypeScript 优先 — 完整类型定义,开发体验友好
  • 代理友好 — 配置 proxyUrl 即可走 HTTP 代理出向(需安装 undici
  • 完整测试覆盖 — 基于 Node.js 内置 node:test,62 个测试用例全部通过

安装

npm install langgraph-plugin-wecom
# 可选:HTTP 代理支持
npm install undici

Node.js 要求:>= 18(使用原生 fetch / AbortSignal


快速开始

准备工作

在企业微信管理后台获取以下凭证:

| 凭证 | 用途 | 必需 | | --- | --- | --- | | 智能机器人 botId | 智能机器人 WebSocket 连接 | ✅ | | 智能机器人 secret | 智能机器人 WebSocket 连接 | ✅ | | 自建应用 corpId / corpSecret / agentId | Agent API 主动发送 | ❌(按需) | | 群机器人 webhook URL | 群消息推送 | ❌(按需) |


基础示例:接入 DeepSeek 智能体

import { WecomPlugin } from "langgraph-plugin-wecom";
import { ChatOpenAI } from "@langchain/openai";
import { StateGraph, MessagesAnnotation, START } from "@langchain/langgraph";
import { HumanMessage, SystemMessage } from "@langchain/core/messages";

// 1. 创建 DeepSeek LLM
const model = new ChatOpenAI({
  model: "deepseek-chat",
  apiKey: process.env.DEEPSEEK_API_KEY,
  configuration: { baseURL: "https://api.deepseek.com" },
});

// 2. 构建 LangGraph Agent
const agent = new StateGraph(MessagesAnnotation)
  .addNode("call_model", async (state) => ({
    messages: [await model.invoke([
      new SystemMessage("你是一个智能助手。"),
      ...state.messages,
    ])],
  }))
  .addEdge(START, "call_model")
  .compile();

// 3. 接入企业微信
const plugin = new WecomPlugin({
  botId: process.env.WECOM_BOT_ID!,
  secret: process.env.WECOM_SECRET!,
});

plugin.onMessage(async (message, reply) => {
  if (!message.text) return;
  const result = await agent.invoke({
    messages: [new HumanMessage(message.text)],
  });
  const content = result.messages[result.messages.length - 1].content;
  await reply.sendText(message.fromUserid, String(content));
});

await plugin.connect();

运行:

DEEPSEEK_API_KEY=sk-xxx WECOM_BOT_ID=xxx WECOM_SECRET=xxx npx tsx my-bot.ts

流式示例:逐 token 展示思考和回复

plugin.onMessage(async (message, reply) => {
  if (!message.text || !message.fromUserid) return;

  const streamId = plugin.newStreamId();
  const stream = await model.stream([
    new SystemMessage("你是一个智能助手。"),
    new HumanMessage(message.text),
  ]);

  let fullContent = "";
  for await (const chunk of stream) {
    const content = chunk.content;
    if (typeof content === "string" && content) {
      fullContent += content;
      // 每 1.5 秒推送一次到企微
      await reply.sendReasoningStream(streamId, {
        visibleText: fullContent,
        finish: false,
      });
    }
  }

  await reply.sendReasoningStream(streamId, {
    visibleText: fullContent,
    finish: true,
  });
});

关于思考过程:DeepSeek 的推理模型(如 deepseek-reasoner)通过 API 的 reasoning_content 字段返回思考过程,本插件的 sendReasoningStream 会自动用 <think> 标签包装推理内容,在企微端呈现思考→回答的完整流程。详见 examples/deepseek-agent.ts


主动发送(Agent API)

const plugin = new WecomPlugin({
  botId: process.env.WECOM_BOT_ID,
  secret: process.env.WECOM_SECRET,
  agent: {
    corpId: process.env.AGENT_CORP_ID,
    corpSecret: process.env.AGENT_CORP_SECRET,
    agentId: process.env.AGENT_ID,
  },
});

// 给用户发送 markdown 消息
await plugin.agentApi.sendText({
  toUser: "UserID",
  text: "**Hello** from LangGraph",
  format: "markdown",
});

Webhook 群通知

await plugin.webhook.sendMarkdown({
  url: process.env.WECOM_WEBHOOK_URL,
  content: "**告警**:服务异常,请及时处理。",
});

LangGraph Tool 集成(LLM 自主调用)

import { WecomPlugin, createWecomTools } from "langgraph-plugin-wecom";
import { createReactAgent } from "@langchain/langgraph/prebuilt";

const plugin = new WecomPlugin({ botId, secret, agent: { ... } });
const tools = createWecomTools({ plugin });

const agent = createReactAgent({ llm, tools });

LLM 现在可以自主调用 wecom_active_send_textwecom_send_textwecom_webhook_send_markdown 等工具。


API 参考

new WecomPlugin(config)

| 参数 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | botId | string | ✅ | 智能机器人 Bot ID | | secret | string | ✅ | 智能机器人 Secret | | agent | { corpId, corpSecret, agentId } | ❌ | 自建应用凭证 | | apiBaseUrl | string | ❌ | Agent API 基础地址(默认 https://qyapi.weixin.qq.com) | | proxyUrl | string | ❌ | HTTP 代理地址(需安装 undici) | | wsUrl | string | ❌ | 自定义 WebSocket 地址 | | autoReconnect | boolean | ❌ | 自动重连(默认 true) | | maxReconnectAttempts | number | ❌ | 最大重连次数 | | debug | boolean | ❌ | 调试日志 |

plugin.onMessage(handler)

plugin.onMessage(async (message, reply) => {
  // message: { msgid, chatid, chattype, fromUserid, msgtype, text, image, ... }
  // reply:   { sendText, sendStream, sendReasoningStream, sendMessage }
});

reply.sendText(userid, content)

发送 markdown 文本回复。

reply.sendStream(streamId, text, finish)

发送流式消息帧(需要自行组装 <think> 标签)。

reply.sendReasoningStream(streamId, options)

发送推理流式消息,自动处理 <think> 标签封装:

// 推理中(<think> 不闭合)
await reply.sendReasoningStream(streamId, {
  reasoningText: "正在分析问题...",
  finish: false,
});

// 推理完成 + 最终回复(<think> 自动闭合)
await reply.sendReasoningStream(streamId, {
  reasoningText: "分析完成",
  visibleText: "这是最终回复",
  finish: true,
});

reply.sendMessage(chatId, content)

sendText,语义别名。

plugin.sendText(userid, content)

智能机器人主动发送 markdown 消息。

plugin.sendStream(frame, streamId, text, finish)

主动发送流式消息帧。

plugin.newStreamId(prefix?)

生成流式消息 ID。

plugin.agentApi.*

| 方法 | 说明 | | --- | --- | | sendText({ toUser?, toParty?, toTag?, chatId?, text, format? }) | 发送文本 / markdown | | sendImage({ ... , mediaId }) | 发送图片 | | sendFile({ ... , mediaId }) | 发送文件 | | sendVoice({ ... , mediaId }) | 发送语音 | | sendVideo({ ... , mediaId }) | 发送视频 | | uploadMedia({ type, buffer, filename }) | 上传临时素材 | | downloadMedia({ mediaId }) | 下载临时素材 |

plugin.webhook.*

| 方法 | 说明 | | --- | --- | | sendText({ url, content, mentionedList?, mentionedMobileList? }) | 群机器人发文本 | | sendMarkdown({ url, content }) | 群机器人发 markdown | | sendImage({ url, base64, md5 }) | 群机器人发图片 | | sendFile({ url, mediaId }) | 群机器人发文件 | | uploadFile({ url, buffer, filename }) | 上传文件获取 media_id |

buildStreamContent(options)

独立工具函数,用于自行组装推理内容:

import { buildStreamContent } from "langgraph-plugin-wecom";

buildStreamContent({ reasoningText: "思考", visibleText: "回答", finish: true });
// → "<think>思考</think>\n回答"

createWecomTools({ plugin, enable? })

| 参数 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | plugin | WecomPlugin | — | 插件实例 | | enable.agentApi | boolean | true | 是否生成 Agent API 工具 | | enable.webhook | boolean | true | 是否生成 Webhook 工具 | | enable.activeSend | boolean | true | 是否生成主动发送工具 | | enable.uploadMedia | boolean | true | 是否生成上传素材工具 |

生成的 Tool 列表:wecom_active_send_textwecom_send_textwecom_send_media_filewecom_webhook_send_textwecom_webhook_send_markdownwecom_webhook_send_image

testAIBotConnection(credentials)

测试智能机器人连接是否正常:

const result = await testAIBotConnection({ botId: "xxx", secret: "yyy" });
console.log(result.success, result.message);

环境变量

| 变量 | 默认值 | 说明 | | --- | --- | --- | | WECOM_LOG_LEVEL | info | 日志级别:debug / info / warn / error / silent | | WECOM_EGRESS_PROXY_URL | — | HTTP 代理地址(需安装 undici) | | WECOM_API_BASE_URL | https://qyapi.weixin.qq.com | Agent API 自定义基础地址 | | LANGGRAPH_WECOM_STATE_DIR | ~/.langgraph-wecom | 持久化 reqId 存储目录 |


示例

所有示例位于 examples/ 目录:

| 示例 | 说明 | | --- | --- | | basic-bot.ts | 基础示例:连接测试、Agent API、Webhook、Tool 生成 | | thinking-test.ts | 思考过程模拟测试(无需 LLM,纯测流式) | | deepseek-agent.ts | DeepSeek 智能体完整示例(流式推理 + 思考过程) |

运行:

# 基础示例
BOT_ID=xxx SECRET=yyy npx tsx examples/basic-bot.ts

# 思考过程测试
WECOM_BOT_ID=xxx WECOM_SECRET=xxx npx tsx examples/thinking-test.ts

# DeepSeek 智能体
DEEPSEEK_API_KEY=sk-xxx WECOM_BOT_ID=xxx WECOM_SECRET=xxx npx tsx examples/deepseek-agent.ts

项目结构

langgraph-plugin-wecom/
├── index.ts                   # 根入口
├── package.json
├── tsconfig.json
├── src/
│   ├── index.ts               # 主入口
│   ├── wecom/
│   │   ├── constants.ts       # API 端点 / 限制 / 常量
│   │   ├── http.ts            # 统一 HTTP 客户端(代理 / 超时)
│   │   ├── ai-bot.ts          # 智能机器人 WebSocket 客户端
│   │   ├── agent-api.ts       # 自建应用 Agent API
│   │   ├── webhook-bot.ts     # 群机器人 Webhook
│   │   ├── think-parser.ts    # <think> 标签解析
│   │   ├── dynamic-agent.ts   # 动态 Agent ID
│   │   ├── reqid-store.ts     # 持久化 reqId 存储
│   │   └── index.ts
│   ├── plugin/
│   │   ├── wecom-plugin.ts    # WecomPlugin 主类
│   │   ├── tools.ts           # LangGraph Tool 封装
│   │   └── index.ts
│   ├── utils/
│   │   ├── logger.ts          # 结构化日志
│   │   ├── cache.ts           # TTLCache / 消息去重 / 文本切分
│   │   └── index.ts
│   └── langgraph/             # @deprecated 旧版兼容
│       ├── agent.ts
│       └── index.ts
├── examples/                  # 可运行示例
│   ├── basic-bot.ts
│   ├── thinking-test.ts
│   └── deepseek-agent.ts
├── tests/                     # 测试(62 个)
│   ├── ai-bot.test.ts
│   ├── agent-api.test.ts
│   ├── webhook-bot.test.ts
│   ├── http.test.ts
│   ├── cache.test.ts
│   ├── think-parser.test.ts
│   └── dynamic-agent.test.ts
├── scripts/
│   └── build.ts               # 构建脚本(esbuild + tsc)
├── dist/                      # 构建产物
└── .trae/
    ├── project_rules.md       # 项目约束
    └── documents/             # 计划文档

开发

# 安装依赖
npm install

# 类型检查
npm run typecheck

# 运行测试(62 个)
npm test

# 构建
npm run build

发布到 npm

# 1. 登录 npm
npm login

# 2. 构建
npm run build

# 3. 发布
npm publish

注意:发布前请确保 npm login 已登录,且包名 langgraph-plugin-wecom 在 npm 上未被占用。


License

MIT


致谢

本项目的企业微信通信实现复用了 openclaw-plugin-wecom 的相关模块,感谢其对企微通信的细致封装。


相关项目