openclaw-agentmail-listener 0.4.1 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +39 -51
  2. package/dist/index.js +2 -2
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -5,52 +5,27 @@ An [OpenClaw](https://openclaw.ai) plugin that listens for incoming emails via [
5
5
  ## What it does
6
6
 
7
7
  - Registers a background service at gateway startup
8
- - Connects to AgentMail via WebSocket
8
+ - Connects to AgentMail via raw WebSocket (`wss://ws.agentmail.to/v0`)
9
9
  - Subscribes to a configured inbox (e.g. `nickbot@agentmail.to`)
10
- - When a `message.received` event fires, injects a system event via `core.system.enqueueSystemEvent()` with email metadata (from, subject, preview)
10
+ - When a `message.received` event fires, injects a system event with email metadata (from, subject, preview)
11
+ - Wakes the agent immediately via `requestHeartbeatNow()` so emails are processed right away
11
12
  - Auto-reconnects with exponential backoff on disconnect
13
+ - Keepalive pings every 30 seconds
12
14
  - Stops cleanly when the gateway shuts down
13
15
 
14
16
  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).
15
17
 
16
18
  ## Installation
17
19
 
18
- ### Option 1: Install from npm (recommended)
19
-
20
20
  ```bash
21
21
  openclaw plugins install openclaw-agentmail-listener
22
22
  ```
23
23
 
24
24
  Restart the gateway afterwards.
25
25
 
26
- ### Option 2: Install from GitHub
27
-
28
- ```bash
29
- git clone https://github.com/thisnick/openclaw-agentmail ~/.openclaw/extensions/agentmail-listener
30
- cd ~/.openclaw/extensions/agentmail-listener
31
- npm install
32
- openclaw gateway restart
33
- ```
34
-
35
- ### Option 3: Load via config path
36
-
37
- In your OpenClaw config (`~/.openclaw/openclaw.json`):
38
-
39
- ```json
40
- {
41
- "plugins": {
42
- "load": {
43
- "paths": ["/path/to/openclaw-agentmail"]
44
- }
45
- }
46
- }
47
- ```
48
-
49
- Then run `npm install` in the plugin directory and restart the gateway.
50
-
51
26
  ## Configuration
52
27
 
53
- Add to your OpenClaw config under `plugins.entries.agentmail-listener.config`:
28
+ Add to your OpenClaw config under `plugins.entries`:
54
29
 
55
30
  ```json
56
31
  {
@@ -60,9 +35,7 @@ Add to your OpenClaw config under `plugins.entries.agentmail-listener.config`:
60
35
  "enabled": true,
61
36
  "config": {
62
37
  "apiKey": "am_us_your_key_here",
63
- "inboxId": "yourbot@agentmail.to",
64
- "eventTypes": ["message.received"],
65
- "sessionKey": "agent:main:main"
38
+ "inboxId": "yourbot@agentmail.to"
66
39
  }
67
40
  }
68
41
  }
@@ -78,7 +51,6 @@ Add to your OpenClaw config under `plugins.entries.agentmail-listener.config`:
78
51
  | `inboxId` | string | ✅ | — | Inbox to subscribe (e.g. `nickbot@agentmail.to`) |
79
52
  | `eventTypes` | string[] | — | `["message.received"]` | Event types to subscribe to |
80
53
  | `sessionKey` | string | — | `"agent:main:main"` | Agent session key for routing system events |
81
- | `wake` | string | — | `"tools-invoke"` | Wake method: `"tools-invoke"` (default), `"hooks"`, or `"off"` |
82
54
 
83
55
  ## System event format
84
56
 
@@ -91,33 +63,49 @@ Subject: Hello there
91
63
  Preview: This is the first 200 chars of the email body...
92
64
  ```
93
65
 
94
- The event is keyed with `contextKey: agentmail:<messageId>` to deduplicate repeated events for the same message.
66
+ The event is keyed with `contextKey: cron:agentmail:<messageId>` so it is both deduplicated and surfaced in the heartbeat prompt (see [How wake works](#how-wake-works) for details).
67
+
68
+ ## How wake works
69
+
70
+ After enqueuing a system event, the plugin calls `requestHeartbeatNow()` with reason `"exec-event"`. This does two things:
95
71
 
96
- ## Instant wake
72
+ 1. **Bypasses file gates** — the heartbeat fires immediately without requiring HEARTBEAT.md
73
+ 2. **Inspects pending events** — the enqueued system event is included in the heartbeat prompt
97
74
 
98
- By default, system events are only processed when the agent's heartbeat fires (which can be up to 1 hour). This plugin triggers an **immediate wake** after enqueuing each email event by calling the gateway's cron wake endpoint (`POST /tools/invoke`).
75
+ 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.
99
76
 
100
- ### Wake methods
77
+ > **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.
101
78
 
102
- | Method | Auth | When to use |
103
- |--------|------|-------------|
104
- | `tools-invoke` (default) | `gateway.auth.token` | Works out of the box, no extra config |
105
- | `hooks` | `hooks.token` | If you already have hooks enabled |
106
- | `off` | — | Disable wake; rely on heartbeat polling |
79
+ **Important config for proactive delivery:**
80
+
81
+ 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"`).
82
+
83
+ ```json
84
+ {
85
+ "agents": {
86
+ "defaults": {
87
+ "heartbeat": {
88
+ "every": "1h",
89
+ "target": "whatsapp"
90
+ }
91
+ }
92
+ }
93
+ }
94
+ ```
107
95
 
108
- The plugin reads port and token from your OpenClaw config automatically.
96
+ **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).
109
97
 
110
- ## Architecture notes
98
+ ## Architecture
111
99
 
112
- - The plugin uses the `agentmail` npm package's WebSocket client
113
- - Reconnection uses exponential backoff (1s → 2s → 4s → ... → 60s max) with ±10% jitter
114
- - Re-subscription happens automatically on each reconnect (WebSocket `open` event)
115
- - Uses `api.runtime.system.enqueueSystemEvent()` to route events to the agent session
116
- - After enqueuing, triggers an immediate agent wake via the gateway's `/tools/invoke` endpoint (cron wake action) so the agent processes the email right away instead of waiting for the next heartbeat poll
100
+ - **Raw WebSocket** connects directly to `wss://ws.agentmail.to/v0` with API key as query param (no SDK dependency for the WebSocket layer)
101
+ - **Reconnection** exponential backoff (1s → 2s → 4s → ... → 60s max) with ±10% jitter
102
+ - **Keepalive** sends WebSocket pings every 30 seconds
103
+ - **In-process wake** — uses `api.runtime.system.requestHeartbeatNow()` with `reason: "exec-event"` (no HTTP round-trips)
104
+ - **System events** uses `api.runtime.system.enqueueSystemEvent()` with `cron:`-prefixed contextKey to ensure prompt visibility
117
105
 
118
106
  ## Dependencies
119
107
 
120
- - `agentmail` ^0.2.17AgentMail TypeScript SDK
108
+ - `ws` ^8.18.0WebSocket client for Node.js
121
109
 
122
110
  ## License
123
111
 
package/dist/index.js CHANGED
@@ -192,10 +192,10 @@ function handleEventInner(api, cfg, event) {
192
192
  const sessionKey = cfg.sessionKey ?? "agent:main:main";
193
193
  api.runtime.system.enqueueSystemEvent(eventText, {
194
194
  sessionKey,
195
- contextKey: `agentmail:${messageId}`
195
+ contextKey: `cron:agentmail:${messageId}`
196
196
  });
197
197
  api.runtime.system.requestHeartbeatNow({
198
- reason: "agentmail: new email",
198
+ reason: "exec-event",
199
199
  sessionKey
200
200
  });
201
201
  api.logger.info("agentmail-listener: heartbeat wake requested");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-agentmail-listener",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "type": "module",
5
5
  "description": "OpenClaw plugin: AgentMail listener — injects system events when emails arrive",
6
6
  "files": [