overmind-mcp 3.5.2 → 3.6.1

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.
@@ -0,0 +1,665 @@
1
+ # 🌉 Overmind Bridge — Agents Persistants & A2A (Guide Unifié)
2
+
3
+ > **Version**: Overmind v3.5.2 — Pattern générique, 2 à 100 agents
4
+ > **Date**: 2026-07-10
5
+ > **Statut**: Remplace `overmind-bridge-persistent-agents.md`, `overmind-bridge-commands-reference.md`, `doc_guide_agent_hermes_permanent.md`, `guide_agent_hermes_overmind.md`, `agent-http-tutorial.md`
6
+
7
+ ---
8
+
9
+ ## 1. Concepts
10
+
11
+ ### Qu'est-ce qu'un agent persistant ?
12
+
13
+ Un agent persistant = **un process `overmind-bridge` autonome** qui :
14
+ - Écoute sur son propre port HTTP
15
+ - A son propre agent Hermes dédié (profil)
16
+ - Garde sa session entre les appels (mémoire conversationnelle)
17
+ - Communique avec les autres agents via HTTP A2A (peer-to-peer)
18
+ - Forward les appels LLM vers le MCP Overmind → Hermes Gateway
19
+
20
+ ### Pourquoi des bridges isolés ?
21
+
22
+ | Sans bridge | Avec bridge isolé |
23
+ |-------------|-------------------|
24
+ | `spawn('hermes', ['-p', agent])` à chaque call | Process persistant, session conservée |
25
+ | 5-10s startup Python par call | <500ms (HTTP direct au Gateway) |
26
+ | Pas de communication inter-agent | A2A HTTP peer-to-peer |
27
+ | Crash d'un agent = crash global | Crash d'un agent ≠ impact sur les autres |
28
+ | Pas de monitoring par agent | `GET /health` par agent |
29
+
30
+ ### L'échelle : 2 à 100 agents
31
+
32
+ Le pattern est **identique** que tu aies 2 ou 100 agents. Chaque agent = :
33
+ - 1 profil Hermes (`~/.hermes/profiles/<name>/`)
34
+ - 1 process bridge (`node dist/bridges/<name>/src/bridge.js`)
35
+ - 1 port dédié (séquence : 3101, 3102, ..., 31XX)
36
+
37
+ ---
38
+
39
+ ## 2. Architecture
40
+
41
+ ```
42
+ ┌──────────────────────────────────────────────────────────────┐
43
+ │ N BRIDGES ISOLÉS — PEER-TO-PEER │
44
+ │ │
45
+ │ :3101 agent_alpha → RPC locaux + A2A vers peers │
46
+ │ :3102 agent_beta → RPC locaux + A2A vers peers │
47
+ │ :3103 agent_gamma → RPC locaux + A2A vers peers │
48
+ │ ... │
49
+ │ :31XX agent_omega → RPC locaux + A2A vers peers │
50
+ │ │
51
+ │ A2A = HTTP POST inter-bridges (JSON-RPC 2.0) │
52
+ │ Chaque bridge a ses propres clients vers les autres │
53
+ │ │
54
+ │ SERVICES PARTAGÉS (single instance): │
55
+ │ :3099 Overmind MCP Server (routing run_agent, memory, ...) │
56
+ │ :8642 Hermes Gateway API (X-Hermes-Profile routing) │
57
+ │ :5432 PostgreSQL (MessageLog + pgvector Memory) │
58
+ └──────────────────────────────────────────────────────────────┘
59
+ ```
60
+
61
+ ### Ce que ce n'est PAS
62
+
63
+ - ❌ Un seul `OverBridgeServer` partagé qui dispatche vers N agents
64
+ - ❌ Un bridge "central" qui connaît tous les agents
65
+ - ❌ N instances Hermes Gateway (1 seule suffit, le header `X-Hermes-Profile` route)
66
+
67
+ ### Services partagés (NE PAS dupliquer)
68
+
69
+ | Service | Port | URL | Rôle |
70
+ |---------|------|-----|------|
71
+ | **Overmind MCP** | :3099 | `http://[::1]:3099/mcp` | 14 tools : run_agent, a2a_hub, agent_control, memory_*, create_agent |
72
+ | **Hermes Gateway** | :8642 | `http://127.0.0.1:8642` | API Server HTTP+SSE, OpenAI-compatible, profile routing |
73
+ | **PostgreSQL** | :5432 | `localhost` | MessageLog (`bridge_messages`) + Memory (pgvector) |
74
+
75
+ ### Allocation des ports
76
+
77
+ Les ports suivent une séquence simple : **3101 + offset**.
78
+
79
+ | Agent # | Port | Exemple nom |
80
+ |---------|------|-------------|
81
+ | #1 | 3101 | `agent_alpha` |
82
+ | #2 | 3102 | `agent_beta` |
83
+ | #3 | 3103 | `agent_gamma` |
84
+ | ... | ... | ... |
85
+ | #N | 3100+N | `agent_<name>` |
86
+
87
+ ---
88
+
89
+ ## 3. Créer un Agent Persistant
90
+
91
+ ### Étape 1 : Créer le profil Hermes
92
+
93
+ ```python
94
+ # Via MCP tool (recommandé)
95
+ create_agent(
96
+ name: "agent_alpha",
97
+ runner: "hermes",
98
+ prompt: "Tu es l'agent Alpha. Tes missions: ...",
99
+ model: "glm-5.2"
100
+ )
101
+ ```
102
+
103
+ Ou via CLI :
104
+ ```bash
105
+ hermes profile create agent_alpha --no-alias --description "Agent Alpha"
106
+ hermes -p agent_alpha config set model.provider z-ai
107
+ hermes -p agent_alpha config set model.model glm-5.2
108
+ ```
109
+
110
+ ### Structure créée sur disque
111
+
112
+ ```
113
+ ~/.hermes/profiles/agent_alpha/
114
+ ├── config.yaml # provider, model, mcp_servers
115
+ ├── .env # clés API (GLM_API_KEY, MINIMAX_CN_API_KEY, ...)
116
+ ├── SOUL.md # system prompt + instructions mémoire
117
+ ├── profile.yaml # metadata kanban routing
118
+ ├── workspace.yaml # kind: persistent, gc_eligible: false
119
+ ├── memories/ # state.db (mémoire SQLite isolée)
120
+ ├── sessions/ # historique conversations
121
+ └── skills/ # mémoire procédurale
122
+ ```
123
+
124
+ ### Auto-détection du provider
125
+
126
+ | Modèle contient | Provider | Clé API |
127
+ |-----------------|----------|---------|
128
+ | `minimax`, `m3` | `minimax-cn` | `MINIMAX_CN_API_KEY` |
129
+ | `glm`, `zai` | `z-ai` | `GLM_API_KEY` |
130
+ | `claude`, `sonnet` | `anthropic` | `ANTHROPIC_API_KEY` |
131
+ | `gpt` | `openai` | `OPENAI_API_KEY` |
132
+ | `deepseek` | `deepseek` | `DEEPSEEK_API_KEY` |
133
+ | *(autre)* | `openrouter` | `OPENROUTER_API_KEY` |
134
+
135
+ ### Étape 2 : Créer le bridge
136
+
137
+ ```bash
138
+ # Créer la structure
139
+ mkdir -p bridges/agent_alpha/{src/clients,logs}
140
+ ```
141
+
142
+ **`bridges/agent_alpha/.env`** :
143
+ ```bash
144
+ AGENT_NAME=agent_alpha
145
+ RUNNER=hermes
146
+ BRIDGE_PORT=3101
147
+ BRIDGE_HOST=127.0.0.1
148
+ MCP_URL=http://[::1]:3099/mcp
149
+ HERMES_GATEWAY_URL=http://127.0.0.1:8642
150
+ HERMES_GATEWAY_KEY=<key>
151
+ SESSION_TTL_MS=14400000
152
+ MESSAGE_LOG_ENABLED=true
153
+ MCP_TIMEOUT_MS=120000
154
+
155
+ # Peers (autres bridges — vide si seul, ou liste tous les autres)
156
+ PEER_BETA_URL=http://127.0.0.1:3102
157
+ PEER_GAMMA_URL=http://127.0.0.1:3103
158
+ ```
159
+
160
+ **`bridges/agent_alpha/src/config.ts`** :
161
+ ```typescript
162
+ import { existsSync, readFileSync } from 'node:fs';
163
+ import { resolve, dirname } from 'node:path';
164
+ import { fileURLToPath } from 'node:url';
165
+ import type { PeerMap } from '../../../common/src/types.js';
166
+
167
+ const __dirname = dirname(fileURLToPath(import.meta.url));
168
+
169
+ function loadEnv(): Record<string, string> {
170
+ const candidatePaths = [
171
+ resolve(__dirname, '..', '.env'),
172
+ resolve(__dirname, '..', '..', '..', '.env'),
173
+ ];
174
+ for (const p of candidatePaths) {
175
+ if (existsSync(p)) return parseEnv(readFileSync(p, 'utf-8'));
176
+ }
177
+ throw new Error(`Missing .env. Looked in:\n ${candidatePaths.join('\n ')}`);
178
+ }
179
+
180
+ function parseEnv(raw: string): Record<string, string> {
181
+ const env: Record<string, string> = {};
182
+ for (const line of raw.split(/\r?\n/)) {
183
+ const t = line.trim();
184
+ if (!t || t.startsWith('#')) continue;
185
+ const idx = t.indexOf('=');
186
+ if (idx === -1) continue;
187
+ env[t.slice(0, idx).trim()] = t.slice(idx + 1).trim().replace(/^["']|["']$/g, '');
188
+ }
189
+ return env;
190
+ }
191
+
192
+ const env = loadEnv();
193
+
194
+ export const config = {
195
+ agentName: env.AGENT_NAME ?? 'agent_alpha',
196
+ runner: env.RUNNER ?? 'hermes',
197
+ port: parseInt(env.BRIDGE_PORT ?? '3101', 10),
198
+ host: env.BRIDGE_HOST ?? '127.0.0.1',
199
+ mcpUrl: env.MCP_URL ?? 'http://[::1]:3099/mcp',
200
+ hermesGatewayUrl: env.HERMES_GATEWAY_URL ?? 'http://127.0.0.1:8642',
201
+ gatewayKey: env.HERMES_GATEWAY_KEY ?? '',
202
+ peers: {
203
+ beta: env.PEER_BETA_URL,
204
+ gamma: env.PEER_GAMMA_URL,
205
+ // ... ajouter autant de peers que nécessaire
206
+ } as PeerMap,
207
+ sessionTtlMs: parseInt(env.SESSION_TTL_MS ?? '14400000', 10),
208
+ messageLogEnabled: env.MESSAGE_LOG_ENABLED === 'true',
209
+ mcpTimeoutMs: parseInt(env.MCP_TIMEOUT_MS ?? '120000', 10),
210
+ };
211
+ ```
212
+
213
+ **`bridges/agent_alpha/src/bridge.ts`** :
214
+ ```typescript
215
+ import { BaseBridge } from '../../../common/src/BaseBridge.js';
216
+ import { Logger } from '../../../common/src/logger.js';
217
+ import { config } from './config.js';
218
+
219
+ const logger = new Logger(config.agentName);
220
+
221
+ class AgentAlphaBridge extends BaseBridge {
222
+ constructor() {
223
+ super({
224
+ agentName: config.agentName,
225
+ port: config.port,
226
+ host: config.host,
227
+ mcpUrl: config.mcpUrl,
228
+ gatewayUrl: config.hermesGatewayUrl,
229
+ peers: config.peers,
230
+ mcpTimeoutMs: config.mcpTimeoutMs,
231
+ sessionTtlMs: config.sessionTtlMs,
232
+ messageLogEnabled: config.messageLogEnabled,
233
+ });
234
+
235
+ // Enregistrer les méthodes RPC locales spécifiques à cet agent
236
+ this.registerRpcMethod('alpha.execute', async (params) => {
237
+ logger.info('Execute requested', params);
238
+ return { status: 'done', ts: Date.now() };
239
+ });
240
+ }
241
+ }
242
+
243
+ const bridge = new AgentAlphaBridge();
244
+ bridge.start().catch((err) => {
245
+ logger.error('Failed to start', { error: (err as Error).message });
246
+ process.exit(1);
247
+ });
248
+
249
+ const shutdown = async (signal: string) => {
250
+ logger.info(`Received ${signal} — shutting down`);
251
+ await bridge.stop();
252
+ process.exit(0);
253
+ };
254
+ process.on('SIGINT', () => shutdown('SIGINT'));
255
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
256
+ ```
257
+
258
+ ### Étape 3 : Build et démarrage
259
+
260
+ ```bash
261
+ # Build (depuis la racine du projet)
262
+ npm run build
263
+
264
+ # Démarrer ce bridge
265
+ node dist/bridges/agent_alpha/src/bridge.js
266
+
267
+ # Vérifier
268
+ curl http://127.0.0.1:3101/health
269
+ ```
270
+
271
+ ---
272
+
273
+ ## 4. Module Common (partagé entre tous les bridges)
274
+
275
+ ### `common/src/BaseBridge.ts`
276
+
277
+ Classe abstraite — chaque bridge l'étend. Fournit :
278
+ - Serveur HTTP (`POST /rpc`, `GET /health`, `POST /shutdown`)
279
+ - `registerRpcMethod(name, handler)` — méthodes RPC locales
280
+ - `forwardToMcp(request)` — forward vers MCP Overmind (`:3099/mcp`)
281
+ - SSE parsing (FastMCP répond en Server-Sent Events)
282
+ - Keep-alive HTTP agent (perf: connection reuse)
283
+ - Graceful shutdown (SIGINT/SIGTERM)
284
+
285
+ **Routage RPC interne** :
286
+ ```
287
+ POST /rpc → dispatchRpc(method)
288
+ 1. health.ping → local (toujours)
289
+ 2. Méthode locale (registerRpcMethod) → handler local
290
+ 3. Sinon → forwardToMcp() → POST http://[::1]:3099/mcp
291
+ ```
292
+
293
+ ### `common/src/BridgeClient.ts`
294
+
295
+ Client HTTP pour appels inter-bridges (A2A). Fournit :
296
+ - `call(method, params)` — JSON-RPC 2.0 avec retry + backoff
297
+ - `healthCheck()` — GET /health sur un peer
298
+ - `sendToAgent(agentName, prompt)` — wrapper `agent.run`
299
+ - UUID uniques (pas de collision)
300
+ - Keep-alive agent partagé
301
+
302
+ ```typescript
303
+ const client = new BridgeClient('http://127.0.0.1:3102');
304
+ const result = await client.call('beta.analyze', { symbol: 'BTC' });
305
+ ```
306
+
307
+ ### `common/src/types.ts`
308
+
309
+ Interfaces partagées : `BridgeConfig`, `PeerMap`, `HealthStatus`, `JsonRpcRequest/Response`, `RunnerType`.
310
+
311
+ ### `common/src/logger.ts`
312
+
313
+ Logger zero-dep : console colorisée + fichier async (non bloquant), rotation 50MB, safe stringify (circular refs).
314
+
315
+ ---
316
+
317
+ ## 5. Commandes RPC (par bridge)
318
+
319
+ ### Format de requête
320
+
321
+ ```bash
322
+ curl -X POST http://127.0.0.1:<PORT>/rpc \
323
+ -H "Content-Type: application/json" \
324
+ -d '{"jsonrpc":"2.0","id":"<id>","method":"<method>","params":{...}}'
325
+ ```
326
+
327
+ ### Endpoints communs (tous les bridges)
328
+
329
+ | Endpoint | HTTP | Description |
330
+ |----------|------|-------------|
331
+ | `GET /health` | GET | `{ agent, status, uptime, rpcMethods[], peerCount }` |
332
+ | `POST /rpc` | POST | JSON-RPC 2.0 dispatcher |
333
+ | `POST /shutdown` | POST | Arrêt propre |
334
+
335
+ ### Méthodes RPC standards (tous les bridges)
336
+
337
+ | Méthode | Params | Description |
338
+ |---------|--------|-------------|
339
+ | `health.ping` | — | Ping local (toujours OK) |
340
+
341
+ ### Méthodes RPC customs (spécifiques par agent)
342
+
343
+ Chaque agent enregistre ses propres méthodes via `registerRpcMethod()`. Exemple avec NEXUS :
344
+
345
+ #### Exemple : nexus_master (orchestrateur)
346
+
347
+ | Méthode | Params | Description |
348
+ |---------|--------|-------------|
349
+ | `master.status` | — | Agrège la santé de tous les peers |
350
+ | `master.broadcast` | `{ message }` | Fan-out à tous les peers |
351
+ | `master.pipeline` | `{ steps: [{ peer, prompt }] }` | Chaîne A→B→C |
352
+ | `master.fanout` | `{ peers[], prompt, merge? }` | Parallèle N + merge |
353
+
354
+ #### Exemple : nexus_trader
355
+
356
+ | Méthode | Params | Description |
357
+ |---------|--------|-------------|
358
+ | `trade.request` | `{ symbol, side, quantity }` | Valide via risk, notifie publisher |
359
+ | `trade.analysis` | `{ symbol, timeframe? }` | Délègue au researcher |
360
+
361
+ #### Exemple : nexus_risk_manager
362
+
363
+ | Méthode | Params | Description |
364
+ |---------|--------|-------------|
365
+ | `risk.validate` | `{ symbol, side, quantity }` | Valide un trade |
366
+ | `risk.drawdown` | — | Check drawdown |
367
+ | `risk.feedback` | `{ message, type }` | Feedback au trader |
368
+
369
+ #### Pattern pour créer tes propres méthodes
370
+
371
+ ```typescript
372
+ // Dans ton bridge.ts
373
+ this.registerRpcMethod('myagent.dosomething', async (params) => {
374
+ const p = params as { input: string };
375
+ // Logique métier ici
376
+ return { result: 'done', ts: Date.now() };
377
+ });
378
+ ```
379
+
380
+ ---
381
+
382
+ ## 6. A2A — Communication Inter-Bridges
383
+
384
+ ### A2A direct (bridge → bridge)
385
+
386
+ ```typescript
387
+ // Dans un bridge, appeler un autre bridge
388
+ import { BridgeClient } from '../../../common/src/BridgeClient.js';
389
+
390
+ const peerClient = new BridgeClient('http://127.0.0.1:3102');
391
+ const result = await peerClient.call('trade.request', {
392
+ symbol: 'BTC', side: 'BUY', quantity: 0.1,
393
+ });
394
+ ```
395
+
396
+ ### A2A via MCP Hub (tool `a2a_hub`)
397
+
398
+ Le MCP Overmind expose le tool `a2a_hub` avec 8 actions :
399
+
400
+ | Action | Params | Description |
401
+ |--------|--------|-------------|
402
+ | `discover` | — | Liste tous les agents + statut |
403
+ | `status` | `target` | État détaillé d'un agent |
404
+ | `send` | `target, message` | Message synchrone A→B |
405
+ | `delegate` | `target, message, callbackUrl?` | Async (retourne taskId) |
406
+ | `pipeline` | `message, steps[]` | Chaîne A→B→C |
407
+ | `fanout` | `targets[], message, mergeStrategy?` | 1→N + merge |
408
+ | `query` | `targets[], message` | Question multi-agents |
409
+ | `broadcast` | `message, race?` | Global à tous |
410
+
411
+ ```python
412
+ a2a_hub(action="send", target="nexus_trader", message="Analyse BTC")
413
+ a2a_hub(action="fanout", targets=["agent_a","agent_b"], message="BTC?", mergeStrategy="best")
414
+ a2a_hub(action="pipeline", message="Analyse", steps=[{"agentName":"researcher"},{"agentName":"trader"}])
415
+ ```
416
+
417
+ ### A2A via OverBridgeServer (JSON-RPC 24 méthodes)
418
+
419
+ Le `OverBridgeServer` expose des méthodes A2A avancées avec persistence Postgres :
420
+
421
+ | Méthode | Description |
422
+ |---------|-------------|
423
+ | `agent.run` | Lance un agent (avec SessionStore multi-tenant) |
424
+ | `agent.a2a` | A→B avec header A2A standardisé |
425
+ | `agent.broadcast` | 1→N (race ou attend tous) |
426
+ | `agent.pipeline` | Chaîne A→B→C (accumulateContext?) |
427
+ | `agent.fanout` | 1→N + merge (concat/best/vote/first_success) |
428
+ | `agent.delegate` | Fire-and-forget + callback URL |
429
+ | `agent.query` | Multi-agent read-only rapide |
430
+ | `agent.status` | Status live (busy/idle/online) |
431
+ | `agent.list` | Liste filtrée |
432
+ | `agent.kill` | Kill un agent |
433
+ | `message.history` | Historique paginé (Postgres) |
434
+ | `message.get` | Récupère un message par UUID |
435
+ | `message.replay` | Rejoue un message |
436
+ | `message.stats` | Stats globales |
437
+ | `session.get` | Session par externalKey + agentName |
438
+ | `session.list` | Toutes les sessions |
439
+ | `session.delete` | Supprime une session |
440
+ | `session.stats` | Stats sessions |
441
+ | `webhook.sms` | Adapt + auto-dispatch SMS |
442
+ | `health.ping` | Liveness |
443
+
444
+ ---
445
+
446
+ ## 7. Lancer un Agent
447
+
448
+ ### Via Gateway HTTP (recommandé — zero subprocess)
449
+
450
+ ```python
451
+ run_agent(runner: "hermes", agentName: "agent_alpha", prompt: "Analyse le marché")
452
+ ```
453
+
454
+ Sous le capot : `HermesGatewayRunner` → `POST :8642/v1/chat/completions` avec `X-Hermes-Profile: agent_alpha` + SSE streaming. Pas de spawn CLI.
455
+
456
+ ### Via curl direct sur le Gateway
457
+
458
+ ```bash
459
+ curl -X POST http://127.0.0.1:8642/v1/chat/completions \
460
+ -H "Content-Type: application/json" \
461
+ -H "Authorization: Bearer ${API_SERVER_KEY}" \
462
+ -H "X-Hermes-Profile: agent_alpha" \
463
+ -d '{"model":"glm-5.2","messages":[{"role":"user","content":"Analyse le BTC"}],"stream":true}'
464
+ ```
465
+
466
+ ### Via bridge RPC
467
+
468
+ ```bash
469
+ curl -X POST http://127.0.0.1:3101/rpc \
470
+ -H "Content-Type: application/json" \
471
+ -d '{"jsonrpc":"2.0","id":"1","method":"agent.run","params":{"agentName":"agent_alpha","runner":"hermes","prompt":"Analyse le BTC"}}'
472
+ ```
473
+
474
+ ### Via Hermes CLI
475
+
476
+ ```bash
477
+ hermes -p agent_alpha chat -q "Analyse le BTC" -Q --yolo
478
+ ```
479
+
480
+ ---
481
+
482
+ ## 8. Gestion du Cycle de Vie
483
+
484
+ ### Profils Hermes
485
+
486
+ | Action | Commande |
487
+ |--------|----------|
488
+ | Lister | `hermes profile list` |
489
+ | Voir | `hermes profile show agent_alpha` |
490
+ | Supprimer | `hermes profile delete agent_alpha --yes` |
491
+ | Changer modèle | `hermes -p agent_alpha config set model.model "MiniMax-M3"` |
492
+ | Update via Overmind | `update_agent_config(name: "agent_alpha", model: "new-model")` |
493
+
494
+ ### Runtime
495
+
496
+ | Action | Commande |
497
+ |--------|----------|
498
+ | Status | `agent_control(agentName: "agent_alpha", action: "status")` |
499
+ | Stream output | `agent_control(agentName: "agent_alpha", action: "stream")` |
500
+ | Kill | `agent_control(agentName: "agent_alpha", action: "kill")` |
501
+ | Health bridge | `curl http://127.0.0.1:3101/health` |
502
+ | Shutdown bridge | `curl -X POST http://127.0.0.1:3101/shutdown` |
503
+
504
+ ---
505
+
506
+ ## 9. Scripts Helper
507
+
508
+ ### Démarrage N bridges
509
+
510
+ ```bash
511
+ # Start all (NEXUS example with 6)
512
+ node scripts/start-all-bridges.cjs
513
+
514
+ # Stop all
515
+ node scripts/stop-all-bridges.cjs
516
+
517
+ # Status
518
+ node scripts/status-bridges.cjs
519
+
520
+ # Test A2A network
521
+ node scripts/test-a2a.cjs
522
+ ```
523
+
524
+ ### Seed (créer la structure pour N agents)
525
+
526
+ ```bash
527
+ node scripts/seed-bridges.cjs
528
+ # Crée bridges/<name>/{src/clients,logs} + .env pour chaque agent
529
+ ```
530
+
531
+ ### Build
532
+
533
+ ```bash
534
+ # Build complet (tsc + postbuild copie .env et config)
535
+ npm run build
536
+
537
+ # Le postbuild copie automatiquement:
538
+ # config/*.json → dist/config/
539
+ # bridges/*/.env → dist/bridges/*/.env
540
+ ```
541
+
542
+ ### Activation Hermes Gateway
543
+
544
+ ```bash
545
+ # Dans config.yaml
546
+ gateway:
547
+ platforms:
548
+ api_server:
549
+ enabled: true
550
+
551
+ # Dans .env
552
+ API_SERVER_KEY=<key>
553
+ API_SERVER_ENABLED=1
554
+
555
+ # Redémarrer
556
+ hermes gateway restart
557
+ ```
558
+
559
+ ---
560
+
561
+ ## 10. Ce que l'Agent Hérite Automatiquement
562
+
563
+ | Héritage | Source |
564
+ |----------|--------|
565
+ | **Mémoire isolée** | `state.db` SQLite dans `memories/` — `OVERMIND_AGENT_NAME` injecté |
566
+ | **Instructions mémoire** | Bloc "## Mémoire Overmind" injecté dans `SOUL.md` |
567
+ | **MCP servers** | `memory` (3 tools: search/store/runs) par défaut |
568
+ | **Clés API** | Toutes les clés du `.env` parent forwardées (GLM, MiniMax, OpenAI, ...) |
569
+ | **Sessions persistantes** | `sessions/` garde l'historique, `workspace.yaml: persistent` |
570
+ | **Kanban routing** | `profile.yaml` pour découverte par `a2a_hub` |
571
+ | **Gateway HTTP** | `HermesGatewayRunner` → `POST :8642` avec `X-Hermes-Profile` |
572
+ | **Circuit breaker** | `BridgeProxy` : 5 failures → open, 30s → half-open, 3 success → closed |
573
+ | **Retry automatique** | `ETIMEDOUT`, `EBODYREAD`, `ECONNRESET` → retry avec backoff |
574
+
575
+ ---
576
+
577
+ ## 11. Bugs Source Corrigés (2026-07-10)
578
+
579
+ ### Overmind (`Workflow/src/bridge/`)
580
+
581
+ | Bug | Fichier | Fix |
582
+ |-----|---------|-----|
583
+ | `localhost` au lieu de `[::1]` (IPv4/IPv6 mismatch) | `types.ts` | → `http://[::1]:3099/mcp` |
584
+ | `ping()` sans SSE Accept (FastMCP rejette) | `BridgeProxy.ts` | → `Accept: text/event-stream` + fallback `GET /health` |
585
+ | `parseSseText` non importé | `BridgeProxy.ts` | → Import ajouté |
586
+
587
+ ### NEXUS (`Nexus/common/` + `bridges/`)
588
+
589
+ | Bug | Fichier | Fix |
590
+ |-----|---------|-----|
591
+ | MCP URL `/rpc` au lieu de `/mcp` (404) | `BaseBridge.ts` | → `/mcp` + SSE parsing |
592
+ | Timeout MCP hardcodé 60s | `BaseBridge.ts` | → `config.mcpTimeoutMs` (120s) |
593
+ | `Date.now()` ID collision | `BridgeClient.ts` | → `crypto.randomUUID()` |
594
+ | `appendFileSync` (sync I/O) | `logger.ts` | → `appendFile` async + rotation 50MB |
595
+ | RPC custom forwardée au MCP (404) | `BaseBridge.ts` | → `registerRpcMethod()` dispatch local |
596
+ | `.env` introuvable après build | `config.ts` | → `candidatePaths[]` multi-niveaux |
597
+ | `postbuild` ne copiait pas `.env` | `postbuild.cjs` | → Section 2: copy bridges/.env |
598
+ | `*/` dans JSDoc cassait CJS | `postbuild.cjs` | → Comment reworded |
599
+ | Pas de graceful shutdown | `bridge.ts` ×N | → `process.on('SIGINT'/'SIGTERM')` |
600
+ | Pas de keep-alive HTTP | `BridgeClient.ts` | → `HttpAgent({ keepAlive: true })` |
601
+
602
+ ### discord_llm
603
+
604
+ | Bug | Fichier | Fix |
605
+ |-----|---------|-----|
606
+ | `localhost:3099` au lieu de `[::1]` | `overmind-bridge.ts` | → `http://[::1]:3099/mcp` |
607
+ | `no-useless-assignment` lint | `overmind-bridge.ts` | → `let mcpStatus: string` |
608
+
609
+ ---
610
+
611
+ ## 12. Exemple Complet — 3 Agents qui Communiquent
612
+
613
+ ### Créer 3 agents
614
+
615
+ ```python
616
+ create_agent(name: "coordinator", runner: "hermes", prompt: "Tu coordonnes...", model: "glm-5.2")
617
+ create_agent(name: "worker_a", runner: "hermes", prompt: "Tu exécutes...", model: "glm-5.2")
618
+ create_agent(name: "worker_b", runner: "hermes", prompt: "Tu valides...", model: "glm-5.2")
619
+ ```
620
+
621
+ ### Structure
622
+
623
+ ```
624
+ bridges/
625
+ ├── coordinator/ # :3101
626
+ │ ├── .env # PEER_WORKER_A_URL=http://127.0.0.1:3102
627
+ │ │ # PEER_WORKER_B_URL=http://127.0.0.1:3103
628
+ │ ├── src/bridge.ts # registerRpcMethod('coord.dispatch', ...)
629
+ │ └── src/clients/CoordinatorToWorkerA.ts
630
+
631
+ ├── worker_a/ # :3102
632
+ │ ├── .env # PEER_COORDINATOR_URL=http://127.0.0.1:3101
633
+ │ └── src/bridge.ts # registerRpcMethod('worker.execute', ...)
634
+
635
+ └── worker_b/ # :3103
636
+ ├── .env # PEER_COORDINATOR_URL=http://127.0.0.1:3101
637
+ └── src/bridge.ts # registerRpcMethod('worker.validate', ...)
638
+ ```
639
+
640
+ ### Communication
641
+
642
+ ```bash
643
+ # Coordinator → Worker A (via bridge HTTP)
644
+ curl -X POST http://127.0.0.1:3101/rpc \
645
+ -d '{"jsonrpc":"2.0","id":"1","method":"coord.dispatch","params":{"task":"analyze BTC"}}'
646
+
647
+ # Worker A → Worker B (via BridgeClient dans le code)
648
+ const client = new BridgeClient('http://127.0.0.1:3103');
649
+ await client.call('worker.validate', { result: 'BTC bullish' });
650
+
651
+ # Coordinator → tous (broadcast)
652
+ curl -X POST http://127.0.0.1:3101/rpc \
653
+ -d '{"jsonrpc":"2.0","id":"2","method":"master.broadcast","params":{"message":"Standby"}}'
654
+ ```
655
+
656
+ ### Démarrage
657
+
658
+ ```bash
659
+ node scripts/start-all-bridges.cjs # Lance les 3 en parallèle
660
+ curl http://127.0.0.1:3101/health # Verify coordinator
661
+ curl http://127.0.0.1:3102/health # Verify worker_a
662
+ curl http://127.0.0.1:3103/health # Verify worker_b
663
+ ```
664
+
665
+ Le pattern est **identique** pour 2, 6, 10, ou 100 agents. Ajoute un bridge, un port, un .env, et il communique avec les autres via HTTP.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "overmind-mcp",
3
- "version": "3.5.2",
3
+ "version": "3.6.1",
4
4
  "description": "Orchestrateur universel agents IA multi-modeles via MCP. Inclut le protocole 'Custom-Nickname' pour identifier vos agents avec des surnoms originaux (The Chaos Prophet, Shadow Sniper, etc.), l'isolation mémoire (Private Memory Context) et le support pour QwenCli et Nous Hermes. Installation automatique des dépendances Docker (PostgreSQL, pgvector) inclus.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",