@dp-pcs/ogp 0.2.30 → 0.3.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 +11 -0
- package/dist/cli/federation.d.ts.map +1 -1
- package/dist/cli/federation.js +3 -1
- package/dist/cli/federation.js.map +1 -1
- package/dist/daemon/notify.d.ts +20 -0
- package/dist/daemon/notify.d.ts.map +1 -1
- package/dist/daemon/notify.js +165 -48
- package/dist/daemon/notify.js.map +1 -1
- package/dist/shared/config.d.ts +3 -0
- package/dist/shared/config.d.ts.map +1 -1
- package/dist/shared/config.js.map +1 -1
- package/docs/TESTING-HERMES-BACKEND.md +278 -0
- package/docs/extending-to-hermes.md +462 -0
- package/docs/hermes-implementation-checklist.md +448 -0
- package/docs/hermes-local-testing.md +478 -0
- package/docs/hermes-tunnel-setup.md +214 -0
- package/docs/platform-agnostic-architecture.md +472 -0
- package/package.json +3 -2
- package/scripts/install-skills.js +142 -20
- package/skills/ogp-project/SKILL.md +321 -226
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
# Testing OGP with Hermes Locally
|
|
2
|
+
|
|
3
|
+
> Quick guide for federating OpenClaw and Hermes on the same machine
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This guide walks through setting up federation between OpenClaw and Hermes running on the same Mac. While the typical use case is remote federation, local testing proves the platform-agnostic architecture works.
|
|
8
|
+
|
|
9
|
+
## Prerequisites
|
|
10
|
+
|
|
11
|
+
- ✅ OpenClaw installed and running
|
|
12
|
+
- ✅ Hermes installed and running
|
|
13
|
+
- ✅ OGP installed (`npm install -g @dp-pcs/ogp`)
|
|
14
|
+
- ✅ Both have separate identities (different API tokens, configs)
|
|
15
|
+
|
|
16
|
+
## Architecture
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
┌─────────────────────────────────────────────────────────┐
|
|
20
|
+
│ Your Mac │
|
|
21
|
+
│ │
|
|
22
|
+
│ ┌──────────────────┐ Federation ┌──────────────────┐│
|
|
23
|
+
│ │ OGP Instance 1 │◄────────────►│ OGP Instance 2 ││
|
|
24
|
+
│ │ (OpenClaw) │ Signed │ (Hermes) ││
|
|
25
|
+
│ │ │ Messages │ ││
|
|
26
|
+
│ │ :18790 │ │ :18791 ││
|
|
27
|
+
│ │ ~/.ogp │ │ ~/.ogp-hermes ││
|
|
28
|
+
│ └────────┬─────────┘ └────────┬─────────┘│
|
|
29
|
+
│ │ │ │
|
|
30
|
+
│ ▼ ▼ │
|
|
31
|
+
│ ┌──────────────────┐ ┌──────────────────┐│
|
|
32
|
+
│ │ OpenClaw │ │ Hermes Gateway ││
|
|
33
|
+
│ │ :18789 │ │ Webhook :8644 ││
|
|
34
|
+
│ └──────────────────┘ └──────────────────┘│
|
|
35
|
+
└─────────────────────────────────────────────────────────┘
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Setup Steps
|
|
39
|
+
|
|
40
|
+
### 1. Configure Hermes Webhook
|
|
41
|
+
|
|
42
|
+
First, configure Hermes to accept OGP federation messages via its webhook platform:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Edit Hermes config
|
|
46
|
+
code ~/.hermes/config.yaml
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Add this under `platforms`:
|
|
50
|
+
|
|
51
|
+
```yaml
|
|
52
|
+
platforms:
|
|
53
|
+
# ... other platforms ...
|
|
54
|
+
|
|
55
|
+
webhook:
|
|
56
|
+
enabled: true
|
|
57
|
+
port: 8644
|
|
58
|
+
host: "127.0.0.1"
|
|
59
|
+
routes:
|
|
60
|
+
ogp_federation:
|
|
61
|
+
secret: "test-secret-ogp-hermes" # MUST match OGP config
|
|
62
|
+
events: ["*"]
|
|
63
|
+
prompt: |
|
|
64
|
+
📡 **OGP Federation Message**
|
|
65
|
+
|
|
66
|
+
**From:** {{peer_display_name}} ({{peer_id}})
|
|
67
|
+
**Intent:** {{intent}}
|
|
68
|
+
{{#if topic}}**Topic:** {{topic}}{{/if}}
|
|
69
|
+
{{#if priority}}**Priority:** {{priority}}{{/if}}
|
|
70
|
+
{{#if conversation_id}}**Thread:** {{conversation_id}}{{/if}}
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
{{message}}
|
|
75
|
+
|
|
76
|
+
{{#if payload}}
|
|
77
|
+
**Additional Data:**
|
|
78
|
+
```json
|
|
79
|
+
{{payload}}
|
|
80
|
+
```
|
|
81
|
+
{{/if}}
|
|
82
|
+
deliver: "telegram" # Change to your preferred channel
|
|
83
|
+
deliver_extra:
|
|
84
|
+
chat_id: "YOUR_TELEGRAM_CHAT_ID" # Or omit for default
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Important:** The `secret` field is critical. This will be used to verify webhook signatures from OGP.
|
|
88
|
+
|
|
89
|
+
### 2. Restart Hermes Gateway
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
hermes gateway restart
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Verify the webhook is listening:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
curl http://localhost:8644/health
|
|
99
|
+
# Should return: {"status":"ok"}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 3. Verify OpenClaw OGP Instance (Existing)
|
|
103
|
+
|
|
104
|
+
Your existing OGP instance should already be configured:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# Check status
|
|
108
|
+
ogp status
|
|
109
|
+
|
|
110
|
+
# Should show:
|
|
111
|
+
# ✓ Daemon running on port 18790
|
|
112
|
+
# ✓ Connected to OpenClaw at http://localhost:18789
|
|
113
|
+
# ✓ Gateway: <your-url>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
If not set up:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
ogp setup
|
|
120
|
+
# Follow prompts, select OpenClaw agent
|
|
121
|
+
ogp start
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 4. Create OGP Instance for Hermes
|
|
125
|
+
|
|
126
|
+
Now create a second OGP instance dedicated to Hermes:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
# Create state directory
|
|
130
|
+
mkdir -p ~/.ogp-hermes
|
|
131
|
+
|
|
132
|
+
# Create configuration
|
|
133
|
+
cat > ~/.ogp-hermes/config.json <<'EOF'
|
|
134
|
+
{
|
|
135
|
+
"daemonPort": 18791,
|
|
136
|
+
"platform": "hermes",
|
|
137
|
+
"gatewayUrl": "http://localhost:18791",
|
|
138
|
+
"displayName": "David (Hermes)",
|
|
139
|
+
"email": "your-email@example.com",
|
|
140
|
+
"stateDir": "~/.ogp-hermes",
|
|
141
|
+
|
|
142
|
+
"hermesWebhookUrl": "http://localhost:8644/webhooks/ogp_federation",
|
|
143
|
+
"hermesWebhookSecret": "test-secret-ogp-hermes",
|
|
144
|
+
|
|
145
|
+
"rendezvous": {
|
|
146
|
+
"enabled": false
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
EOF
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Note:** We're using `http://localhost:18791` as the gateway URL since both are on the same machine. For remote federation, you'd use your public tunnel URL.
|
|
153
|
+
|
|
154
|
+
### 5. Modify OGP to Support Hermes Backend
|
|
155
|
+
|
|
156
|
+
**TEMPORARY:** Until the notification backend refactor is merged, manually patch `src/daemon/notify.ts`:
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
// Add near the top of the file
|
|
160
|
+
async function notifyHermes(
|
|
161
|
+
peerId: string,
|
|
162
|
+
peerDisplayName: string,
|
|
163
|
+
intent: string,
|
|
164
|
+
payload: any
|
|
165
|
+
): Promise<void> {
|
|
166
|
+
const config = loadConfig();
|
|
167
|
+
const webhookUrl = config.hermesWebhookUrl || 'http://localhost:8644/webhooks/ogp_federation';
|
|
168
|
+
const secret = config.hermesWebhookSecret;
|
|
169
|
+
|
|
170
|
+
if (!secret) {
|
|
171
|
+
throw new Error('Hermes webhook secret not configured');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const body = {
|
|
175
|
+
peer_id: peerId,
|
|
176
|
+
peer_display_name: peerDisplayName,
|
|
177
|
+
intent: intent,
|
|
178
|
+
topic: payload.topic || "",
|
|
179
|
+
message: payload.message || JSON.stringify(payload),
|
|
180
|
+
priority: payload.priority || "normal",
|
|
181
|
+
conversation_id: payload.conversationId,
|
|
182
|
+
timestamp: new Date().toISOString(),
|
|
183
|
+
payload: payload
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const bodyStr = JSON.stringify(body);
|
|
187
|
+
const signature = crypto
|
|
188
|
+
.createHmac('sha256', secret)
|
|
189
|
+
.update(bodyStr)
|
|
190
|
+
.digest('hex');
|
|
191
|
+
|
|
192
|
+
await fetch(webhookUrl, {
|
|
193
|
+
method: 'POST',
|
|
194
|
+
headers: {
|
|
195
|
+
'Content-Type': 'application/json',
|
|
196
|
+
'X-Hub-Signature-256': `sha256=${signature}`
|
|
197
|
+
},
|
|
198
|
+
body: bodyStr
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Modify the main notification function
|
|
203
|
+
export async function notifyLocalAgent(...) {
|
|
204
|
+
const config = loadConfig();
|
|
205
|
+
const platform = config.platform || 'openclaw';
|
|
206
|
+
|
|
207
|
+
if (platform === 'hermes') {
|
|
208
|
+
await notifyHermes(peerId, peerDisplayName, intent, payload);
|
|
209
|
+
} else {
|
|
210
|
+
await notifyOpenClaw(peerId, intent, payload); // existing code
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Then rebuild:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
cd ~/Documents/GitHub/ogp
|
|
219
|
+
npm run build
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### 6. Start Hermes OGP Instance
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
# Set state directory via env var
|
|
226
|
+
export OGP_STATE_DIR=~/.ogp-hermes
|
|
227
|
+
|
|
228
|
+
# Start the daemon (will use config from ~/.ogp-hermes/config.json)
|
|
229
|
+
node ~/Documents/GitHub/ogp/dist/daemon/server.js &
|
|
230
|
+
|
|
231
|
+
# Or if using the CLI wrapper:
|
|
232
|
+
# ogp start --config ~/.ogp-hermes/config.json --port 18791
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Verify it's running:
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
curl http://localhost:18791/.well-known/ogp
|
|
239
|
+
# Should return OGP metadata with public key
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### 7. Establish Federation
|
|
243
|
+
|
|
244
|
+
Now federate the two local instances:
|
|
245
|
+
|
|
246
|
+
**From OpenClaw OGP → Hermes OGP:**
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
# Request federation from OpenClaw's OGP to Hermes's OGP
|
|
250
|
+
ogp federation request http://localhost:18791 --alias hermes-local
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
You should see:
|
|
254
|
+
```
|
|
255
|
+
✓ Federation request sent to http://localhost:18791
|
|
256
|
+
✓ Peer alias: hermes-local (auto-resolved from display name)
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
**From Hermes OGP → Approve:**
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
# List pending requests
|
|
263
|
+
OGP_STATE_DIR=~/.ogp-hermes ogp federation list --status pending
|
|
264
|
+
|
|
265
|
+
# Should show the request from OpenClaw's OGP
|
|
266
|
+
# Note the peer ID (first 16 chars of public key)
|
|
267
|
+
|
|
268
|
+
# Approve it
|
|
269
|
+
OGP_STATE_DIR=~/.ogp-hermes ogp federation approve <peer-id> \
|
|
270
|
+
--intents message,agent-comms \
|
|
271
|
+
--topics general,testing
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
**Reverse Direction (Optional):**
|
|
275
|
+
|
|
276
|
+
If you want bidirectional federation:
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
# From Hermes OGP, request to OpenClaw OGP
|
|
280
|
+
OGP_STATE_DIR=~/.ogp-hermes ogp federation request http://localhost:18790 --alias openclaw-local
|
|
281
|
+
|
|
282
|
+
# From OpenClaw OGP, approve
|
|
283
|
+
ogp federation approve <hermes-peer-id>
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### 8. Test Message Flow
|
|
287
|
+
|
|
288
|
+
**Send from OpenClaw to Hermes:**
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
# Simple message
|
|
292
|
+
ogp federation send hermes-local message '{"text":"Hello from OpenClaw!"}'
|
|
293
|
+
|
|
294
|
+
# Agent-comms with topic
|
|
295
|
+
ogp federation agent hermes-local testing "This is a test message from OpenClaw" --priority high
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
**What should happen:**
|
|
299
|
+
1. Message leaves OpenClaw's OGP (port 18790)
|
|
300
|
+
2. Travels to Hermes's OGP (port 18791)
|
|
301
|
+
3. Doorman validates signature and scope
|
|
302
|
+
4. OGP posts to Hermes webhook (port 8644)
|
|
303
|
+
5. Hermes webhook adapter formats the message
|
|
304
|
+
6. Hermes processes and sends to your configured delivery (Telegram, etc.)
|
|
305
|
+
|
|
306
|
+
**Check Hermes logs:**
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
tail -f ~/.hermes/logs/gateway.log
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
You should see:
|
|
313
|
+
```
|
|
314
|
+
[webhook] Received POST on route ogp_federation
|
|
315
|
+
[webhook] Signature verified
|
|
316
|
+
[webhook] Triggering agent run for session webhook:ogp_federation:...
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### 9. Test Reverse Direction (Optional)
|
|
320
|
+
|
|
321
|
+
If you set up bidirectional federation:
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
OGP_STATE_DIR=~/.ogp-hermes ogp federation send openclaw-local message '{"text":"Hello from Hermes!"}'
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
The message should appear in OpenClaw.
|
|
328
|
+
|
|
329
|
+
## Troubleshooting
|
|
330
|
+
|
|
331
|
+
### Port Already in Use
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
# Check what's using port 18791
|
|
335
|
+
lsof -i :18791
|
|
336
|
+
|
|
337
|
+
# Kill if needed
|
|
338
|
+
kill <PID>
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Webhook Not Receiving Messages
|
|
342
|
+
|
|
343
|
+
1. **Check Hermes webhook is running:**
|
|
344
|
+
```bash
|
|
345
|
+
curl http://localhost:8644/health
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
2. **Verify webhook secret matches:**
|
|
349
|
+
```bash
|
|
350
|
+
# In ~/.ogp-hermes/config.json
|
|
351
|
+
cat ~/.ogp-hermes/config.json | grep hermesWebhookSecret
|
|
352
|
+
|
|
353
|
+
# In ~/.hermes/config.yaml
|
|
354
|
+
grep -A5 ogp_federation ~/.hermes/config.yaml | grep secret
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
3. **Check Hermes gateway logs:**
|
|
358
|
+
```bash
|
|
359
|
+
tail -f ~/.hermes/logs/gateway.log
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### Signature Verification Failed
|
|
363
|
+
|
|
364
|
+
This means the webhook secret doesn't match. Double-check:
|
|
365
|
+
- `hermesWebhookSecret` in `~/.ogp-hermes/config.json`
|
|
366
|
+
- `secret` under `routes.ogp_federation` in `~/.hermes/config.yaml`
|
|
367
|
+
|
|
368
|
+
They must be identical.
|
|
369
|
+
|
|
370
|
+
### OGP Daemon Won't Start
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
# Check if port 18791 is already in use
|
|
374
|
+
lsof -i :18791
|
|
375
|
+
|
|
376
|
+
# Check logs
|
|
377
|
+
tail -f ~/.ogp-hermes/daemon.log
|
|
378
|
+
|
|
379
|
+
# Verify config is valid JSON
|
|
380
|
+
jq . ~/.ogp-hermes/config.json
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Federation Request Fails
|
|
384
|
+
|
|
385
|
+
```bash
|
|
386
|
+
# Verify Hermes OGP is reachable
|
|
387
|
+
curl http://localhost:18791/.well-known/ogp
|
|
388
|
+
|
|
389
|
+
# Check OpenClaw OGP peers list
|
|
390
|
+
ogp federation list
|
|
391
|
+
|
|
392
|
+
# Check Hermes OGP peers list
|
|
393
|
+
OGP_STATE_DIR=~/.ogp-hermes ogp federation list
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
## Verification Checklist
|
|
397
|
+
|
|
398
|
+
- [ ] Hermes gateway running with webhook enabled (port 8644)
|
|
399
|
+
- [ ] OpenClaw OGP running (port 18790)
|
|
400
|
+
- [ ] Hermes OGP running (port 18791)
|
|
401
|
+
- [ ] Both OGP instances have unique keypairs
|
|
402
|
+
- [ ] Federation established (peer approved on both sides)
|
|
403
|
+
- [ ] Test message sent successfully
|
|
404
|
+
- [ ] Message appears in Hermes delivery channel
|
|
405
|
+
- [ ] Webhook signature verified (check logs)
|
|
406
|
+
|
|
407
|
+
## Next Steps
|
|
408
|
+
|
|
409
|
+
Once local federation works:
|
|
410
|
+
|
|
411
|
+
1. **Test Remote Federation:**
|
|
412
|
+
- Deploy Hermes to a VPS or cloud instance
|
|
413
|
+
- Set up HTTPS tunnel for Hermes OGP
|
|
414
|
+
- Federate with a truly remote OpenClaw instance
|
|
415
|
+
|
|
416
|
+
2. **Test Scope Policies:**
|
|
417
|
+
```bash
|
|
418
|
+
# Restrict Hermes peer to specific topics
|
|
419
|
+
ogp federation grant hermes-local \
|
|
420
|
+
--topics project-alpha,memory-sync \
|
|
421
|
+
--rate 50/3600
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
3. **Test Agent-Comms Response Policies:**
|
|
425
|
+
```bash
|
|
426
|
+
# Configure how OpenClaw responds to Hermes
|
|
427
|
+
ogp agent-comms configure hermes-local \
|
|
428
|
+
--topics testing \
|
|
429
|
+
--level full \
|
|
430
|
+
--notes "Local Hermes instance"
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
4. **Test Project Collaboration:**
|
|
434
|
+
```bash
|
|
435
|
+
# Create a project on OpenClaw
|
|
436
|
+
ogp project create test-project "Test Federation"
|
|
437
|
+
|
|
438
|
+
# Send contribution to Hermes
|
|
439
|
+
ogp project send-contribution hermes-local test-project progress \
|
|
440
|
+
"Testing cross-platform federation"
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
## Cleanup
|
|
444
|
+
|
|
445
|
+
To stop the test setup:
|
|
446
|
+
|
|
447
|
+
```bash
|
|
448
|
+
# Stop Hermes OGP
|
|
449
|
+
kill $(cat ~/.ogp-hermes/daemon.pid)
|
|
450
|
+
|
|
451
|
+
# Or if using CLI wrapper:
|
|
452
|
+
# OGP_STATE_DIR=~/.ogp-hermes ogp stop
|
|
453
|
+
|
|
454
|
+
# Stop OpenClaw OGP
|
|
455
|
+
ogp stop
|
|
456
|
+
|
|
457
|
+
# Stop Hermes gateway
|
|
458
|
+
hermes gateway stop
|
|
459
|
+
|
|
460
|
+
# Remove test state (optional)
|
|
461
|
+
# rm -rf ~/.ogp-hermes
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
## Summary
|
|
465
|
+
|
|
466
|
+
This setup proves that:
|
|
467
|
+
- ✅ OGP works with multiple platforms (OpenClaw + Hermes)
|
|
468
|
+
- ✅ Multiple OGP instances can run on the same machine
|
|
469
|
+
- ✅ Federation is platform-agnostic (only notification backend differs)
|
|
470
|
+
- ✅ Cryptographic verification works identically for local and remote peers
|
|
471
|
+
- ✅ The "router" analogy holds: protocol is the same, backend adapts
|
|
472
|
+
|
|
473
|
+
**The key insight:** Each AI assistant gets its own OGP gateway instance. The core protocol never changes; only the notification mechanism adapts to the local platform.
|
|
474
|
+
|
|
475
|
+
---
|
|
476
|
+
|
|
477
|
+
**Last Updated:** 2026-04-04
|
|
478
|
+
**Tested With:** OGP v0.2.31, Hermes v0.7.0, OpenClaw v1.x
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Hermes OGP Remote Federation Setup
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
Enable remote OpenClaw instance (clawporate) to federate with local Hermes instance.
|
|
5
|
+
|
|
6
|
+
## Prerequisites
|
|
7
|
+
- Hermes OGP daemon running on port 18793
|
|
8
|
+
- Existing Cloudflare tunnel (currently routing to OpenClaw OGP on 18790)
|
|
9
|
+
- Domain name (e.g., sarcastek.com)
|
|
10
|
+
|
|
11
|
+
## Step 1: Add Tunnel Route for Hermes OGP
|
|
12
|
+
|
|
13
|
+
### Find Your Tunnel Config
|
|
14
|
+
```bash
|
|
15
|
+
ls ~/.cloudflared/*.yml
|
|
16
|
+
cat ~/.cloudflared/config.yml # or your tunnel config file
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Add Hermes Route
|
|
20
|
+
Edit your tunnel config to add a new hostname for Hermes:
|
|
21
|
+
|
|
22
|
+
```yaml
|
|
23
|
+
tunnel: <your-tunnel-id>
|
|
24
|
+
credentials-file: ~/.cloudflared/<tunnel-id>.json
|
|
25
|
+
|
|
26
|
+
ingress:
|
|
27
|
+
# Existing OpenClaw OGP route
|
|
28
|
+
- hostname: ogp.sarcastek.com
|
|
29
|
+
service: http://localhost:18790
|
|
30
|
+
|
|
31
|
+
# NEW: Hermes OGP route
|
|
32
|
+
- hostname: hermes-ogp.sarcastek.com
|
|
33
|
+
service: http://localhost:18793
|
|
34
|
+
|
|
35
|
+
# Existing routes...
|
|
36
|
+
- hostname: openclaw.sarcastek.com
|
|
37
|
+
service: http://localhost:18789
|
|
38
|
+
|
|
39
|
+
# Catch-all (must be last)
|
|
40
|
+
- service: http_status:404
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Add DNS Record
|
|
44
|
+
In Cloudflare dashboard:
|
|
45
|
+
1. Go to DNS settings
|
|
46
|
+
2. Add CNAME record:
|
|
47
|
+
- Name: `hermes-ogp`
|
|
48
|
+
- Target: `<your-tunnel-id>.cfargotunnel.com`
|
|
49
|
+
- Proxy: Yes (orange cloud)
|
|
50
|
+
|
|
51
|
+
### Restart Tunnel
|
|
52
|
+
```bash
|
|
53
|
+
# If using service
|
|
54
|
+
sudo systemctl restart cloudflared
|
|
55
|
+
|
|
56
|
+
# Or if running manually
|
|
57
|
+
cloudflared tunnel run <tunnel-name>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Verify
|
|
61
|
+
```bash
|
|
62
|
+
curl https://hermes-ogp.sarcastek.com/.well-known/ogp | jq .
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Should return Hermes OGP discovery card.
|
|
66
|
+
|
|
67
|
+
## Step 2: Update Hermes Config
|
|
68
|
+
|
|
69
|
+
Update `~/.ogp-hermes/config.json` to use the public URL:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"daemonPort": 18793,
|
|
74
|
+
"platform": "hermes",
|
|
75
|
+
"gatewayUrl": "https://hermes-ogp.sarcastek.com", // Changed from localhost
|
|
76
|
+
"displayName": "David (Hermes)",
|
|
77
|
+
"email": "david@example.com",
|
|
78
|
+
"stateDir": "/Users/davidproctor/.ogp-hermes",
|
|
79
|
+
"hermesWebhookUrl": "http://localhost:8644/webhooks/ogp_federation",
|
|
80
|
+
"hermesWebhookSecret": "ogp-test-secret-hermes-2026",
|
|
81
|
+
"rendezvous": {
|
|
82
|
+
"enabled": false
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Restart Hermes Daemon
|
|
88
|
+
```bash
|
|
89
|
+
# Kill existing daemon
|
|
90
|
+
pkill -f "test-daemon-start"
|
|
91
|
+
|
|
92
|
+
# Start with new config
|
|
93
|
+
OGP_HOME=~/.ogp-hermes node dist/cli/federation.js daemon start
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Step 3: Federation Request from Clawporate
|
|
97
|
+
|
|
98
|
+
On the **remote clawporate** machine:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Request federation with local Hermes
|
|
102
|
+
ogp federation request https://hermes-ogp.sarcastek.com clawporate-hermes --alias hermes-local
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Step 4: Approve on Local Hermes
|
|
106
|
+
|
|
107
|
+
On your **local machine**:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# List pending requests
|
|
111
|
+
OGP_HOME=~/.ogp-hermes ogp federation list --status pending
|
|
112
|
+
|
|
113
|
+
# Approve clawporate
|
|
114
|
+
OGP_HOME=~/.ogp-hermes ogp federation approve <peer-id-or-alias>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Step 5: Send Test Message
|
|
118
|
+
|
|
119
|
+
From **clawporate**:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
ogp federation send hermes-local "Hello Hermes from clawporate! Testing OGP cross-platform federation."
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Should appear in Hermes (via webhook → Telegram/logs).
|
|
126
|
+
|
|
127
|
+
## Architecture Diagram
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
┌─────────────────────────┐
|
|
131
|
+
│ Clawporate (Remote) │
|
|
132
|
+
│ OpenClaw Gateway │
|
|
133
|
+
└───────────┬─────────────┘
|
|
134
|
+
│
|
|
135
|
+
│ OGP Federation
|
|
136
|
+
│ (HTTPS + Ed25519 signatures)
|
|
137
|
+
│
|
|
138
|
+
▼
|
|
139
|
+
┌─────────────────────────┐
|
|
140
|
+
│ Cloudflare Tunnel │
|
|
141
|
+
│ hermes-ogp.sarcastek.com│
|
|
142
|
+
└───────────┬─────────────┘
|
|
143
|
+
│
|
|
144
|
+
│ Reverse Proxy
|
|
145
|
+
│
|
|
146
|
+
▼
|
|
147
|
+
┌─────────────────────────┐
|
|
148
|
+
│ Local Machine │
|
|
149
|
+
│ │
|
|
150
|
+
│ ┌──────────────────┐ │
|
|
151
|
+
│ │ Hermes OGP │ │
|
|
152
|
+
│ │ Port 18793 │ │
|
|
153
|
+
│ └────────┬─────────┘ │
|
|
154
|
+
│ │ │
|
|
155
|
+
│ │ Webhook POST │
|
|
156
|
+
│ ▼ │
|
|
157
|
+
│ ┌──────────────────┐ │
|
|
158
|
+
│ │ Hermes Webhook │ │
|
|
159
|
+
│ │ Port 8644 │ │
|
|
160
|
+
│ └────────┬─────────┘ │
|
|
161
|
+
│ │ │
|
|
162
|
+
│ │ Deliver │
|
|
163
|
+
│ ▼ │
|
|
164
|
+
│ Telegram / Logs │
|
|
165
|
+
└─────────────────────────┘
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Port Summary
|
|
169
|
+
|
|
170
|
+
| Service | Port | Access |
|
|
171
|
+
|---------|------|--------|
|
|
172
|
+
| OpenClaw Gateway | 18789 | openclaw.sarcastek.com |
|
|
173
|
+
| OpenClaw OGP | 18790 | ogp.sarcastek.com |
|
|
174
|
+
| Hermes OGP | 18793 | hermes-ogp.sarcastek.com |
|
|
175
|
+
| Hermes Webhook | 8644 | localhost only |
|
|
176
|
+
| Hermes Gateway | varies | localhost only |
|
|
177
|
+
|
|
178
|
+
## Troubleshooting
|
|
179
|
+
|
|
180
|
+
### Test Discovery Endpoint
|
|
181
|
+
```bash
|
|
182
|
+
curl https://hermes-ogp.sarcastek.com/.well-known/ogp
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Check Federation Status
|
|
186
|
+
```bash
|
|
187
|
+
OGP_HOME=~/.ogp-hermes ogp federation list
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Test Notification Delivery
|
|
191
|
+
```bash
|
|
192
|
+
OGP_HOME=~/.ogp-hermes node test-hermes-notify.mjs
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Check Webhook Delivery
|
|
196
|
+
```bash
|
|
197
|
+
hermes webhook list
|
|
198
|
+
hermes status | grep Telegram
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Security Notes
|
|
202
|
+
|
|
203
|
+
- OGP messages are cryptographically signed (Ed25519)
|
|
204
|
+
- Webhook uses HMAC-SHA256 signature verification
|
|
205
|
+
- Tunnel provides HTTPS termination
|
|
206
|
+
- Private keys stored in macOS Keychain (Hermes) or filesystem with restricted permissions (OpenClaw)
|
|
207
|
+
|
|
208
|
+
## Next Steps
|
|
209
|
+
|
|
210
|
+
After successful federation:
|
|
211
|
+
1. Test bidirectional messaging
|
|
212
|
+
2. Test different intents (agent-comms, project.*, etc.)
|
|
213
|
+
3. Set up monitoring/logging
|
|
214
|
+
4. Document federation workflow for team
|