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

openclaw-agentmail-listener

v0.4.3

Published

OpenClaw plugin: AgentMail listener — injects system events when emails arrive

Readme

openclaw-agentmail-listener

An OpenClaw plugin that listens for incoming emails via AgentMail WebSocket and injects system events so your AI agent can act on them.

What it does

  • Registers a background service at gateway startup
  • Connects to AgentMail via raw WebSocket (wss://ws.agentmail.to/v0)
  • Subscribes to a configured inbox (e.g. [email protected])
  • When a message.received event fires, injects a system event with email metadata (from, subject, preview)
  • Wakes the agent immediately via requestHeartbeatNow() so emails are processed right away
  • Auto-reconnects with exponential backoff on disconnect
  • Keepalive pings every 30 seconds
  • Stops cleanly when the gateway shuts down

This is not a channel plugin — it doesn't handle replies. It just triggers system events so the agent notices new emails and can decide what to do (e.g. read the full message via the AgentMail skill and reply).

Installation

openclaw plugins install openclaw-agentmail-listener

Restart the gateway afterwards.

Configuration

Add to your OpenClaw config under plugins.entries:

{
  "plugins": {
    "entries": {
      "openclaw-agentmail-listener": {
        "enabled": true,
        "config": {
          "apiKey": "am_us_your_key_here",
          "inboxId": "[email protected]"
        }
      }
    }
  }
}

Config fields

| Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | apiKey | string | ✅ | — | Your AgentMail API key | | inboxId | string | ✅ | — | Inbox to subscribe (e.g. [email protected]) | | eventTypes | string[] | — | ["message.received"] | Event types to subscribe to | | sessionKey | string | — | "agent:main:main" | Agent session key for routing system events |

System event format

When an email arrives, the plugin injects a system event like:

📧 New email in [email protected]
From: [email protected]
Subject: Hello there
Preview: This is the first 200 chars of the email body...

The event is keyed with contextKey: cron:agentmail:<messageId> so it is both deduplicated and surfaced in the heartbeat prompt (see How wake works for details).

How wake works

After enqueuing a system event, the plugin calls requestHeartbeatNow() with reason "exec-event". This does two things:

  1. Bypasses file gates — the heartbeat fires immediately without requiring HEARTBEAT.md
  2. Inspects pending events — the enqueued system event is included in the heartbeat prompt

The cron: prefix on the contextKey ensures the event passes through OpenClaw's hasTaggedCronEvents check, which enables event inspection and renders the email content via buildCronEventPrompt. Without this prefix, the event would be enqueued but silently discarded from the prompt.

Why not reason: "wake"? The "wake" reason bypasses file gates but does not enable shouldInspectPendingEvents in the heartbeat runner, so system events are ignored. "exec-event" enables both.

Important config for proactive delivery:

The heartbeat target must be set to a channel (e.g. "whatsapp", "telegram") or "last" — otherwise the agent processes the email but the response is silently dropped (default target is "none").

{
  "agents": {
    "defaults": {
      "heartbeat": {
        "every": "1h",
        "target": "whatsapp"
      }
    }
  }
}

Note: The requests-in-flight check is global — if any conversation is active on any channel, the wake is deferred (retries every 1s until the queue clears).

Architecture

  • Raw WebSocket — connects directly to wss://ws.agentmail.to/v0 with API key as query param (no SDK dependency for the WebSocket layer)
  • Reconnection — exponential backoff (1s → 2s → 4s → ... → 60s max) with ±10% jitter
  • Keepalive — sends WebSocket pings every 30 seconds
  • In-process wake — uses api.runtime.system.requestHeartbeatNow() with reason: "exec-event" (no HTTP round-trips)
  • System events — uses api.runtime.system.enqueueSystemEvent() with cron:-prefixed contextKey to ensure prompt visibility

Dependencies

  • ws ^8.18.0 — WebSocket client for Node.js

License

MIT