@dp-pcs/ogp 0.2.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.
Files changed (82) hide show
  1. package/README.md +437 -0
  2. package/dist/cli/agent-comms.d.ts +55 -0
  3. package/dist/cli/agent-comms.d.ts.map +1 -0
  4. package/dist/cli/agent-comms.js +217 -0
  5. package/dist/cli/agent-comms.js.map +1 -0
  6. package/dist/cli/expose.d.ts +3 -0
  7. package/dist/cli/expose.d.ts.map +1 -0
  8. package/dist/cli/expose.js +104 -0
  9. package/dist/cli/expose.js.map +1 -0
  10. package/dist/cli/federation.d.ts +28 -0
  11. package/dist/cli/federation.d.ts.map +1 -0
  12. package/dist/cli/federation.js +409 -0
  13. package/dist/cli/federation.js.map +1 -0
  14. package/dist/cli/install.d.ts +3 -0
  15. package/dist/cli/install.d.ts.map +1 -0
  16. package/dist/cli/install.js +111 -0
  17. package/dist/cli/install.js.map +1 -0
  18. package/dist/cli/setup.d.ts +2 -0
  19. package/dist/cli/setup.d.ts.map +1 -0
  20. package/dist/cli/setup.js +33 -0
  21. package/dist/cli/setup.js.map +1 -0
  22. package/dist/cli.d.ts +3 -0
  23. package/dist/cli.d.ts.map +1 -0
  24. package/dist/cli.js +305 -0
  25. package/dist/cli.js.map +1 -0
  26. package/dist/daemon/agent-comms.d.ts +76 -0
  27. package/dist/daemon/agent-comms.d.ts.map +1 -0
  28. package/dist/daemon/agent-comms.js +188 -0
  29. package/dist/daemon/agent-comms.js.map +1 -0
  30. package/dist/daemon/doorman.d.ts +52 -0
  31. package/dist/daemon/doorman.d.ts.map +1 -0
  32. package/dist/daemon/doorman.js +203 -0
  33. package/dist/daemon/doorman.js.map +1 -0
  34. package/dist/daemon/intent-registry.d.ts +11 -0
  35. package/dist/daemon/intent-registry.d.ts.map +1 -0
  36. package/dist/daemon/intent-registry.js +101 -0
  37. package/dist/daemon/intent-registry.js.map +1 -0
  38. package/dist/daemon/keypair.d.ts +5 -0
  39. package/dist/daemon/keypair.d.ts.map +1 -0
  40. package/dist/daemon/keypair.js +25 -0
  41. package/dist/daemon/keypair.js.map +1 -0
  42. package/dist/daemon/message-handler.d.ts +20 -0
  43. package/dist/daemon/message-handler.d.ts.map +1 -0
  44. package/dist/daemon/message-handler.js +159 -0
  45. package/dist/daemon/message-handler.js.map +1 -0
  46. package/dist/daemon/notify.d.ts +7 -0
  47. package/dist/daemon/notify.d.ts.map +1 -0
  48. package/dist/daemon/notify.js +54 -0
  49. package/dist/daemon/notify.js.map +1 -0
  50. package/dist/daemon/peers.d.ts +66 -0
  51. package/dist/daemon/peers.d.ts.map +1 -0
  52. package/dist/daemon/peers.js +171 -0
  53. package/dist/daemon/peers.js.map +1 -0
  54. package/dist/daemon/reply-handler.d.ts +67 -0
  55. package/dist/daemon/reply-handler.d.ts.map +1 -0
  56. package/dist/daemon/reply-handler.js +176 -0
  57. package/dist/daemon/reply-handler.js.map +1 -0
  58. package/dist/daemon/scopes.d.ts +62 -0
  59. package/dist/daemon/scopes.d.ts.map +1 -0
  60. package/dist/daemon/scopes.js +113 -0
  61. package/dist/daemon/scopes.js.map +1 -0
  62. package/dist/daemon/server.d.ts +8 -0
  63. package/dist/daemon/server.d.ts.map +1 -0
  64. package/dist/daemon/server.js +286 -0
  65. package/dist/daemon/server.js.map +1 -0
  66. package/dist/shared/config.d.ts +42 -0
  67. package/dist/shared/config.d.ts.map +1 -0
  68. package/dist/shared/config.js +42 -0
  69. package/dist/shared/config.js.map +1 -0
  70. package/dist/shared/signing.d.ts +13 -0
  71. package/dist/shared/signing.d.ts.map +1 -0
  72. package/dist/shared/signing.js +46 -0
  73. package/dist/shared/signing.js.map +1 -0
  74. package/docs/agent-comms.md +277 -0
  75. package/docs/federation-flow.md +407 -0
  76. package/docs/quickstart.md +241 -0
  77. package/docs/scopes.md +198 -0
  78. package/package.json +57 -0
  79. package/scripts/install-skills.js +32 -0
  80. package/skills/ogp/SKILL.md +235 -0
  81. package/skills/ogp-agent-comms/SKILL.md +345 -0
  82. package/skills/ogp-expose/SKILL.md +281 -0
@@ -0,0 +1,277 @@
1
+ # Agent Communications (v0.2.0)
2
+
3
+ The `agent-comms` intent enables rich agent-to-agent communication with topic routing, priority levels, and reply support.
4
+
5
+ ## Overview
6
+
7
+ Unlike simple `message` intent, `agent-comms` is designed for:
8
+ - **Topic-based routing**: Messages categorized by topic
9
+ - **Priority handling**: Low, normal, or high priority
10
+ - **Conversation threading**: Multi-turn conversations via `conversationId`
11
+ - **Async replies**: Callback or polling mechanisms
12
+
13
+ ## Message Schema
14
+
15
+ ```typescript
16
+ {
17
+ intent: 'agent-comms',
18
+ from: 'peer-id',
19
+ to: 'your-id',
20
+ nonce: 'unique-id',
21
+ timestamp: 'ISO-8601',
22
+ replyTo?: 'callback-url', // Optional callback for reply
23
+ conversationId?: 'thread-id', // Optional thread identifier
24
+ payload: {
25
+ topic: string, // Required: routing category
26
+ message: string, // Required: message content
27
+ priority?: 'low' | 'normal' | 'high' // Optional: default 'normal'
28
+ }
29
+ }
30
+ ```
31
+
32
+ ## CLI Usage
33
+
34
+ ### Send Agent-Comms
35
+
36
+ ```bash
37
+ # Basic message
38
+ ogp federation agent <peer-id> <topic> <message>
39
+
40
+ # With priority
41
+ ogp federation agent stan memory-management "Question" --priority high
42
+
43
+ # With conversation threading
44
+ ogp federation agent stan project-alpha "Follow-up" --conversation conv-123
45
+
46
+ # Wait for reply
47
+ ogp federation agent stan queries "Status?" --wait --timeout 60000
48
+ ```
49
+
50
+ ### Examples
51
+
52
+ ```bash
53
+ # Ask about memory management
54
+ ogp federation agent stan memory-management "How do you persist context across sessions?"
55
+
56
+ # High-priority task delegation
57
+ ogp federation agent alice task-delegation "Deploy staging ASAP" --priority high
58
+
59
+ # Query with reply waiting
60
+ ogp federation agent bob queries "What's the current status of project-alpha?" --wait
61
+ ```
62
+
63
+ ## Topic Categories
64
+
65
+ Topics are arbitrary strings that you define based on your use case. Common patterns:
66
+
67
+ | Topic | Description |
68
+ |-------|-------------|
69
+ | `memory-management` | Context and memory operations |
70
+ | `task-delegation` | Task assignment and coordination |
71
+ | `project-*` | Project-specific discussions |
72
+ | `queries` | General questions |
73
+ | `status-updates` | Status and progress reports |
74
+ | `planning` | Planning and scheduling |
75
+
76
+ ### Topic Restrictions
77
+
78
+ Receiving gateways can restrict which topics a peer can use:
79
+
80
+ ```bash
81
+ # Grant Stan only memory and task topics
82
+ ogp federation approve stan \
83
+ --intents agent-comms \
84
+ --topics memory-management,task-delegation
85
+
86
+ # Stan can now send to memory-management ✓
87
+ # Stan cannot send to billing ✗ (403 Topic not allowed)
88
+ ```
89
+
90
+ ## Priority Levels
91
+
92
+ | Priority | Behavior |
93
+ |----------|----------|
94
+ | `low` | Background, non-urgent |
95
+ | `normal` | Standard handling (default) |
96
+ | `high` | Expedited, visible indicator |
97
+
98
+ Priority is indicated in notifications:
99
+ ```
100
+ [OGP Agent-Comms] [HIGH] Stan → task-delegation: Deploy staging ASAP
101
+ [OGP Agent-Comms] Alice → queries: What's the status?
102
+ [OGP Agent-Comms] [low] Bob → updates: Daily summary attached
103
+ ```
104
+
105
+ ## Reply Mechanism
106
+
107
+ ### Callback Pattern (Preferred)
108
+
109
+ When you send with `--wait`, your gateway provides a callback URL:
110
+
111
+ ```
112
+ replyTo: https://your-gateway.com/federation/reply/nonce-123
113
+ ```
114
+
115
+ The receiving gateway can POST a reply to this URL:
116
+
117
+ ```json
118
+ {
119
+ "reply": {
120
+ "nonce": "nonce-123",
121
+ "success": true,
122
+ "data": { "answer": "We use PostgreSQL for persistence" },
123
+ "timestamp": "2026-03-23T10:30:00Z"
124
+ },
125
+ "signature": "..."
126
+ }
127
+ ```
128
+
129
+ ### Polling Pattern (Fallback)
130
+
131
+ If callback fails or isn't provided, senders can poll:
132
+
133
+ ```bash
134
+ # Sender polls for reply
135
+ GET /federation/reply/nonce-123
136
+ ```
137
+
138
+ Response:
139
+ ```json
140
+ {
141
+ "nonce": "nonce-123",
142
+ "status": "complete",
143
+ "reply": {
144
+ "success": true,
145
+ "data": { "answer": "..." },
146
+ "timestamp": "..."
147
+ }
148
+ }
149
+ ```
150
+
151
+ Or if not ready:
152
+ ```json
153
+ {
154
+ "nonce": "nonce-123",
155
+ "status": "pending",
156
+ "message": "Reply not yet available"
157
+ }
158
+ ```
159
+
160
+ ## Conversation Threading
161
+
162
+ Use `conversationId` for multi-turn conversations:
163
+
164
+ ```bash
165
+ # Start conversation
166
+ ogp federation agent stan project "Let's plan the sprint" --conversation sprint-42
167
+
168
+ # Continue conversation
169
+ ogp federation agent stan project "What about the API changes?" --conversation sprint-42
170
+
171
+ # Both messages share the same thread
172
+ ```
173
+
174
+ The receiving gateway sees the `conversationId` in metadata:
175
+ ```json
176
+ {
177
+ "ogp": {
178
+ "intent": "agent-comms",
179
+ "topic": "project",
180
+ "message": "What about the API changes?",
181
+ "conversationId": "sprint-42",
182
+ "nonce": "msg-456"
183
+ }
184
+ }
185
+ ```
186
+
187
+ ## OpenClaw Integration
188
+
189
+ When agent-comms arrives, your OpenClaw agent receives a notification:
190
+
191
+ ```
192
+ [OGP Agent-Comms] [HIGH] Stan → memory-management: How do you persist context?
193
+ ```
194
+
195
+ Metadata includes full context:
196
+ ```json
197
+ {
198
+ "ogp": {
199
+ "from": "stan:18790",
200
+ "intent": "agent-comms",
201
+ "nonce": "abc-123",
202
+ "topic": "memory-management",
203
+ "message": "How do you persist context?",
204
+ "priority": "high",
205
+ "replyTo": "https://stan.example.com/federation/reply/abc-123",
206
+ "conversationId": "conv-001"
207
+ }
208
+ }
209
+ ```
210
+
211
+ ## Rate Limiting
212
+
213
+ Agent-comms respects per-peer rate limits:
214
+
215
+ ```bash
216
+ # Grant 10 messages per minute
217
+ ogp federation approve stan --intents agent-comms --rate 10/60
218
+ ```
219
+
220
+ Exceeding the limit returns:
221
+ ```
222
+ HTTP 429 Too Many Requests
223
+ Retry-After: 42
224
+ ```
225
+
226
+ ## Security Best Practices
227
+
228
+ 1. **Use topic restrictions**: Grant only necessary topics
229
+ 2. **Set appropriate rate limits**: Prevent abuse
230
+ 3. **Verify sender context**: Check peer identity in notifications
231
+ 4. **Monitor high-priority**: Track high-priority message patterns
232
+ 5. **Review conversation threads**: Watch for suspicious threading
233
+
234
+ ## Example Flows
235
+
236
+ ### One-Shot Question
237
+
238
+ ```
239
+ Stan David
240
+ | |
241
+ |--- agent-comms (topic: memory) -->|
242
+ | | Notifies OpenClaw
243
+ | | Agent processes
244
+ |<-- reply (callback) ---------|
245
+ | |
246
+ ```
247
+
248
+ ### Polling Pattern
249
+
250
+ ```
251
+ Stan David
252
+ | |
253
+ |--- agent-comms ------------->|
254
+ | | Stores reply
255
+ |--- GET /reply/:nonce ------->|
256
+ |<-- 404 (not ready) ----------|
257
+ | |
258
+ |--- GET /reply/:nonce ------->|
259
+ |<-- 200 (reply data) ---------|
260
+ | |
261
+ ```
262
+
263
+ ### Multi-Turn Conversation
264
+
265
+ ```
266
+ Stan David
267
+ | |
268
+ |--- agent-comms (conv: c1) -->|
269
+ |<-- ack ----------------------|
270
+ | |
271
+ |--- agent-comms (conv: c1) -->|
272
+ |<-- reply (callback) ---------|
273
+ | |
274
+ |--- agent-comms (conv: c1) -->|
275
+ |<-- reply (callback) ---------|
276
+ | |
277
+ ```
@@ -0,0 +1,407 @@
1
+ # Federation Flow
2
+
3
+ Detailed walkthrough of OGP federation message flows.
4
+
5
+ ## Table of Contents
6
+
7
+ 1. [Discovery](#discovery)
8
+ 2. [Federation Request](#federation-request)
9
+ 3. [Federation Approval](#federation-approval)
10
+ 4. [Message Exchange](#message-exchange)
11
+ 5. [Security Model](#security-model)
12
+
13
+ ## Discovery
14
+
15
+ Before federating, peers discover each other via the `/.well-known/ogp` endpoint.
16
+
17
+ ### Request
18
+
19
+ ```http
20
+ GET /.well-known/ogp HTTP/1.1
21
+ Host: peer.example.com
22
+ ```
23
+
24
+ ### Response
25
+
26
+ ```json
27
+ {
28
+ "version": "0.1.0",
29
+ "displayName": "Alice",
30
+ "email": "alice@example.com",
31
+ "gatewayUrl": "https://peer.example.com",
32
+ "publicKey": "302a300506032b6570032100abc123...",
33
+ "endpoints": {
34
+ "request": "https://peer.example.com/federation/request",
35
+ "approve": "https://peer.example.com/federation/approve",
36
+ "reply": "https://peer.example.com/federation/reply/:nonce"
37
+ }
38
+ }
39
+ ```
40
+
41
+ This endpoint:
42
+ - Is unauthenticated (public discovery)
43
+ - Returns peer identity and public key
44
+ - Lists federation endpoints
45
+
46
+ ## Federation Request
47
+
48
+ Alice wants to federate with Bob. Alice sends a signed request.
49
+
50
+ ### Alice's Side
51
+
52
+ ```bash
53
+ ogp federation request https://bob.example.com peer-bob
54
+ ```
55
+
56
+ This:
57
+ 1. Loads Alice's keypair
58
+ 2. Builds peer info with Alice's public key
59
+ 3. Signs the peer info with Alice's private key
60
+ 4. POSTs to Bob's `/federation/request`
61
+
62
+ ### Request
63
+
64
+ ```http
65
+ POST /federation/request HTTP/1.1
66
+ Host: bob.example.com
67
+ Content-Type: application/json
68
+
69
+ {
70
+ "peer": {
71
+ "id": "peer-alice",
72
+ "displayName": "Alice",
73
+ "email": "alice@example.com",
74
+ "gatewayUrl": "https://alice.example.com",
75
+ "publicKey": "302a300506032b6570032100def456..."
76
+ },
77
+ "signature": "a1b2c3d4e5f6..."
78
+ }
79
+ ```
80
+
81
+ ### Bob's Side
82
+
83
+ Bob's OGP daemon:
84
+ 1. Receives request
85
+ 2. Stores peer as `pending`
86
+ 3. Returns acknowledgment
87
+
88
+ ```json
89
+ {
90
+ "received": true,
91
+ "status": "pending",
92
+ "message": "Federation request received and pending approval"
93
+ }
94
+ ```
95
+
96
+ Bob sees the request:
97
+
98
+ ```bash
99
+ $ ogp federation list --status pending
100
+
101
+ PENDING PEERS:
102
+
103
+ peer-alice
104
+ Name: Alice
105
+ Status: pending
106
+ Gateway: https://alice.example.com
107
+ Public key: 302a300506032b6570032100def456...
108
+ ```
109
+
110
+ ## Federation Approval
111
+
112
+ Bob approves Alice's request.
113
+
114
+ ### Bob's Side
115
+
116
+ ```bash
117
+ ogp federation approve peer-alice
118
+ ```
119
+
120
+ This:
121
+ 1. Updates peer status to `approved` in `~/.ogp/peers.json`
122
+ 2. POSTs approval to Alice's `/federation/approve`
123
+
124
+ ### Request
125
+
126
+ ```http
127
+ POST /federation/approve HTTP/1.1
128
+ Host: alice.example.com
129
+ Content-Type: application/json
130
+
131
+ {
132
+ "peerId": "peer-alice",
133
+ "approved": true
134
+ }
135
+ ```
136
+
137
+ ### Alice's Side
138
+
139
+ Alice's OGP daemon:
140
+ 1. Receives approval
141
+ 2. Updates Bob's status to `approved`
142
+
143
+ Now both sides have approved peers:
144
+
145
+ ```bash
146
+ $ ogp federation list --status approved
147
+
148
+ APPROVED PEERS:
149
+
150
+ peer-bob
151
+ Name: Bob
152
+ Status: approved
153
+ Gateway: https://bob.example.com
154
+ Public key: 302a300506032b6570032100abc123...
155
+ ```
156
+
157
+ ## Message Exchange
158
+
159
+ Alice sends a message to Bob.
160
+
161
+ ### Alice Sends
162
+
163
+ ```bash
164
+ ogp federation send peer-bob message '{"text":"Hello, Bob!"}'
165
+ ```
166
+
167
+ This:
168
+ 1. Builds message object with intent, nonce, timestamp, payload
169
+ 2. Signs message with Alice's private key
170
+ 3. POSTs to Bob's `/federation/message`
171
+
172
+ ### Request
173
+
174
+ ```http
175
+ POST /federation/message HTTP/1.1
176
+ Host: bob.example.com
177
+ Content-Type: application/json
178
+
179
+ {
180
+ "message": {
181
+ "intent": "message",
182
+ "from": "peer-alice",
183
+ "to": "peer-bob",
184
+ "nonce": "550e8400-e29b-41d4-a716-446655440000",
185
+ "timestamp": "2026-03-19T10:30:00.000Z",
186
+ "payload": {
187
+ "text": "Hello, Bob!"
188
+ }
189
+ },
190
+ "signature": "a1b2c3d4e5f6..."
191
+ }
192
+ ```
193
+
194
+ ### Bob Receives
195
+
196
+ Bob's OGP daemon:
197
+ 1. Verifies sender (`peer-alice`) is in approved peers
198
+ 2. Verifies signature using Alice's public key
199
+ 3. Checks intent exists in registry
200
+ 4. Forwards to Bob's OpenClaw via webhook
201
+
202
+ ### OpenClaw Notification
203
+
204
+ ```http
205
+ POST /api/system-event HTTP/1.1
206
+ Host: bob-openclaw.local:18789
207
+ Authorization: Bearer bob-token
208
+ Content-Type: application/json
209
+
210
+ {
211
+ "text": "[OGP] Message from Alice: Hello, Bob!",
212
+ "sessionKey": "agent:main:main",
213
+ "ogp": {
214
+ "from": "peer-alice",
215
+ "intent": "message",
216
+ "nonce": "550e8400-e29b-41d4-a716-446655440000",
217
+ "payload": {
218
+ "text": "Hello, Bob!"
219
+ }
220
+ }
221
+ }
222
+ ```
223
+
224
+ Bob's OpenClaw agent sees:
225
+
226
+ ```
227
+ [OGP] Message from Alice: Hello, Bob!
228
+ ```
229
+
230
+ ### Response
231
+
232
+ Bob's OGP daemon responds to Alice:
233
+
234
+ ```json
235
+ {
236
+ "received": true,
237
+ "timestamp": "2026-03-19T10:30:01.000Z"
238
+ }
239
+ ```
240
+
241
+ ## Security Model
242
+
243
+ ### Keypair Generation
244
+
245
+ Each OGP instance generates an Ed25519 keypair:
246
+
247
+ ```typescript
248
+ const { publicKey, privateKey } = crypto.generateKeyPairSync('ed25519');
249
+ ```
250
+
251
+ Stored in `~/.ogp/keypair.json`:
252
+
253
+ ```json
254
+ {
255
+ "publicKey": "302a300506032b6570032100...",
256
+ "privateKey": "302e020100300506032b657004220420..."
257
+ }
258
+ ```
259
+
260
+ ### Message Signing
261
+
262
+ When Alice sends a message:
263
+
264
+ 1. Build message object
265
+ 2. Serialize to JSON
266
+ 3. Sign with Ed25519 private key
267
+
268
+ ```typescript
269
+ const message = {
270
+ intent: "message",
271
+ from: "peer-alice",
272
+ to: "peer-bob",
273
+ nonce: crypto.randomUUID(),
274
+ timestamp: new Date().toISOString(),
275
+ payload: { text: "Hello!" }
276
+ };
277
+
278
+ const signature = crypto.sign(
279
+ null,
280
+ Buffer.from(JSON.stringify(message)),
281
+ privateKey
282
+ );
283
+ ```
284
+
285
+ ### Signature Verification
286
+
287
+ When Bob receives a message:
288
+
289
+ 1. Look up Alice's public key from `peers.json`
290
+ 2. Verify signature
291
+
292
+ ```typescript
293
+ const isValid = crypto.verify(
294
+ null,
295
+ Buffer.from(JSON.stringify(message)),
296
+ alicePublicKey,
297
+ signature
298
+ );
299
+ ```
300
+
301
+ If signature is invalid:
302
+ - Message is rejected
303
+ - Error returned to sender
304
+ - No notification sent to OpenClaw
305
+
306
+ ### Threat Model
307
+
308
+ **OGP protects against:**
309
+
310
+ - ✓ Impersonation (signature verification)
311
+ - ✓ Message tampering (signature covers full message)
312
+ - ✓ Unauthorized peers (approval required)
313
+ - ✓ Man-in-the-middle (HTTPS tunnels)
314
+
315
+ **OGP does NOT protect against:**
316
+
317
+ - ✗ Compromised peer credentials (keep `keypair.json` secure)
318
+ - ✗ DDoS attacks (add rate limiting if needed)
319
+ - ✗ Replay attacks (nonce tracking not yet implemented)
320
+
321
+ ### Best Practices
322
+
323
+ 1. **Keep private keys secure**
324
+ - Don't commit `~/.ogp/keypair.json` to git
325
+ - Use file permissions: `chmod 600 ~/.ogp/keypair.json`
326
+
327
+ 2. **Verify peer identity**
328
+ - Before approving, confirm peer identity out-of-band
329
+ - Check `/.well-known/ogp` matches expected public key
330
+
331
+ 3. **Use HTTPS tunnels**
332
+ - Always use cloudflared or ngrok (both provide HTTPS)
333
+ - Never expose raw HTTP to the internet
334
+
335
+ 4. **Monitor peer activity**
336
+ - Check OpenClaw logs for suspicious messages
337
+ - Reject peers that send malicious content
338
+
339
+ ## Message Flow Diagrams
340
+
341
+ ### Full Federation Flow
342
+
343
+ ```
344
+ Alice Bob
345
+ | |
346
+ |--- GET /.well-known/ogp -->
347
+ |<-- Discovery response ---|
348
+ | |
349
+ |-- POST /federation/request -->
350
+ |<-- Status: pending -------|
351
+ | |
352
+ | [Bob approves]
353
+ | |
354
+ |<-- POST /federation/approve --
355
+ |--- Acknowledgment --->|
356
+ | |
357
+ |-- POST /federation/message -->
358
+ |<-- Response ----------|
359
+ | |
360
+ | [Bob's OpenClaw]
361
+ | |<-- Webhook
362
+ | |
363
+ ```
364
+
365
+ ### Message Verification Flow
366
+
367
+ ```
368
+ ┌─────────────────────────────────────┐
369
+ │ Incoming message + signature │
370
+ └──────────────┬──────────────────────┘
371
+
372
+
373
+ ┌─────────────────────────────────────┐
374
+ │ 1. Check: Is sender approved? │
375
+ └──────────────┬──────────────────────┘
376
+ │ Yes
377
+
378
+ ┌─────────────────────────────────────┐
379
+ │ 2. Load sender's public key │
380
+ └──────────────┬──────────────────────┘
381
+
382
+
383
+ ┌─────────────────────────────────────┐
384
+ │ 3. Verify signature │
385
+ └──────────────┬──────────────────────┘
386
+ │ Valid
387
+
388
+ ┌─────────────────────────────────────┐
389
+ │ 4. Check intent exists │
390
+ └──────────────┬──────────────────────┘
391
+ │ Yes
392
+
393
+ ┌─────────────────────────────────────┐
394
+ │ 5. Notify OpenClaw │
395
+ └──────────────┬──────────────────────┘
396
+
397
+
398
+ ┌─────────────────────────────────────┐
399
+ │ 6. Return success │
400
+ └─────────────────────────────────────┘
401
+ ```
402
+
403
+ ## Next Steps
404
+
405
+ - See [quickstart.md](./quickstart.md) for hands-on tutorial
406
+ - Check [README.md](../README.md) for CLI reference
407
+ - Explore custom intents in `~/.ogp/intents.json`