@agent-pulse/elizaos-plugin 0.1.0

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.
package/README.md ADDED
@@ -0,0 +1,309 @@
1
+ # @openclaw/eliza-plugin-pulse
2
+
3
+ ElizaOS plugin for the [Agent Pulse](https://agentpulse.io) protocol with **gate functionality** for secure agent-to-agent interactions.
4
+
5
+ ## Overview
6
+
7
+ Agent Pulse is a decentralized liveness protocol where agents prove they're alive by transferring PULSE tokens to a signal sink. This plugin extends the base functionality with **gate capabilities** that validate incoming/outgoing interactions based on on-chain liveness signals.
8
+
9
+ ### Features
10
+
11
+ - ✅ **Standard Pulse Actions**: Send pulses, check status, monitor protocol health
12
+ - 🔒 **Inbound Gate**: Validates incoming messages from external agents before processing
13
+ - 🚪 **Outbound Gate**: Checks target agent status before sending responses
14
+ - 📊 **v2 Analytics**: Reliability metrics, liveness proofs, global stats, peer correlation
15
+ - ⚙️ **Multiple Modes**: Strict, permissive, and audit modes for different security needs
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install @openclaw/eliza-plugin-pulse
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ### 1. Add to Your Character File
26
+
27
+ ```json
28
+ {
29
+ "name": "MyAgent",
30
+ "plugins": ["@openclaw/eliza-plugin-pulse"],
31
+ "settings": {
32
+ "pulse": {
33
+ "gate": {
34
+ "enabled": true,
35
+ "mode": "strict",
36
+ "threshold": "24h"
37
+ },
38
+ "contractAddress": "0xe61C615743A02983A46aFF66Db035297e8a43846",
39
+ "chainId": 84532
40
+ }
41
+ }
42
+ }
43
+ ```
44
+
45
+ ### 2. Environment Variables (Optional)
46
+
47
+ ```bash
48
+ AGENT_PULSE_RPC_URL=https://sepolia.base.org
49
+ AGENT_PULSE_API_URL=https://api.agentpulse.io
50
+ AGENT_PULSE_TOKEN_ADDRESS=0x21111B39A502335aC7e45c4574Dd083A69258b07
51
+ AGENT_PULSE_REGISTRY_ADDRESS=0xe61C615743A02983A46aFF66Db035297e8a43846
52
+ ```
53
+
54
+ ## Gate Configuration
55
+
56
+ The gate reads configuration from `character.settings.pulse`:
57
+
58
+ ```json
59
+ {
60
+ "settings": {
61
+ "pulse": {
62
+ "gate": {
63
+ "enabled": true, // Enable/disable the gate
64
+ "mode": "strict", // "strict" | "permissive" | "audit"
65
+ "threshold": "24h" // Max age for considering agent alive
66
+ },
67
+ "contractAddress": "0xe61C615743A02983A46aFF66Db035297e8a43846",
68
+ "chainId": 84532,
69
+ "rpcUrl": "https://sepolia.base.org" // Optional override
70
+ }
71
+ }
72
+ }
73
+ ```
74
+
75
+ ### Gate Modes
76
+
77
+ | Mode | Behavior | Use Case |
78
+ |------|----------|----------|
79
+ | `strict` | Block messages from agents that fail `isAlive()` check | High-security environments |
80
+ | `permissive` | Allow all messages, flag suspicious ones with warnings | Balanced security/UX |
81
+ | `audit` | Always allow, log all checks (dry-run) | Testing and monitoring |
82
+
83
+ ### Threshold Format
84
+
85
+ The threshold accepts ISO 8601 duration formats:
86
+
87
+ - `"24h"` - 24 hours
88
+ - `"1d"` - 1 day
89
+ - `"12h"` - 12 hours
90
+ - `"PT6H"` - 6 hours (ISO format)
91
+
92
+ ## How the Gate Works
93
+
94
+ ### Inbound Gate (Evaluator)
95
+
96
+ Runs **before all other evaluators** for every message:
97
+
98
+ 1. **Identity Extraction**: Extracts sender's Ethereum address from:
99
+ - Message text (e.g., "I'm agent 0x1234...")
100
+ - User metadata
101
+ - Sender ID (if it looks like an address)
102
+
103
+ 2. **Agent Detection**: Determines if sender is likely an agent using heuristics:
104
+ - Contains Ethereum addresses
105
+ - Agent-specific keywords (pulse, stake, smart contract)
106
+ - Agent-like metadata markers
107
+
108
+ 3. **IsAlive Check**: Calls Pulse API to verify:
109
+ - Is the agent registered?
110
+ - When was the last pulse?
111
+ - Is it within the threshold?
112
+
113
+ 4. **Decision**: Based on mode:
114
+ - `strict`: Block if not alive
115
+ - `permissive`: Allow but flag
116
+ - `audit`: Allow and log
117
+
118
+ ### Outbound Gate (Action Wrapper)
119
+
120
+ Wraps all action handlers to check target agents:
121
+
122
+ 1. **Target Extraction**: Identifies recipient from:
123
+ - Action options (`targetAddress`)
124
+ - State from inbound gate (replying to an agent)
125
+ - Message content
126
+
127
+ 2. **Status Check**: Verifies target's liveness
128
+
129
+ 3. **Action Control**: Blocks or proceeds based on decision
130
+
131
+ ## Edge Cases
132
+
133
+ The gate handles these scenarios gracefully:
134
+
135
+ | Scenario | Behavior |
136
+ |----------|----------|
137
+ | **No pulse settings** | Gate is no-op (disabled), all interactions allowed |
138
+ | **RPC unreachable** | Degrades per mode: strict=block, permissive/audit=allow |
139
+ | **Non-agent user** | Skips gate entirely (humans pass through) |
140
+ | **No identity found** | strict=block, others=skip |
141
+ | **Agent never pulsed** | Treated as not alive (fails check) |
142
+ | **Cache expired** | Re-checks status with 1-minute caching |
143
+
144
+ ## Example Character
145
+
146
+ See [example-gated-character.json](./example-gated-character.json) for a complete example of an agent configured with:
147
+
148
+ - Strict gate mode enabled
149
+ - 24-hour liveness threshold
150
+ - Security-focused personality
151
+ - Helpful responses for verified agents
152
+
153
+ ## Actions
154
+
155
+ ### SEND_PULSE
156
+ Send a liveness pulse to prove the agent is alive.
157
+
158
+ ```
159
+ User: "Send a pulse for my agent"
160
+ Agent: "✅ Pulse sent successfully! Transaction: 0xabc... Streak: 5"
161
+ ```
162
+
163
+ ### GET_AGENT_STATUS
164
+ Get the current status of an agent.
165
+
166
+ ```
167
+ User: "Check my agent status"
168
+ Agent: "**Agent Status: 0x742d...0bEb**
169
+ 🟢 Alive
170
+ • Last Pulse: 2 hours ago
171
+ • Streak: 🔥 5 days
172
+ • Hazard Score: ✅ 0/100"
173
+ ```
174
+
175
+ ### GET_RELIABILITY (v2 - Paid)
176
+ Get comprehensive reliability metrics.
177
+
178
+ ```
179
+ User: "Check reliability"
180
+ Agent: "Agent reliability: 92.3%
181
+ Uptime: 99.1%
182
+ Jitter: 0.08
183
+ Hazard Rate: 0.02"
184
+ ```
185
+
186
+ **Price:** $0.01 USDC
187
+
188
+ ### GET_LIVENESS_PROOF (v2 - Paid)
189
+ Get a cryptographically signed proof of liveness.
190
+
191
+ ```
192
+ User: "Get liveness proof"
193
+ Agent: "✅ Alive | Proof: eyJhbG..."
194
+ ```
195
+
196
+ **Price:** $0.005 USDC
197
+
198
+ ### GET_GLOBAL_STATS (v2 - Paid)
199
+ Get network-wide aggregate statistics.
200
+
201
+ ```
202
+ User: "Show network stats"
203
+ Agent: "Active Agents: 1,500
204
+ Average Streak: 30.5 days
205
+ Network Health: ✅ Healthy"
206
+ ```
207
+
208
+ **Price:** $0.03 USDC
209
+
210
+ ### GET_PEER_CORRELATION (v2 - Paid)
211
+ Find agents with correlated liveness patterns.
212
+
213
+ ```
214
+ User: "Find similar agents"
215
+ Agent: "Correlation: 0.78
216
+ Similar agents: 2 found
217
+ Cluster: copywriters-west"
218
+ ```
219
+
220
+ **Price:** $0.02 USDC
221
+
222
+ ## Providers
223
+
224
+ ### PULSE_STATE
225
+ Provides current state from the Agent Pulse protocol:
226
+
227
+ ```
228
+ Agent Pulse Protocol:
229
+ Protocol: ✅ HEALTHY | 1,234 agents
230
+ Agent: 🟢 Alive | 🔥 5 | 2h ago
231
+ TTL: 24h | Min pulse: 1 PULSE
232
+ ```
233
+
234
+ ## Programmatic Usage
235
+
236
+ ### Check if an Agent is Alive
237
+
238
+ ```typescript
239
+ import { isAlive, getPulseGateSettings } from "@openclaw/eliza-plugin-pulse";
240
+
241
+ const settings = getPulseGateSettings(runtime);
242
+ if (settings) {
243
+ const result = await isAlive(
244
+ "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
245
+ settings,
246
+ runtime
247
+ );
248
+
249
+ console.log(result.allowed); // true/false
250
+ console.log(result.reason); // Explanation if not allowed
251
+ console.log(result.status); // Full status object
252
+ }
253
+ ```
254
+
255
+ ### Extract Identity from Message
256
+
257
+ ```typescript
258
+ import { extractIdentity, isLikelyAgent } from "@openclaw/eliza-plugin-pulse";
259
+
260
+ const identity = extractIdentity(message, runtime);
261
+ if (identity.found) {
262
+ console.log(identity.address); // Ethereum address
263
+ console.log(identity.source); // "signature" | "claimed" | "inferred"
264
+ }
265
+
266
+ const isAgent = isLikelyAgent(message, runtime);
267
+ ```
268
+
269
+ ### Manual Gate Check
270
+
271
+ ```typescript
272
+ import { makeGateDecision } from "@openclaw/eliza-plugin-pulse";
273
+
274
+ const decision = makeGateDecision(
275
+ "strict", // mode
276
+ checkResult, // GateCheckResult from isAlive()
277
+ identity // ExtractedIdentity
278
+ );
279
+
280
+ console.log(decision.allow); // true/false
281
+ console.log(decision.flag); // true/false
282
+ console.log(decision.log); // true/false
283
+ ```
284
+
285
+ ## Contract Addresses
286
+
287
+ **Base Sepolia (Chain ID: 84532)**
288
+ - PulseRegistry: `0xe61C615743A02983A46aFF66Db035297e8a43846`
289
+ - PulseToken: `0x21111B39A502335aC7e45c4574Dd083A69258b07`
290
+
291
+ ## Development
292
+
293
+ ```bash
294
+ # Install dependencies
295
+ npm install
296
+
297
+ # Build
298
+ npm run build
299
+
300
+ # Type check
301
+ npm run typecheck
302
+
303
+ # Watch mode
304
+ npm run dev
305
+ ```
306
+
307
+ ## License
308
+
309
+ MIT