# WeChatBot: four SDKs, one cursor, and the leader election it leaves to you

> WeChatBot is an MIT-licensed SDK family for the iLink Bot API, published for Node.js, Python, Go and Rust, aimed at wiring a WeChat account into an agent. The shared core is small and specific: QR login with persisted credentials, long polling with cursor management, automatic re-login when a session expires, and a context token that survives restarts. The interesting gap is multi-account deployment, where the SDK isolates storage per tenant and then tells you that leader election is your problem.

**corespeed-io/wechatbot** — 微信 iLink Bot SDK for OpenClaw/AI Agent

- Repository: https://github.com/corespeed-io/wechatbot
- Website: https://wechatbot.dev
- Stars: 663 · Forks: 91
- Language: TypeScript
- License: MIT
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/corespeed-io-wechatbot

## Four SDKs over one protocol, and they are not the same size

The repository ships four client libraries and marks all four production ready. The install line for each is the only thing that differs: an npm package under a scoped name, a pip package, a Go module path inside this repository, and a crate. Underneath, the implementations are uneven in a way the status column hides. The Node.js SDK is the largest, with eleven modules, eight test files and four example bots. The Python SDK is async on aiohttp with six modules and two test files. The Go SDK is written against the standard library only and splits into a bot client, a types file and an internal package covering protocol, auth and crypto. The Rust SDK has six modules. So one badge covers four codebases of different sizes and, more importantly, different test depth, with the Node.js side carrying four times the test files of the Python side. That does not make the others unusable, since the shared feature set is the part you need and it is implemented in all four, but it does mean the language you pick for convenience is also the language whose edge cases will be fixed first. The design is credited to an existing WeChat bot project from Tencent, and the stated goal is getting an agent connected in minutes.

## The cursor is the state, and two pollers on one account destroy it

Message reception is long polling with automatic cursor management, and that single phrase carries the reliability story. A poller holds a position in the message stream, and the cursor is what makes the next fetch continue where the last one stopped. Get it wrong in one direction and you reprocess messages you have already handled; get it wrong in the other and you silently skip messages, which in a bot that is answering questions looks like the bot going quiet. The SDK manages the cursor inside one instance and persists credentials under a dot-directory in the user's home, so a restart resumes the session without another QR scan. Session expiry is handled too, with the specific error code for an expired session triggering an automatic re-login. What the SDK does not do is stop two instances from polling the same account. The multi-account guidance is explicit that a given account may only have one polling instance across an entire cluster, because the cursors overwrite each other, and that a multi-machine deployment needs an advisory lock or a lease table to pick the leader. That is the deal: you get the client, the protocol and the state machine, and leader election is left to your infrastructure.

## Storage isolation is a correctness requirement, not a style preference

Each bot instance is fully isolated, with its own HTTP client, its own event set and its own message poller, no global state, and no local port to occupy, so a single backend process can run several WeChat accounts at once. The isolation that matters is not in memory, though. It is in storage. Every account needs its own storage directory or its own storage namespace, and the guidance is blunt that sharing one will overwrite each other's credentials. That failure mode deserves attention because it is silent: two tenants pointing at the same directory do not produce an error, they produce one tenant whose login state has been replaced by another's, and you find out when messages go to the wrong conversation. The multi-tenant example wires a Postgres storage per tenant, or a per-tenant directory under a data path, which is the pattern to copy. The other half of that example is how login becomes usable in a web product: the QR code is not printed to a terminal but handed to you through a callback, so the URL can be pushed to a specific user's page while other callbacks report that the code was scanned or has expired and should be refreshed.

## A context store sits between every subsystem and the network

The architecture is a small graph and it explains why the SDK has a storage layer at all. Your bot code talks to a client that acts as the core scheduler, which fans out to four subsystems: the poller, the sender, the typing indicator and media. All four reach a context store that caches tokens, and the context store is what talks to the protocol layer over HTTP, which in turn sits on top of the storage that holds credentials and state. The features that make this necessary are the unglamorous ones. A context token is handed out per conversation, has its own lifecycle, and is managed automatically across restarts, so you never handle it but you depend on it. The typing indicator needs a ticket, and that ticket is cached rather than fetched per keystroke. Media travels over the platform's CDN, and that transfer is encrypted with AES in ECB mode with support for two key formats. ECB is worth naming out loud, because it encrypts blocks independently and gives no semantic protection to repeated plaintext; it is the platform's choice for this channel rather than a decision the SDK made, and the documentation here does not explain what differs between the two key formats or why both are supported. If you are handling anything sensitive through that path, know that this is the layer to look at.

## Text is split at a paragraph, then a line, then a space

Sending a reply is where a bot most easily reveals itself, and the SDK has one specific answer to that: smart chunking that splits text on natural boundaries, trying a paragraph break first, then a line, then a space. The ordering is the design. A fixed character count is simple and produces the tell, because a sentence that stops mid-clause in a chat window is the most recognisable signature of an automated reply there is. Falling back through progressively smaller boundaries means a short message is never split at all, a paragraph is split between paragraphs, and only genuinely long unbroken text ends up cut at a space. What the documentation available here does not say is the threshold that triggers a split, whether anything beyond whitespace is considered when hunting for a boundary, or how a chunk boundary interacts with the context token when the reply spans several sends. Those are the questions to answer from the source before you rely on it for long-form content, and they are the difference between a bot that reads naturally and one that reads correctly.

## Only the Node.js package has middleware, storage adapters and typed events

Five capabilities exist on the Node.js side alone. There is a composable middleware pipeline in the style Express and Koa use, so you can wrap the client rather than editing it. Storage is pluggable across file, memory or anything you implement, with Redis and SQLite given as examples, which is what makes the per-tenant Postgres storage in the multi-tenant example possible. Events are typed, so a lifecycle handler gets completion in an editor instead of a string you mistype. Logging is structured, levelled, context-aware and transported through something you choose. And there is a chained message builder that composes text, image and file parts into one message. The other three SDKs ship the shared feature set and stop there. The storage adapter is the one that matters most in practice, because it is the seam where multi-tenancy and testability live, and it is only available in one of the four languages. On documentation, the repository carries a protocol reference for the iLink Bot API, an architecture document that includes a comparison of the SDKs, a README per language and one for the agent extension, while the bilingual documentation site and the full multi-tenant example have both moved to a separate repository. That is where to look if you want the long version of either.

## The pre-built bot points at a releases page with nothing on it

For people who do not want to write code, the documentation offers a pre-compiled echo bot and sends you to the project's releases page to get it, installed by piping a remote script into your shell on macOS or Linux, or by running the equivalent PowerShell command on Windows. ```python
from wechatbot import WeChatBot

bot = WeChatBot()

@bot.on_message
async def handle(msg):
    await bot.reply(msg, f"Echo: {msg.text}")

bot.run()  # 扫码登录 + 开始监听
``` Neither route can work right now, because the repository has no published releases, so the first half of the instruction has nothing behind it. Worth saying plainly as well: piping a script straight into an interpreter is the installer shape people are trained to be suspicious of, and these instructions carry no checksum and no way to read the script before running it. The documented alternative that does exist is the coding-assistant extension, which installs with a single command into the Pi agent and then uses one slash command to display a QR code for scanning from WeChat, after which the chat is connected to the assistant. The last commit on this repository is dated 29 September 2026, so the project itself is current; it is the packaged binary that is missing, which is a different kind of gap and an easy one for the maintainers to close.

## Conclusion

WeChatBot fits you if you are putting an agent or a bot behind a WeChat account you control and you want the protocol details handled for you: credential persistence, cursor bookkeeping, context token lifetime, media upload and download, and the session-expiry path that otherwise leaves you re-scanning by hand. It does not fit a production deployment spread over several machines until you have solved leader election yourself, because two pollers on one account corrupt each other's cursor and the SDK's own guidance is to bring an advisory lock or a lease table. Check three things before you commit. Give every account its own storage namespace from the first day, since a shared one silently overwrites credentials rather than raising. Decide which language you actually run, because the Node.js package is the only one with middleware, storage adapters and typed events while the other three ship the shared feature set. And read the section on installers before running anything piped into a shell, because the pre-built bot it points at is not currently published.

## FAQ

### Which programming languages does the WeChatBot SDK support?

Four, each published separately and each marked production ready: an npm package for Node.js, a pip package for Python, a Go module path inside the repository, and a crate for Rust. The Node.js SDK is the largest, with eleven modules, eight test files and four example bots, while the Go SDK uses only the standard library.

### Do I have to scan a QR code again every time the bot restarts?

No. Credentials are persisted under a dot-directory in your home directory, and calling login restores the session after a restart without another scan. If the session itself has expired, the SDK recognises the expiry code and logs in again automatically.

### Can I run several WeChat accounts from one process with WeChatBot?

Yes. Each instance has its own HTTP client, events and message poller, with no global state and no local port, so one backend can hold several accounts. Two rules follow: every account needs its own storage directory or namespace because sharing overwrites credentials, and only one instance may poll a given account across a cluster, which is why multi-machine setups need an advisory lock or a lease table.

### How does multi-tenant QR login work in WeChatBot?

Login accepts callbacks, so the QR code URL is handed to your code instead of being printed. The example pushes the URL to that tenant's own page, reports when the code has been scanned, and refreshes the code when it expires.

### How does WeChatBot split long replies?

It uses smart chunking on natural boundaries, trying a paragraph break first, then a line break, then a space, instead of cutting at a fixed character count. The documentation does not state the length that triggers a split.

### What protocol does the WeChatBot SDK talk to?

The iLink Bot API, with a protocol reference kept in the repository's documentation folder. The project credits an existing WeChat bot project from Tencent as its inspiration and also ships an extension that bridges WeChat to a coding assistant.

## Sources

- [corespeed-io/wechatbot on GitHub](https://github.com/corespeed-io/wechatbot)
- [Issues](https://github.com/corespeed-io/wechatbot/issues)
- [License: MIT](https://github.com/corespeed-io/wechatbot/blob/main/LICENSE)
- [Project website](https://wechatbot.dev)
- [README](https://github.com/corespeed-io/wechatbot/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/corespeed-io-wechatbot
