agim
One stateless interface for IM login, receive, and send. agim is a plain SDK: it owns no storage, no plugin registry, and no host concepts. Callers persist the login handshake and receive cursor themselves and hand them back on the next call.
Interface
class IMClient(ABC):
async def login(self) -> LoginHandshake: ...
async def is_login(self, handshake: LoginHandshake) -> LoginState: ...
async def receive(self, cursor: str | None = None) -> ReceiveResult: ...
async def send(self, chat_id: str, text: str, *, context_token: str | None = None) -> None: ...
async def aclose(self) -> None: ...
Because nothing is stored inside agim:
login()returns the QR payload and the provider state needed to poll it. Persist the wholeLoginHandshake, then pass it back tois_login().receive()returns the message and the next cursor. Persist the cursor, then pass it to the nextreceive().send()takes the context token the caller stored from the inbound message.
One getupdates poll can carry several messages. receive() still hands over
exactly one message per call: the rest of the batch waits in memory (oldest
first), and the returned cursor only advances past the batch once its last
message has been handed over, so a restart mid-batch re-delivers that batch
instead of dropping the messages behind the first one.
Platform clients
WeChatClient implements the Tencent personal WeChat iLink/ClawBot protocol
used by Tencent's official openclaw-weixin project: QR login, getupdates
long polling, and sendmessage. More platforms (for example Discord)
implement the same IMClient surface.
Inbound messages carry their attachments on InboundMessage.media, one
InboundMedia per image, voice note, file, or video. The client downloads the
CDN reference and removes the AES-128-ECB encryption before returning, so a
caller receives usable bytes; whether a given consumer reads an image, plays a
voice note, or ignores both is the caller's decision. An item that cannot be
downloaded or decrypted is logged and skipped: the message keeps the
[image]/[voice]/[file]/[video] placeholder in its text. An item over
MAX_MEDIA_BYTES raises MediaTooLargeError from fetch_media and is reported
on InboundMessage.rejected_media, so a caller can tell the sender that the
attachment was refused instead of losing it quietly.
Storage
None. Whoever calls agim owns persistence.
Metadata
Release files for agim 0.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| agim-0.0.1.tar.gz | 53.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| agim-0.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 70.0 kB
Release files / agim-0.0.1.tar.gz
| Download URL | agim-0.0.1.tar.gz |
|---|---|
| Size | 53.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fd3bbf1eb5a462beac79a9363d4fde07073a7a6f4163f8dedbcffbf07708331a
|
|
BLAKE2b-256 checksum How to use checksums |
61493f30855123c45cfc277e782604f49a115368a2df64052762584d63ae40b3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / agim-0.0.1-py3-none-any.whl
| Download URL | agim-0.0.1-py3-none-any.whl |
|---|---|
| Size | 16.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ebc77845616ca7073897b4c36345b892f904df779f449e27cc5ad4269e99c4e7
|
|
BLAKE2b-256 checksum How to use checksums |
391aaa548e736c73af063dc1c2e253af073a10c410f0901480263c950626250a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|