@olane/o-leader 0.7.2 → 0.7.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.
- package/README.md +524 -258
- package/dist/src/leader.node.d.ts.map +1 -1
- package/dist/src/leader.node.js +2 -0
- package/package.json +8 -7
package/README.md
CHANGED
|
@@ -1,102 +1,135 @@
|
|
|
1
|
-
# o-leader
|
|
1
|
+
# o-leader {#o-leader}
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**The root coordinator for self-organizing Olane OS agent networks.**
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
- **One-line definition**: The root coordinator node for Olane OS agent networks
|
|
7
|
-
- **Business value statement**: Provides centralized coordination and discovery for distributed agent networks
|
|
8
|
-
- **Key differentiator**: Self-organizing agent networks without manual infrastructure configuration
|
|
5
|
+
**TL;DR**: `o-leader` enables multi-agent systems to discover and coordinate autonomously. Agents self-register their capabilities, discover other agents via a built-in registry, and form dynamic networks without manual configuration. Perfect for scaling from single-agent to distributed multi-agent architectures.
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
-
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Overview {#overview}
|
|
10
|
+
|
|
11
|
+
`o-leader` is the **root coordinator node** for Olane OS agent networks. It provides centralized discovery and coordination for distributed agents, enabling self-organizing systems without manual infrastructure configuration.
|
|
12
|
+
|
|
13
|
+
### When to use o-leader {#when-to-use}
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
- **
|
|
18
|
-
- **
|
|
19
|
-
- **
|
|
20
|
-
-
|
|
15
|
+
Use `o-leader` when:
|
|
16
|
+
- Building **multi-agent systems** requiring coordination
|
|
17
|
+
- Creating **discoverable agent networks** (agents find each other autonomously)
|
|
18
|
+
- Implementing **hierarchical agent architectures** (departments, teams, domains)
|
|
19
|
+
- Scaling from **single-agent to multi-agent** systems
|
|
20
|
+
|
|
21
|
+
### Core capabilities {#core-capabilities}
|
|
22
|
+
|
|
23
|
+
<CardGroup cols={2}>
|
|
24
|
+
<Card title="Network Coordination" icon="network-wired" color="#0D9373">
|
|
25
|
+
Entry point for agents joining the network
|
|
26
|
+
</Card>
|
|
27
|
+
<Card title="Agent Discovery" icon="magnifying-glass" color="#0D9373">
|
|
28
|
+
Built-in registry for finding agents by capability
|
|
29
|
+
</Card>
|
|
30
|
+
<Card title="Network Intelligence" icon="brain" color="#0D9373">
|
|
31
|
+
Automatic indexing and mapping of agent capabilities
|
|
32
|
+
</Card>
|
|
33
|
+
<Card title="Fault Tolerance" icon="shield" color="#0D9373">
|
|
34
|
+
Automatic failover and recovery coordination
|
|
35
|
+
</Card>
|
|
36
|
+
</CardGroup>
|
|
21
37
|
|
|
22
38
|
---
|
|
23
39
|
|
|
24
|
-
##
|
|
40
|
+
## Quick Start {#quick-start}
|
|
41
|
+
|
|
42
|
+
### Prerequisites {#prerequisites}
|
|
25
43
|
|
|
26
|
-
### Prerequisites
|
|
27
44
|
- Node.js 20.x or higher
|
|
28
45
|
- Basic understanding of Olane OS concepts
|
|
29
|
-
-
|
|
46
|
+
- `@olane/o-core` installed
|
|
47
|
+
|
|
48
|
+
### Installation {#installation}
|
|
30
49
|
|
|
31
|
-
### Installation
|
|
32
50
|
```bash
|
|
33
51
|
npm install @olane/o-leader
|
|
34
52
|
```
|
|
35
53
|
|
|
36
|
-
### Basic Leader Node Setup
|
|
54
|
+
### Basic Leader Node Setup {#basic-setup}
|
|
55
|
+
|
|
37
56
|
```typescript
|
|
38
57
|
import { oLeaderNode } from '@olane/o-leader';
|
|
39
|
-
import {
|
|
58
|
+
import { oAddress } from '@olane/o-core';
|
|
40
59
|
|
|
41
|
-
// Create a leader node
|
|
60
|
+
// Create a leader node for your agent network
|
|
42
61
|
const leader = new oLeaderNode({
|
|
43
62
|
networkName: 'my-agent-network',
|
|
44
|
-
//
|
|
63
|
+
address: oAddress.leader(), // o://leader
|
|
45
64
|
});
|
|
46
65
|
|
|
47
|
-
// Start the leader
|
|
66
|
+
// Start the leader (initializes registry and coordination services)
|
|
48
67
|
await leader.start();
|
|
49
68
|
|
|
50
|
-
|
|
69
|
+
console.log('Leader node running at o://leader');
|
|
70
|
+
console.log('Registry service available at o://registry');
|
|
51
71
|
```
|
|
52
72
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
### Next Steps
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
73
|
+
**What this does:**
|
|
74
|
+
1. Creates a leader node at `o://leader`
|
|
75
|
+
2. Initializes the built-in registry at `o://registry`
|
|
76
|
+
3. Opens the network for agents to join
|
|
77
|
+
|
|
78
|
+
### Next Steps {#next-steps}
|
|
79
|
+
|
|
80
|
+
<CardGroup cols={3}>
|
|
81
|
+
<Card title="Join Agents" icon="users" href="#joining-agents-to-network">
|
|
82
|
+
Connect agents to your network
|
|
83
|
+
</Card>
|
|
84
|
+
<Card title="Discover Agents" icon="magnifying-glass" href="#using-the-registry">
|
|
85
|
+
Search for agents by capability
|
|
86
|
+
</Card>
|
|
87
|
+
<Card title="Custom Validation" icon="shield-check" href="#join-request-validation">
|
|
88
|
+
Implement access control
|
|
89
|
+
</Card>
|
|
90
|
+
</CardGroup>
|
|
62
91
|
|
|
63
92
|
---
|
|
64
93
|
|
|
65
|
-
##
|
|
94
|
+
## Core Concepts {#core-concepts}
|
|
95
|
+
|
|
96
|
+
### Leader Node Architecture {#leader-architecture}
|
|
66
97
|
|
|
67
|
-
|
|
98
|
+
The leader node is the **root coordinator** of an Olane OS agent network. Unlike traditional orchestrators that require pre-defined workflows, `o-leader` enables **emergent coordination** where agents self-organize.
|
|
68
99
|
|
|
69
|
-
####
|
|
70
|
-
The leader node is the **root coordinator** of an Olane OS agent network. Unlike traditional orchestrators, it enables **emergent coordination** rather than explicit control.
|
|
100
|
+
#### Key Responsibilities {#leader-responsibilities}
|
|
71
101
|
|
|
72
|
-
#### Key Responsibilities
|
|
73
102
|
1. **Network Entry Point**: First contact for agents joining the network
|
|
74
103
|
2. **Registry Management**: Maintains live directory of agents and capabilities
|
|
75
104
|
3. **Discovery Coordination**: Helps agents find each other via `o://` addressing
|
|
76
105
|
4. **Network Intelligence**: Tracks and indexes agent capabilities across the network
|
|
77
106
|
|
|
78
|
-
#### Leader vs Traditional Orchestration
|
|
107
|
+
#### Leader vs Traditional Orchestration {#leader-vs-traditional}
|
|
108
|
+
|
|
79
109
|
| Traditional Orchestrators | o-leader Node |
|
|
80
110
|
|--------------------------|---------------|
|
|
81
|
-
| Pre-defined workflows | Emergent workflows |
|
|
82
|
-
| Centralized control | Distributed coordination |
|
|
83
|
-
| Manual scaling | Self-organizing |
|
|
84
|
-
| Fixed topology | Dynamic hierarchy |
|
|
111
|
+
| Pre-defined workflows | **Emergent workflows** |
|
|
112
|
+
| Centralized control | **Distributed coordination** |
|
|
113
|
+
| Manual scaling | **Self-organizing** |
|
|
114
|
+
| Fixed topology | **Dynamic hierarchy** |
|
|
85
115
|
|
|
86
|
-
### The Registry Service
|
|
116
|
+
### The Registry Service {#registry-service}
|
|
87
117
|
|
|
88
|
-
#### Purpose
|
|
89
118
|
The registry is the **discovery mechanism** for your agent network - a dynamic directory where agents register their capabilities and find other agents.
|
|
90
119
|
|
|
91
|
-
#### Registry Operations
|
|
120
|
+
#### Registry Operations {#registry-operations}
|
|
121
|
+
|
|
92
122
|
- **`commit`**: Register an agent and its capabilities
|
|
93
123
|
- **`search`**: Find agents by address, protocol, or capability
|
|
94
|
-
-
|
|
124
|
+
- **`find_all`**: List all registered agents
|
|
95
125
|
- **`remove`**: Deregister an agent from the network
|
|
96
126
|
|
|
97
|
-
####
|
|
127
|
+
#### Example: Finding Agents by Capability {#registry-example}
|
|
128
|
+
|
|
98
129
|
```typescript
|
|
99
|
-
|
|
130
|
+
import { oAddress } from '@olane/o-core';
|
|
131
|
+
|
|
132
|
+
// Search for agents with specific capabilities
|
|
100
133
|
const agents = await leader.use(new oAddress('o://registry'), {
|
|
101
134
|
method: 'search',
|
|
102
135
|
params: {
|
|
@@ -104,34 +137,38 @@ const agents = await leader.use(new oAddress('o://registry'), {
|
|
|
104
137
|
}
|
|
105
138
|
});
|
|
106
139
|
|
|
107
|
-
|
|
140
|
+
console.log(`Found ${agents.result.length} agents with payment capabilities`);
|
|
141
|
+
// Use the discovered agents in your workflow
|
|
108
142
|
```
|
|
109
143
|
|
|
110
|
-
### Network Joining Flow
|
|
144
|
+
### Network Joining Flow {#joining-flow}
|
|
145
|
+
|
|
146
|
+
When an agent joins the network, the following process occurs:
|
|
111
147
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
2. Leader validates the join request (customizable)
|
|
148
|
+
1. Agent sends join request to `o://leader`
|
|
149
|
+
2. Leader validates the request (customizable)
|
|
115
150
|
3. Leader updates parent-child relationships
|
|
116
151
|
4. Agent is registered in the registry
|
|
117
152
|
5. Agent receives network configuration
|
|
118
153
|
6. Agent can now discover and communicate with other agents
|
|
119
154
|
|
|
120
|
-
#### Join Request Structure
|
|
155
|
+
#### Join Request Structure {#join-request-structure}
|
|
156
|
+
|
|
121
157
|
```typescript
|
|
158
|
+
// Example join request parameters
|
|
122
159
|
{
|
|
123
|
-
caller: 'o://company/finance/analyst',
|
|
124
|
-
parent: 'o://company/finance',
|
|
125
|
-
transports: ['webrtc', 'websocket']
|
|
160
|
+
caller: 'o://company/finance/analyst', // Agent's address
|
|
161
|
+
parent: 'o://company/finance', // Parent in hierarchy
|
|
162
|
+
transports: ['webrtc', 'websocket'] // Supported transports
|
|
126
163
|
}
|
|
127
164
|
```
|
|
128
165
|
|
|
129
|
-
### Network Indexing
|
|
166
|
+
### Network Indexing {#network-indexing}
|
|
167
|
+
|
|
168
|
+
**Network indexing** periodically crawls all registered agents to build a **comprehensive map** of network capabilities, enabling intelligent routing and discovery.
|
|
130
169
|
|
|
131
|
-
####
|
|
132
|
-
Periodic crawling of all registered agents to build a **comprehensive map** of network capabilities, enabling intelligent routing and discovery.
|
|
170
|
+
#### Why Indexing Matters {#indexing-benefits}
|
|
133
171
|
|
|
134
|
-
#### Why Indexing Matters
|
|
135
172
|
- **Capability Discovery**: Agents can find specialized tools across the network
|
|
136
173
|
- **Intelligent Routing**: Requests automatically routed to capable agents
|
|
137
174
|
- **Network Health**: Identify disconnected or unresponsive agents
|
|
@@ -139,42 +176,53 @@ Periodic crawling of all registered agents to build a **comprehensive map** of n
|
|
|
139
176
|
|
|
140
177
|
---
|
|
141
178
|
|
|
142
|
-
##
|
|
179
|
+
## Integration Guide {#integration-guide}
|
|
143
180
|
|
|
144
|
-
### Setting Up Your Leader Node
|
|
181
|
+
### Setting Up Your Leader Node {#setup-leader}
|
|
182
|
+
|
|
183
|
+
#### Basic Configuration {#basic-configuration}
|
|
145
184
|
|
|
146
|
-
#### Basic Configuration
|
|
147
185
|
```typescript
|
|
148
186
|
import { oLeaderNode } from '@olane/o-leader';
|
|
187
|
+
import { oAddress, NodeType } from '@olane/o-core';
|
|
149
188
|
import { RegistryMemoryTool } from '@olane/o-leader';
|
|
150
189
|
|
|
190
|
+
// Create leader with basic configuration
|
|
151
191
|
const leader = new oLeaderNode({
|
|
152
192
|
networkName: 'production-agents',
|
|
153
193
|
address: oAddress.leader(), // o://leader
|
|
154
194
|
type: NodeType.LEADER,
|
|
155
|
-
// Optional: custom registry implementation
|
|
156
|
-
registry: new RegistryMemoryTool(config)
|
|
157
195
|
});
|
|
158
196
|
|
|
197
|
+
// Start the leader node (initializes registry and network services)
|
|
159
198
|
await leader.start();
|
|
199
|
+
|
|
200
|
+
console.log('Leader node ready to accept agent connections');
|
|
160
201
|
```
|
|
161
202
|
|
|
162
|
-
#### Configuration Options
|
|
163
|
-
- `networkName`: Identifier for your agent network
|
|
164
|
-
- `address`: Network address (defaults to `o://leader`)
|
|
165
|
-
- `type`: Node type (always `NodeType.LEADER`)
|
|
166
|
-
- `methods`: Custom methods exposed by the leader
|
|
167
|
-
- `registry`: Registry implementation (memory or persistent)
|
|
203
|
+
#### Configuration Options {#configuration-options}
|
|
168
204
|
|
|
169
|
-
|
|
205
|
+
| Option | Type | Description | Default |
|
|
206
|
+
|--------|------|-------------|---------|
|
|
207
|
+
| `networkName` | string | Identifier for your agent network | Required |
|
|
208
|
+
| `address` | oAddress | Network address | `o://leader` |
|
|
209
|
+
| `type` | NodeType | Node type | `NodeType.LEADER` |
|
|
210
|
+
| `methods` | object | Custom methods exposed by the leader | `{}` |
|
|
211
|
+
| `registry` | RegistryTool | Registry implementation (memory or persistent) | `RegistryMemoryTool` |
|
|
212
|
+
|
|
213
|
+
### Joining Agents to Network {#joining-agents-to-network}
|
|
214
|
+
|
|
215
|
+
#### From an Agent Node {#agent-join-example}
|
|
170
216
|
|
|
171
|
-
#### From an Agent Node
|
|
172
217
|
```typescript
|
|
173
218
|
import { oNode } from '@olane/o-node';
|
|
219
|
+
import { oAddress } from '@olane/o-core';
|
|
174
220
|
|
|
221
|
+
// Create an agent node
|
|
175
222
|
const agent = new oNode({
|
|
176
|
-
address: 'o://company/sales/analyst',
|
|
177
|
-
parent: 'o://company/sales'
|
|
223
|
+
address: new oAddress('o://company/sales/analyst'),
|
|
224
|
+
parent: new oAddress('o://company/sales'),
|
|
225
|
+
protocols: ['lead-qualification', 'deal-analysis']
|
|
178
226
|
});
|
|
179
227
|
|
|
180
228
|
// Join the network via leader
|
|
@@ -186,52 +234,77 @@ await agent.use(oAddress.leader(), {
|
|
|
186
234
|
transports: ['webrtc']
|
|
187
235
|
}
|
|
188
236
|
});
|
|
237
|
+
|
|
238
|
+
console.log('Agent successfully joined network');
|
|
239
|
+
// Agent is now discoverable via registry
|
|
189
240
|
```
|
|
190
241
|
|
|
191
|
-
#### Join Request Validation
|
|
242
|
+
#### Join Request Validation {#join-request-validation}
|
|
243
|
+
|
|
192
244
|
Customize validation logic for network access control:
|
|
193
245
|
|
|
194
246
|
```typescript
|
|
247
|
+
import { oLeaderNode } from '@olane/o-leader';
|
|
248
|
+
import { oRequest } from '@olane/o-core';
|
|
249
|
+
|
|
195
250
|
class CustomLeader extends oLeaderNode {
|
|
251
|
+
// Override to implement custom validation
|
|
196
252
|
async validateJoinRequest(request: oRequest): Promise<boolean> {
|
|
197
253
|
const { caller, parent } = request.params;
|
|
198
254
|
|
|
199
|
-
//
|
|
255
|
+
// Example: Check parent authorization
|
|
200
256
|
if (!this.isAuthorizedParent(parent)) {
|
|
201
257
|
throw new Error('Unauthorized parent address');
|
|
202
258
|
}
|
|
203
259
|
|
|
260
|
+
// Example: Verify security requirements
|
|
204
261
|
if (!this.meetsSecurityRequirements(caller)) {
|
|
205
262
|
throw new Error('Agent does not meet security requirements');
|
|
206
263
|
}
|
|
207
264
|
|
|
208
265
|
return true;
|
|
209
266
|
}
|
|
267
|
+
|
|
268
|
+
private isAuthorizedParent(parent: string): boolean {
|
|
269
|
+
// Your authorization logic
|
|
270
|
+
return parent.startsWith('o://company/');
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
private meetsSecurityRequirements(caller: string): boolean {
|
|
274
|
+
// Your security validation logic
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
210
277
|
}
|
|
211
278
|
```
|
|
212
279
|
|
|
213
|
-
### Using the Registry
|
|
280
|
+
### Using the Registry {#using-the-registry}
|
|
281
|
+
|
|
282
|
+
#### Registering Agent Capabilities {#registering-capabilities}
|
|
214
283
|
|
|
215
|
-
#### Registering Agent Capabilities
|
|
216
284
|
```typescript
|
|
217
|
-
|
|
285
|
+
import { oAddress } from '@olane/o-core';
|
|
286
|
+
|
|
287
|
+
// Commit agent to registry with its capabilities
|
|
218
288
|
await leader.use(new oAddress('o://registry'), {
|
|
219
289
|
method: 'commit',
|
|
220
290
|
params: {
|
|
221
|
-
peerId: 'QmXxxx...',
|
|
291
|
+
peerId: 'QmXxxx...', // libp2p peer ID
|
|
222
292
|
address: 'o://company/finance/analyst',
|
|
223
|
-
staticAddress: 'analyst-prod-01',
|
|
224
|
-
protocols: [
|
|
293
|
+
staticAddress: 'analyst-prod-01', // Stable reference
|
|
294
|
+
protocols: [ // Agent capabilities
|
|
225
295
|
'financial-analysis',
|
|
226
296
|
'report-generation',
|
|
227
297
|
'data-visualization'
|
|
228
298
|
],
|
|
229
|
-
transports: ['webrtc', 'websocket']
|
|
299
|
+
transports: ['webrtc', 'websocket'] // Supported transports
|
|
230
300
|
}
|
|
231
301
|
});
|
|
302
|
+
|
|
303
|
+
console.log('Agent registered in registry');
|
|
232
304
|
```
|
|
233
305
|
|
|
234
|
-
#### Searching for Agents
|
|
306
|
+
#### Searching for Agents {#searching-agents}
|
|
307
|
+
|
|
235
308
|
```typescript
|
|
236
309
|
// Find agents by capability
|
|
237
310
|
const analysts = await leader.use(new oAddress('o://registry'), {
|
|
@@ -240,6 +313,7 @@ const analysts = await leader.use(new oAddress('o://registry'), {
|
|
|
240
313
|
protocols: ['financial-analysis']
|
|
241
314
|
}
|
|
242
315
|
});
|
|
316
|
+
console.log(`Found ${analysts.result.length} financial analysts`);
|
|
243
317
|
|
|
244
318
|
// Find agent by address
|
|
245
319
|
const agent = await leader.use(new oAddress('o://registry'), {
|
|
@@ -248,6 +322,7 @@ const agent = await leader.use(new oAddress('o://registry'), {
|
|
|
248
322
|
address: 'o://company/finance/analyst'
|
|
249
323
|
}
|
|
250
324
|
});
|
|
325
|
+
console.log('Found agent:', agent.result[0]);
|
|
251
326
|
|
|
252
327
|
// Find by static address (for stable references)
|
|
253
328
|
const stable = await leader.use(new oAddress('o://registry'), {
|
|
@@ -256,36 +331,55 @@ const stable = await leader.use(new oAddress('o://registry'), {
|
|
|
256
331
|
staticAddress: 'analyst-prod-01'
|
|
257
332
|
}
|
|
258
333
|
});
|
|
334
|
+
console.log('Found stable agent reference');
|
|
259
335
|
```
|
|
260
336
|
|
|
261
|
-
#### Listing All Agents
|
|
337
|
+
#### Listing All Agents {#listing-agents}
|
|
338
|
+
|
|
262
339
|
```typescript
|
|
340
|
+
// Get all registered agents in the network
|
|
263
341
|
const allAgents = await leader.use(new oAddress('o://registry'), {
|
|
264
342
|
method: 'find_all',
|
|
265
343
|
params: {}
|
|
266
344
|
});
|
|
267
345
|
|
|
268
346
|
console.log(`Network has ${allAgents.result.length} active agents`);
|
|
347
|
+
allAgents.result.forEach(agent => {
|
|
348
|
+
console.log(`- ${agent.address} (${agent.protocols.join(', ')})`);
|
|
349
|
+
});
|
|
269
350
|
```
|
|
270
351
|
|
|
271
|
-
### Network Indexing
|
|
352
|
+
### Network Indexing {#network-indexing-usage}
|
|
353
|
+
|
|
354
|
+
#### Triggering Network Index {#trigger-index}
|
|
272
355
|
|
|
273
|
-
#### Triggering Network Index
|
|
274
356
|
```typescript
|
|
275
|
-
|
|
357
|
+
import { oAddress } from '@olane/o-core';
|
|
358
|
+
|
|
359
|
+
// Trigger a full network index
|
|
276
360
|
await leader.use(oAddress.leader(), {
|
|
277
361
|
method: 'index_network',
|
|
278
362
|
params: {}
|
|
279
363
|
});
|
|
280
364
|
|
|
365
|
+
console.log('Network indexing complete');
|
|
281
366
|
// This crawls all registered agents and indexes their capabilities
|
|
282
367
|
```
|
|
283
368
|
|
|
284
|
-
|
|
369
|
+
<Note>
|
|
370
|
+
**Tip**: Run indexing on a schedule (e.g., every 5-10 minutes) or trigger it after significant network changes.
|
|
371
|
+
</Note>
|
|
372
|
+
|
|
373
|
+
#### Custom Indexing Logic {#custom-indexing}
|
|
374
|
+
|
|
285
375
|
Extend the leader to implement custom indexing:
|
|
286
376
|
|
|
287
377
|
```typescript
|
|
378
|
+
import { oLeaderNode } from '@olane/o-leader';
|
|
379
|
+
import { oRequest, oAddress, RestrictedAddresses } from '@olane/o-core';
|
|
380
|
+
|
|
288
381
|
class CustomLeader extends oLeaderNode {
|
|
382
|
+
// Override the default indexing logic
|
|
289
383
|
async _tool_index_network(request: oRequest): Promise<any> {
|
|
290
384
|
// Get all registered nodes
|
|
291
385
|
const nodes = await this.use(
|
|
@@ -293,27 +387,40 @@ class CustomLeader extends oLeaderNode {
|
|
|
293
387
|
{ method: 'find_all', params: {} }
|
|
294
388
|
);
|
|
295
389
|
|
|
390
|
+
console.log(`Indexing ${nodes.result.data.length} nodes`);
|
|
391
|
+
|
|
296
392
|
// Custom indexing per node
|
|
297
393
|
for (const node of nodes.result.data) {
|
|
298
394
|
const capabilities = await this.indexNodeCapabilities(node);
|
|
299
395
|
await this.storeCapabilities(node.address, capabilities);
|
|
300
396
|
}
|
|
301
397
|
|
|
302
|
-
return {
|
|
398
|
+
return {
|
|
399
|
+
message: 'Network indexed with custom logic!',
|
|
400
|
+
nodesIndexed: nodes.result.data.length
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
private async indexNodeCapabilities(node: any) {
|
|
405
|
+
// Your custom capability indexing logic
|
|
406
|
+
return { /* capabilities */ };
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
private async storeCapabilities(address: string, capabilities: any) {
|
|
410
|
+
// Store in your custom storage
|
|
303
411
|
}
|
|
304
412
|
}
|
|
305
413
|
```
|
|
306
414
|
|
|
307
415
|
---
|
|
308
416
|
|
|
309
|
-
##
|
|
417
|
+
## Advanced Topics {#advanced-topics}
|
|
310
418
|
|
|
311
|
-
### Custom Registry Implementations
|
|
419
|
+
### Custom Registry Implementations {#custom-registry}
|
|
312
420
|
|
|
313
|
-
|
|
314
|
-
The default `RegistryMemoryTool` stores registrations in memory, which is great for development but not persistent. For production, implement a persistent registry.
|
|
421
|
+
The default `RegistryMemoryTool` stores registrations in **memory** (great for development but not persistent). For **production**, implement a persistent registry backed by a database.
|
|
315
422
|
|
|
316
|
-
#### Persistent Registry Example
|
|
423
|
+
#### Persistent Registry Example {#persistent-registry-example}
|
|
317
424
|
```typescript
|
|
318
425
|
import { RegistryTool } from '@olane/o-leader';
|
|
319
426
|
import { oRequest } from '@olane/o-core';
|
|
@@ -348,26 +455,45 @@ class PostgresRegistryTool extends RegistryTool {
|
|
|
348
455
|
}
|
|
349
456
|
```
|
|
350
457
|
|
|
351
|
-
#### Using Custom Registry
|
|
458
|
+
#### Using Custom Registry {#using-custom-registry}
|
|
459
|
+
|
|
352
460
|
```typescript
|
|
461
|
+
import { oLeaderNode } from '@olane/o-leader';
|
|
462
|
+
|
|
463
|
+
// Initialize your database connection
|
|
353
464
|
const db = new Database(dbConfig);
|
|
465
|
+
|
|
466
|
+
// Create custom registry instance
|
|
354
467
|
const registry = new PostgresRegistryTool(config, db);
|
|
355
468
|
|
|
469
|
+
// Use custom registry in leader
|
|
356
470
|
const leader = new oLeaderNode({
|
|
357
|
-
|
|
358
|
-
registry: registry
|
|
471
|
+
networkName: 'production-network',
|
|
472
|
+
registry: registry // Use persistent registry instead of memory
|
|
359
473
|
});
|
|
474
|
+
|
|
475
|
+
await leader.start();
|
|
476
|
+
console.log('Leader using persistent registry');
|
|
360
477
|
```
|
|
361
478
|
|
|
362
|
-
|
|
479
|
+
<Check>
|
|
480
|
+
**Production Recommendation**: Always use a persistent registry (PostgreSQL, Redis, MongoDB) for production networks.
|
|
481
|
+
</Check>
|
|
363
482
|
|
|
364
|
-
|
|
365
|
-
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
### Multi-Leader Networks {#multi-leader-networks}
|
|
486
|
+
|
|
487
|
+
#### When to Use Multiple Leaders {#when-multi-leader}
|
|
488
|
+
|
|
489
|
+
Use multiple leaders when you need:
|
|
490
|
+
|
|
491
|
+
- **Geographic Distribution**: Leader per region for low latency
|
|
366
492
|
- **Organizational Boundaries**: Leader per department or team
|
|
367
493
|
- **Fault Tolerance**: Backup leaders for high availability
|
|
368
494
|
- **Scale**: Distribute coordination load across leaders
|
|
369
495
|
|
|
370
|
-
#### Federation Pattern
|
|
496
|
+
#### Federation Pattern {#federation-pattern}
|
|
371
497
|
```typescript
|
|
372
498
|
// Primary leader
|
|
373
499
|
const primaryLeader = new oLeaderNode({
|
|
@@ -392,9 +518,15 @@ const euLeader = new oLeaderNode({
|
|
|
392
518
|
// but can query primary leader for global discovery
|
|
393
519
|
```
|
|
394
520
|
|
|
395
|
-
|
|
521
|
+
<Note>
|
|
522
|
+
**Pattern**: Regional leaders handle local coordination while primary leader maintains global visibility.
|
|
523
|
+
</Note>
|
|
396
524
|
|
|
397
|
-
|
|
525
|
+
---
|
|
526
|
+
|
|
527
|
+
### Security and Access Control {#security-access-control}
|
|
528
|
+
|
|
529
|
+
#### Network Access Policies {#access-policies}
|
|
398
530
|
```typescript
|
|
399
531
|
class SecureLeader extends oLeaderNode {
|
|
400
532
|
private allowedNetworks = new Set(['o://company/*']);
|
|
@@ -427,9 +559,14 @@ class SecureLeader extends oLeaderNode {
|
|
|
427
559
|
}
|
|
428
560
|
```
|
|
429
561
|
|
|
430
|
-
#### Registry Access Control
|
|
562
|
+
#### Registry Access Control {#registry-access-control}
|
|
563
|
+
|
|
431
564
|
```typescript
|
|
565
|
+
import { RegistryTool } from '@olane/o-leader';
|
|
566
|
+
import { oRequest } from '@olane/o-core';
|
|
567
|
+
|
|
432
568
|
class ProtectedRegistry extends RegistryTool {
|
|
569
|
+
// Override search to add permission checks
|
|
433
570
|
async _tool_search(request: oRequest): Promise<any> {
|
|
434
571
|
// Verify requesting agent has permission
|
|
435
572
|
const requester = request.metadata.caller;
|
|
@@ -441,12 +578,29 @@ class ProtectedRegistry extends RegistryTool {
|
|
|
441
578
|
const results = await this.performSearch(request.params);
|
|
442
579
|
return this.filterByPermissions(results, requester);
|
|
443
580
|
}
|
|
581
|
+
|
|
582
|
+
private canSearch(caller: string): boolean {
|
|
583
|
+
// Your permission logic
|
|
584
|
+
return caller.startsWith('o://company/');
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
private filterByPermissions(results: any[], caller: string): any[] {
|
|
588
|
+
// Filter results based on caller permissions
|
|
589
|
+
return results.filter(agent => this.hasAccessTo(caller, agent));
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
private hasAccessTo(caller: string, agent: any): boolean {
|
|
593
|
+
// Your access control logic
|
|
594
|
+
return true;
|
|
595
|
+
}
|
|
444
596
|
}
|
|
445
597
|
```
|
|
446
598
|
|
|
447
|
-
|
|
599
|
+
---
|
|
600
|
+
|
|
601
|
+
### Network Health Monitoring {#network-health}
|
|
448
602
|
|
|
449
|
-
#### Health Check Implementation
|
|
603
|
+
#### Health Check Implementation {#health-check-implementation}
|
|
450
604
|
```typescript
|
|
451
605
|
class MonitoredLeader extends oLeaderNode {
|
|
452
606
|
async getNetworkHealth(): Promise<NetworkHealth> {
|
|
@@ -477,9 +631,11 @@ class MonitoredLeader extends oLeaderNode {
|
|
|
477
631
|
}
|
|
478
632
|
```
|
|
479
633
|
|
|
480
|
-
|
|
634
|
+
---
|
|
635
|
+
|
|
636
|
+
### Performance Optimization {#performance-optimization}
|
|
481
637
|
|
|
482
|
-
#### Registry Caching
|
|
638
|
+
#### Registry Caching {#registry-caching}
|
|
483
639
|
```typescript
|
|
484
640
|
class CachedRegistry extends RegistryTool {
|
|
485
641
|
private cache = new Map<string, CacheEntry>();
|
|
@@ -541,12 +697,13 @@ class OptimizedRegistry extends RegistryMemoryTool {
|
|
|
541
697
|
|
|
542
698
|
---
|
|
543
699
|
|
|
544
|
-
##
|
|
700
|
+
## Best Practices {#best-practices}
|
|
545
701
|
|
|
546
|
-
### Network Design Patterns
|
|
702
|
+
### Network Design Patterns {#network-design-patterns}
|
|
547
703
|
|
|
548
|
-
#### 1. Hierarchical Organization
|
|
549
|
-
|
|
704
|
+
#### 1. Hierarchical Organization {#hierarchical-organization}
|
|
705
|
+
|
|
706
|
+
Structure your network to **mirror your business domains**:
|
|
550
707
|
```
|
|
551
708
|
o://leader # Root coordinator
|
|
552
709
|
└── o://company # Company root
|
|
@@ -558,38 +715,51 @@ o://leader # Root coordinator
|
|
|
558
715
|
└── o://company/engineering/frontend
|
|
559
716
|
```
|
|
560
717
|
|
|
561
|
-
#### 2. Capability-Based Discovery
|
|
562
|
-
|
|
718
|
+
#### 2. Capability-Based Discovery {#capability-based-discovery}
|
|
719
|
+
|
|
720
|
+
Register agents with **clear, specific capabilities**:
|
|
721
|
+
|
|
563
722
|
```typescript
|
|
564
|
-
// Good: Specific capabilities
|
|
723
|
+
// ✅ Good: Specific capabilities
|
|
565
724
|
protocols: ['payment-processing', 'stripe-api', 'refund-handling']
|
|
566
725
|
|
|
567
|
-
// Avoid: Generic capabilities
|
|
726
|
+
// ❌ Avoid: Generic capabilities
|
|
568
727
|
protocols: ['payments', 'api', 'processing']
|
|
569
728
|
```
|
|
570
729
|
|
|
571
|
-
#### 3. Static Addresses for Stability
|
|
572
|
-
|
|
730
|
+
#### 3. Static Addresses for Stability {#static-addresses}
|
|
731
|
+
|
|
732
|
+
Use **static addresses** for production agents that need stable references:
|
|
733
|
+
|
|
573
734
|
```typescript
|
|
735
|
+
// Register agent with both dynamic and static addresses
|
|
574
736
|
{
|
|
575
|
-
address: 'o://company/finance/analyst', // Dynamic
|
|
576
|
-
staticAddress: 'analyst-prod-01' // Stable reference
|
|
737
|
+
address: 'o://company/finance/analyst', // Dynamic (changes with restarts)
|
|
738
|
+
staticAddress: 'analyst-prod-01' // Stable (consistent reference)
|
|
577
739
|
}
|
|
578
740
|
```
|
|
579
741
|
|
|
580
|
-
|
|
742
|
+
<Check>
|
|
743
|
+
**Why?** Static addresses allow reliable references even when agent instances change.
|
|
744
|
+
</Check>
|
|
745
|
+
|
|
746
|
+
---
|
|
747
|
+
|
|
748
|
+
### Operational Guidelines {#operational-guidelines}
|
|
749
|
+
|
|
750
|
+
#### Registry Maintenance {#registry-maintenance}
|
|
581
751
|
|
|
582
|
-
#### Registry Maintenance
|
|
583
752
|
- **TTL Strategy**: Implement time-to-live for registry entries to auto-cleanup stale agents
|
|
584
753
|
- **Health Checks**: Periodically verify registered agents are still responsive
|
|
585
754
|
- **Cleanup**: Remove inactive agents to keep registry performant
|
|
586
755
|
|
|
587
|
-
#### Network Indexing
|
|
756
|
+
#### Network Indexing {#indexing-guidelines}
|
|
757
|
+
|
|
588
758
|
- **Scheduled Indexing**: Run network indexing on a schedule (e.g., every 5 minutes)
|
|
589
759
|
- **Event-Driven**: Trigger indexing when significant network changes occur
|
|
590
760
|
- **Incremental**: For large networks, implement incremental indexing
|
|
591
761
|
|
|
592
|
-
#### Monitoring and Observability
|
|
762
|
+
#### Monitoring and Observability {#monitoring-observability}
|
|
593
763
|
```typescript
|
|
594
764
|
// Log key network events
|
|
595
765
|
leader.on('agent:joined', (agent) => {
|
|
@@ -616,22 +786,38 @@ const metrics = {
|
|
|
616
786
|
};
|
|
617
787
|
```
|
|
618
788
|
|
|
619
|
-
### Security Best Practices
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
789
|
+
### Security Best Practices {#security-best-practices}
|
|
790
|
+
|
|
791
|
+
Follow these security guidelines for production networks:
|
|
792
|
+
|
|
793
|
+
<Steps>
|
|
794
|
+
<Step title="Validate Join Requests">
|
|
795
|
+
Always implement custom `validateJoinRequest()` logic with business rules
|
|
796
|
+
</Step>
|
|
797
|
+
<Step title="Use Authentication">
|
|
798
|
+
Require authentication tokens for all join requests
|
|
799
|
+
</Step>
|
|
800
|
+
<Step title="Rate Limiting">
|
|
801
|
+
Implement rate limiting on join requests to prevent abuse
|
|
802
|
+
</Step>
|
|
803
|
+
<Step title="Permission-Based Access">
|
|
804
|
+
Filter registry results based on caller permissions
|
|
805
|
+
</Step>
|
|
806
|
+
<Step title="Monitor Patterns">
|
|
807
|
+
Watch for unusual patterns (rapid joins, suspicious addresses)
|
|
808
|
+
</Step>
|
|
809
|
+
<Step title="Encrypted Transports">
|
|
810
|
+
Prefer WebRTC over WebSocket for sensitive data
|
|
811
|
+
</Step>
|
|
812
|
+
</Steps>
|
|
627
813
|
|
|
628
814
|
---
|
|
629
815
|
|
|
630
|
-
##
|
|
816
|
+
## Troubleshooting {#troubleshooting}
|
|
631
817
|
|
|
632
|
-
### Common Issues
|
|
818
|
+
### Common Issues {#common-issues}
|
|
633
819
|
|
|
634
|
-
#### Agents Can't Join Network
|
|
820
|
+
#### Agents Can't Join Network {#agents-cant-join}
|
|
635
821
|
**Symptoms**: Join requests fail or timeout
|
|
636
822
|
**Solutions**:
|
|
637
823
|
- Verify leader is running and accessible
|
|
@@ -639,38 +825,48 @@ const metrics = {
|
|
|
639
825
|
- Review `validateJoinRequest` logic for rejections
|
|
640
826
|
- Ensure parent address exists in hierarchy
|
|
641
827
|
|
|
642
|
-
#### Registry Search Returns No Results
|
|
828
|
+
#### Registry Search Returns No Results {#registry-no-results}
|
|
829
|
+
|
|
643
830
|
**Symptoms**: Search returns empty array when agents should exist
|
|
831
|
+
|
|
644
832
|
**Solutions**:
|
|
645
833
|
- Verify agents committed to registry successfully
|
|
646
834
|
- Check search parameters match registered protocols/addresses
|
|
647
835
|
- Inspect registry state: `await registry.find_all()`
|
|
648
836
|
- Look for typos in protocol names or addresses
|
|
649
837
|
|
|
650
|
-
#### Network Indexing Fails
|
|
838
|
+
#### Network Indexing Fails {#indexing-fails}
|
|
839
|
+
|
|
651
840
|
**Symptoms**: Index operation throws errors or never completes
|
|
841
|
+
|
|
652
842
|
**Solutions**:
|
|
653
843
|
- Check for agents that are unresponsive or disconnected
|
|
654
844
|
- Implement timeout logic for indexing individual agents
|
|
655
845
|
- Add error handling to continue indexing after failures
|
|
656
846
|
- Monitor agent count vs indexed count
|
|
657
847
|
|
|
658
|
-
#### Memory Issues with Large Networks
|
|
848
|
+
#### Memory Issues with Large Networks {#memory-issues}
|
|
849
|
+
|
|
659
850
|
**Symptoms**: Registry memory grows unbounded
|
|
851
|
+
|
|
660
852
|
**Solutions**:
|
|
661
|
-
- Implement persistent registry instead of in-memory
|
|
662
|
-
- Add TTL for registry entries
|
|
663
|
-
- Implement cleanup for disconnected agents
|
|
664
|
-
- Consider registry sharding for very large networks
|
|
853
|
+
- Implement **persistent registry** instead of in-memory
|
|
854
|
+
- Add **TTL** for registry entries
|
|
855
|
+
- Implement **cleanup** for disconnected agents
|
|
856
|
+
- Consider **registry sharding** for very large networks
|
|
857
|
+
|
|
858
|
+
---
|
|
859
|
+
|
|
860
|
+
### Debugging Tips {#debugging-tips}
|
|
665
861
|
|
|
666
|
-
|
|
862
|
+
#### Enable Debug Logging {#debug-logging}
|
|
667
863
|
|
|
668
|
-
#### Enable Debug Logging
|
|
669
864
|
```bash
|
|
865
|
+
# Enable debug output for o-leader and o-protocol
|
|
670
866
|
DEBUG=o-protocol:*,o-leader:* node your-app.js
|
|
671
867
|
```
|
|
672
868
|
|
|
673
|
-
#### Inspect Registry State
|
|
869
|
+
#### Inspect Registry State {#inspect-registry}
|
|
674
870
|
```typescript
|
|
675
871
|
const allAgents = await leader.use(
|
|
676
872
|
new oAddress('o://registry'),
|
|
@@ -702,31 +898,37 @@ class DebugLeader extends oLeaderNode {
|
|
|
702
898
|
|
|
703
899
|
---
|
|
704
900
|
|
|
705
|
-
##
|
|
901
|
+
## API Reference {#api-reference}
|
|
902
|
+
|
|
903
|
+
### oLeaderNode {#oleadernode}
|
|
904
|
+
|
|
905
|
+
The main class for creating a leader node.
|
|
706
906
|
|
|
707
|
-
|
|
907
|
+
#### Constructor {#oleadernode-constructor}
|
|
708
908
|
|
|
709
|
-
#### Constructor
|
|
710
909
|
```typescript
|
|
711
910
|
constructor(config: oNodeToolConfig)
|
|
712
911
|
```
|
|
713
912
|
|
|
714
913
|
**Parameters:**
|
|
715
|
-
- `config.networkName` (string): Network identifier
|
|
716
|
-
- `config.address` (oAddress): Leader node address (default: `o://leader`)
|
|
717
|
-
- `config.type` (NodeType): Must be `NodeType.LEADER`
|
|
718
|
-
- `config.methods` (object): Custom methods to expose
|
|
719
|
-
- Other oNodeToolConfig parameters
|
|
720
914
|
|
|
721
|
-
|
|
915
|
+
| Parameter | Type | Required | Description |
|
|
916
|
+
|-----------|------|----------|-------------|
|
|
917
|
+
| `config.networkName` | string | Yes | Network identifier |
|
|
918
|
+
| `config.address` | oAddress | No | Leader node address (default: `o://leader`) |
|
|
919
|
+
| `config.type` | NodeType | No | Must be `NodeType.LEADER` |
|
|
920
|
+
| `config.methods` | object | No | Custom methods to expose |
|
|
921
|
+
|
|
922
|
+
#### Methods {#oleadernode-methods}
|
|
923
|
+
|
|
924
|
+
##### `validateJoinRequest(request: oRequest): Promise<boolean>` {#validate-join}
|
|
722
925
|
|
|
723
|
-
##### `validateJoinRequest(request: oRequest): Promise<boolean>`
|
|
724
926
|
Override to implement custom join validation logic.
|
|
725
927
|
|
|
726
928
|
**Parameters:**
|
|
727
|
-
- `request
|
|
929
|
+
- `request` (oRequest): Join request containing caller, parent, transports
|
|
728
930
|
|
|
729
|
-
**Returns:** Promise
|
|
931
|
+
**Returns:** `Promise<boolean>` - Resolves to `true` if valid, throws error if invalid
|
|
730
932
|
|
|
731
933
|
**Example:**
|
|
732
934
|
```typescript
|
|
@@ -738,7 +940,8 @@ async validateJoinRequest(request: oRequest): Promise<boolean> {
|
|
|
738
940
|
}
|
|
739
941
|
```
|
|
740
942
|
|
|
741
|
-
##### `_tool_join_network(request: oRequest): Promise<any>`
|
|
943
|
+
##### `_tool_join_network(request: oRequest): Promise<any>` {#tool-join-network}
|
|
944
|
+
|
|
742
945
|
Processes agent join requests.
|
|
743
946
|
|
|
744
947
|
**Request Parameters:**
|
|
@@ -746,38 +949,49 @@ Processes agent join requests.
|
|
|
746
949
|
- `parent` (string): Parent address in hierarchy
|
|
747
950
|
- `transports` (string[]): Available transport protocols
|
|
748
951
|
|
|
749
|
-
**Returns:** Success message
|
|
952
|
+
**Returns:** `Promise<any>` - Success message
|
|
953
|
+
|
|
954
|
+
##### `_tool_index_network(request: oRequest): Promise<any>` {#tool-index-network}
|
|
750
955
|
|
|
751
|
-
##### `_tool_index_network(request: oRequest): Promise<any>`
|
|
752
956
|
Indexes all registered agents in the network.
|
|
753
957
|
|
|
754
|
-
**Returns:** Index completion status
|
|
958
|
+
**Returns:** `Promise<any>` - Index completion status
|
|
959
|
+
|
|
960
|
+
##### `_tool_save_plan(request: oRequest): Promise<any>` {#tool-save-plan}
|
|
755
961
|
|
|
756
|
-
##### `_tool_save_plan(request: oRequest): Promise<any>`
|
|
757
962
|
Saves network coordination plans.
|
|
758
963
|
|
|
759
964
|
**Request Parameters:**
|
|
760
965
|
- `plan` (object): Plan to save
|
|
761
966
|
|
|
967
|
+
**Returns:** `Promise<any>` - Success indicator
|
|
968
|
+
|
|
762
969
|
---
|
|
763
970
|
|
|
764
|
-
### RegistryTool
|
|
971
|
+
### RegistryTool {#registrytool}
|
|
972
|
+
|
|
973
|
+
Abstract base class for registry implementations.
|
|
974
|
+
|
|
975
|
+
#### Abstract Methods {#registrytool-methods}
|
|
765
976
|
|
|
766
|
-
|
|
977
|
+
##### `_tool_commit(request: oRequest): Promise<ToolResult>` {#registry-commit}
|
|
767
978
|
|
|
768
|
-
##### `_tool_commit(request: oRequest): Promise<ToolResult>`
|
|
769
979
|
Register an agent in the registry.
|
|
770
980
|
|
|
771
981
|
**Request Parameters:**
|
|
772
|
-
- `peerId` (string, required): Agent's peer ID
|
|
773
|
-
- `address` (string): Agent's o:// address
|
|
774
|
-
- `staticAddress` (string): Stable reference address
|
|
775
|
-
- `protocols` (string[]): Capabilities/protocols
|
|
776
|
-
- `transports` (string[]): Transport protocols
|
|
777
982
|
|
|
778
|
-
|
|
983
|
+
| Parameter | Type | Required | Description |
|
|
984
|
+
|-----------|------|----------|-------------|
|
|
985
|
+
| `peerId` | string | Yes | Agent's peer ID |
|
|
986
|
+
| `address` | string | No | Agent's o:// address |
|
|
987
|
+
| `staticAddress` | string | No | Stable reference address |
|
|
988
|
+
| `protocols` | string[] | No | Capabilities/protocols |
|
|
989
|
+
| `transports` | string[] | No | Transport protocols |
|
|
990
|
+
|
|
991
|
+
**Returns:** `Promise<ToolResult>` - Success indicator
|
|
992
|
+
|
|
993
|
+
##### `_tool_search(request: oRequest): Promise<ToolResult>` {#registry-search}
|
|
779
994
|
|
|
780
|
-
##### `_tool_search(request: oRequest): Promise<ToolResult>`
|
|
781
995
|
Search for agents matching criteria.
|
|
782
996
|
|
|
783
997
|
**Request Parameters:**
|
|
@@ -785,42 +999,50 @@ Search for agents matching criteria.
|
|
|
785
999
|
- `staticAddress` (string, optional): Search by static address
|
|
786
1000
|
- `protocols` (string[], optional): Search by protocols
|
|
787
1001
|
|
|
788
|
-
**Returns:** Array of matching agents
|
|
1002
|
+
**Returns:** `Promise<ToolResult>` - Array of matching agents
|
|
1003
|
+
|
|
1004
|
+
##### `_tool_find_all(request: oRequest): Promise<ToolResult>` {#registry-find-all}
|
|
789
1005
|
|
|
790
|
-
##### `_tool_find_all(request: oRequest): Promise<ToolResult>`
|
|
791
1006
|
List all registered agents.
|
|
792
1007
|
|
|
793
|
-
**Returns:** Array of all registered agents
|
|
1008
|
+
**Returns:** `Promise<ToolResult>` - Array of all registered agents
|
|
1009
|
+
|
|
1010
|
+
##### `_tool_remove(request: oRequest): Promise<ToolResult>` {#registry-remove}
|
|
794
1011
|
|
|
795
|
-
##### `_tool_remove(request: oRequest): Promise<ToolResult>`
|
|
796
1012
|
Remove an agent from registry.
|
|
797
1013
|
|
|
798
1014
|
**Request Parameters:**
|
|
799
1015
|
- `peerId` (string): Peer ID of agent to remove
|
|
800
1016
|
|
|
801
|
-
**Returns:** Success indicator
|
|
1017
|
+
**Returns:** `Promise<ToolResult>` - Success indicator
|
|
802
1018
|
|
|
803
1019
|
---
|
|
804
1020
|
|
|
805
|
-
### RegistryMemoryTool
|
|
1021
|
+
### RegistryMemoryTool {#registrymemorytool}
|
|
806
1022
|
|
|
807
|
-
Concrete implementation of RegistryTool using in-memory storage.
|
|
1023
|
+
Concrete implementation of `RegistryTool` using in-memory storage.
|
|
808
1024
|
|
|
809
1025
|
**Usage:**
|
|
810
1026
|
```typescript
|
|
1027
|
+
import { RegistryMemoryTool } from '@olane/o-leader';
|
|
1028
|
+
|
|
811
1029
|
const registry = new RegistryMemoryTool(config);
|
|
812
1030
|
```
|
|
813
1031
|
|
|
814
|
-
**
|
|
815
|
-
- Uses Map data structures for fast lookups
|
|
816
|
-
- Protocol indexing for efficient searches
|
|
817
|
-
- Not persistent across restarts
|
|
1032
|
+
**Characteristics:**
|
|
1033
|
+
- Uses Map data structures for **fast lookups**
|
|
1034
|
+
- Protocol indexing for **efficient searches**
|
|
1035
|
+
- **Not persistent** across restarts (use for development only)
|
|
1036
|
+
|
|
1037
|
+
<Warning>
|
|
1038
|
+
**Production Warning**: Use a persistent registry (PostgreSQL, Redis) for production networks.
|
|
1039
|
+
</Warning>
|
|
818
1040
|
|
|
819
1041
|
---
|
|
820
1042
|
|
|
821
|
-
##
|
|
1043
|
+
## Examples {#examples}
|
|
822
1044
|
|
|
823
|
-
### Example 1: Basic Multi-Agent Network
|
|
1045
|
+
### Example 1: Basic Multi-Agent Network {#example-basic-network}
|
|
824
1046
|
```typescript
|
|
825
1047
|
// examples/basic-network.ts
|
|
826
1048
|
import { oLeaderNode, RegistryMemoryTool } from '@olane/o-leader';
|
|
@@ -874,7 +1096,7 @@ async function main() {
|
|
|
874
1096
|
}
|
|
875
1097
|
```
|
|
876
1098
|
|
|
877
|
-
### Example 2:
|
|
1099
|
+
### Example 2: Secure Network with Validation {#example-secure-network}
|
|
878
1100
|
```typescript
|
|
879
1101
|
// examples/secure-network.ts
|
|
880
1102
|
import { oLeaderNode } from '@olane/o-leader';
|
|
@@ -916,7 +1138,7 @@ const leader = new SecureLeader({
|
|
|
916
1138
|
await leader.start();
|
|
917
1139
|
```
|
|
918
1140
|
|
|
919
|
-
### Example 3: Capability Discovery
|
|
1141
|
+
### Example 3: Capability Discovery {#example-capability-discovery}
|
|
920
1142
|
```typescript
|
|
921
1143
|
// examples/capability-discovery.ts
|
|
922
1144
|
import { oAddress } from '@olane/o-core';
|
|
@@ -946,7 +1168,7 @@ async function findAnalysisAgents(leader: oLeaderNode) {
|
|
|
946
1168
|
}
|
|
947
1169
|
```
|
|
948
1170
|
|
|
949
|
-
### Example 4: Network Health Dashboard
|
|
1171
|
+
### Example 4: Network Health Dashboard {#example-health-dashboard}
|
|
950
1172
|
```typescript
|
|
951
1173
|
// examples/health-dashboard.ts
|
|
952
1174
|
import { oLeaderNode, RegistryMemoryTool } from '@olane/o-leader';
|
|
@@ -996,11 +1218,11 @@ class HealthMonitorLeader extends oLeaderNode {
|
|
|
996
1218
|
|
|
997
1219
|
---
|
|
998
1220
|
|
|
999
|
-
##
|
|
1221
|
+
## Migration Guide {#migration-guide}
|
|
1000
1222
|
|
|
1001
|
-
### From Manual Coordination to o-leader
|
|
1223
|
+
### From Manual Coordination to o-leader {#migration-manual-to-leader}
|
|
1002
1224
|
|
|
1003
|
-
#### Before: Manual Agent Management
|
|
1225
|
+
#### Before: Manual Agent Management {#before-manual}
|
|
1004
1226
|
```typescript
|
|
1005
1227
|
// Manually tracking agents
|
|
1006
1228
|
const agents = {
|
|
@@ -1018,7 +1240,7 @@ function findAgent(capability) {
|
|
|
1018
1240
|
}
|
|
1019
1241
|
```
|
|
1020
1242
|
|
|
1021
|
-
#### After: With o-leader
|
|
1243
|
+
#### After: With o-leader {#after-with-leader}
|
|
1022
1244
|
```typescript
|
|
1023
1245
|
// Automatic registration and discovery
|
|
1024
1246
|
const leader = new oLeaderNode({ networkName: 'agents' });
|
|
@@ -1036,9 +1258,9 @@ const agents = await leader.use(new oAddress('o://registry'), {
|
|
|
1036
1258
|
});
|
|
1037
1259
|
```
|
|
1038
1260
|
|
|
1039
|
-
### From Other Frameworks
|
|
1261
|
+
### From Other Frameworks {#migration-from-frameworks}
|
|
1040
1262
|
|
|
1041
|
-
#### From LangGraph
|
|
1263
|
+
#### From LangGraph {#migration-from-langgraph}
|
|
1042
1264
|
LangGraph requires explicit graph definitions. With o-leader, agents discover each other:
|
|
1043
1265
|
|
|
1044
1266
|
```typescript
|
|
@@ -1054,7 +1276,7 @@ const leader = new oLeaderNode({ networkName: 'agents' });
|
|
|
1054
1276
|
// No pre-defined connections needed
|
|
1055
1277
|
```
|
|
1056
1278
|
|
|
1057
|
-
#### From CrewAI
|
|
1279
|
+
#### From CrewAI {#migration-from-crewai}
|
|
1058
1280
|
CrewAI uses explicit crew definitions. o-leader enables dynamic crews:
|
|
1059
1281
|
|
|
1060
1282
|
```typescript
|
|
@@ -1074,91 +1296,135 @@ const agents = await leader.use(new oAddress('o://registry'), {
|
|
|
1074
1296
|
|
|
1075
1297
|
---
|
|
1076
1298
|
|
|
1077
|
-
##
|
|
1299
|
+
## FAQ {#faq}
|
|
1078
1300
|
|
|
1079
|
-
### General Questions
|
|
1301
|
+
### General Questions {#faq-general}
|
|
1080
1302
|
|
|
1081
|
-
|
|
1082
|
-
|
|
1303
|
+
<AccordionGroup>
|
|
1304
|
+
<Accordion title="Do I need a leader node for every Olane OS network?">
|
|
1305
|
+
Yes, every network needs at least one leader node. It serves as the **entry point** and **coordination hub** for the network.
|
|
1306
|
+
</Accordion>
|
|
1083
1307
|
|
|
1084
|
-
|
|
1085
|
-
|
|
1308
|
+
<Accordion title="Can I have multiple leader nodes?">
|
|
1309
|
+
Yes, for large or distributed networks, you can implement a **federation pattern** with regional leaders. See [Multi-Leader Networks](#multi-leader-networks).
|
|
1310
|
+
</Accordion>
|
|
1086
1311
|
|
|
1087
|
-
|
|
1088
|
-
|
|
1312
|
+
<Accordion title="Is the registry required?">
|
|
1313
|
+
The registry is **built into** the leader node and is essential for agent discovery. You cannot run a leader without a registry.
|
|
1314
|
+
</Accordion>
|
|
1089
1315
|
|
|
1090
|
-
|
|
1091
|
-
|
|
1316
|
+
<Accordion title="What happens if the leader node goes down?">
|
|
1317
|
+
Existing agent connections remain active, but **new agents cannot join**. Implement leader failover for high availability.
|
|
1318
|
+
</Accordion>
|
|
1319
|
+
</AccordionGroup>
|
|
1092
1320
|
|
|
1093
|
-
### Technical Questions
|
|
1321
|
+
### Technical Questions {#faq-technical}
|
|
1094
1322
|
|
|
1095
|
-
|
|
1096
|
-
|
|
1323
|
+
<AccordionGroup>
|
|
1324
|
+
<Accordion title="How does registry search performance scale?">
|
|
1325
|
+
In-memory registry is **O(n)** for searches. For large networks (1000+ agents), implement **indexed** or **database-backed** registries.
|
|
1326
|
+
</Accordion>
|
|
1097
1327
|
|
|
1098
|
-
|
|
1099
|
-
|
|
1328
|
+
<Accordion title="Can I customize the registry implementation?">
|
|
1329
|
+
Yes, extend `RegistryTool` to implement custom storage backends (PostgreSQL, Redis, MongoDB, etc.). See [Custom Registry Implementations](#custom-registry).
|
|
1330
|
+
</Accordion>
|
|
1100
1331
|
|
|
1101
|
-
|
|
1102
|
-
|
|
1332
|
+
<Accordion title="What transports does the leader support?">
|
|
1333
|
+
The leader supports all **libp2p transports**: WebRTC, WebSocket, TCP, QUIC, etc.
|
|
1334
|
+
</Accordion>
|
|
1103
1335
|
|
|
1104
|
-
|
|
1105
|
-
|
|
1336
|
+
<Accordion title="How do I handle registry cleanup?">
|
|
1337
|
+
Implement **TTL logic** in your registry and **periodic cleanup** of disconnected agents. See [Registry Maintenance](#registry-maintenance).
|
|
1338
|
+
</Accordion>
|
|
1339
|
+
</AccordionGroup>
|
|
1106
1340
|
|
|
1107
|
-
### Operational Questions
|
|
1341
|
+
### Operational Questions {#faq-operational}
|
|
1108
1342
|
|
|
1109
|
-
|
|
1110
|
-
|
|
1343
|
+
<AccordionGroup>
|
|
1344
|
+
<Accordion title="How often should I run network indexing?">
|
|
1345
|
+
Depends on network dynamics:
|
|
1346
|
+
- **Stable networks**: Every 5-10 minutes
|
|
1347
|
+
- **Dynamic networks**: Event-driven indexing
|
|
1348
|
+
- **Large networks**: Incremental indexing
|
|
1349
|
+
</Accordion>
|
|
1111
1350
|
|
|
1112
|
-
|
|
1113
|
-
|
|
1351
|
+
<Accordion title="What's the recommended registry backend for production?">
|
|
1352
|
+
For production, use a **persistent registry** (PostgreSQL, Redis, MongoDB) instead of in-memory. See [Persistent Registry Example](#persistent-registry-example).
|
|
1353
|
+
</Accordion>
|
|
1114
1354
|
|
|
1115
|
-
|
|
1116
|
-
|
|
1355
|
+
<Accordion title="How do I monitor leader health?">
|
|
1356
|
+
Implement **health check endpoints** and monitoring using your observability tools. See [Network Health Monitoring](#network-health).
|
|
1357
|
+
</Accordion>
|
|
1117
1358
|
|
|
1118
|
-
|
|
1119
|
-
|
|
1359
|
+
<Accordion title="Can agents join from different networks?">
|
|
1360
|
+
Yes, as long as they can **reach the leader node** and **pass validation**.
|
|
1361
|
+
</Accordion>
|
|
1362
|
+
</AccordionGroup>
|
|
1120
1363
|
|
|
1121
1364
|
---
|
|
1122
1365
|
|
|
1123
|
-
##
|
|
1124
|
-
|
|
1125
|
-
### Documentation
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1366
|
+
## Support and Resources {#support-resources}
|
|
1367
|
+
|
|
1368
|
+
### Documentation {#documentation-links}
|
|
1369
|
+
|
|
1370
|
+
<CardGroup cols={2}>
|
|
1371
|
+
<Card title="Olane OS Overview" icon="home" href="/README.md">
|
|
1372
|
+
Learn about Olane OS architecture
|
|
1373
|
+
</Card>
|
|
1374
|
+
<Card title="o-core" icon="gear" href="/packages/o-core/README.md">
|
|
1375
|
+
Core protocol and addressing
|
|
1376
|
+
</Card>
|
|
1377
|
+
<Card title="o-node" icon="server" href="/packages/o-node/README.md">
|
|
1378
|
+
Build agent nodes
|
|
1379
|
+
</Card>
|
|
1380
|
+
<Card title="o-lane" icon="brain" href="/packages/o-lane/README.md">
|
|
1381
|
+
Add intelligence to nodes
|
|
1382
|
+
</Card>
|
|
1383
|
+
</CardGroup>
|
|
1384
|
+
|
|
1385
|
+
### Examples {#example-projects}
|
|
1386
|
+
|
|
1387
|
+
- [Basic Network Setup](/examples/basic-network) - Simple multi-agent network
|
|
1388
|
+
- [Secure Network](/examples/secure-network) - Custom validation and access control
|
|
1389
|
+
- [Multi-Region Federation](/examples/multi-region) - Distributed leader pattern
|
|
1390
|
+
- [Health Monitoring](/examples/health-monitoring) - Network observability
|
|
1391
|
+
|
|
1392
|
+
### Community {#community}
|
|
1393
|
+
|
|
1394
|
+
<CardGroup cols={3}>
|
|
1395
|
+
<Card title="GitHub Issues" icon="github" href="https://github.com/olane-labs/olane/issues">
|
|
1396
|
+
Report bugs or request features
|
|
1397
|
+
</Card>
|
|
1398
|
+
<Card title="Discussions" icon="comments" href="https://github.com/olane-labs/olane/discussions">
|
|
1399
|
+
Ask questions and share ideas
|
|
1400
|
+
</Card>
|
|
1401
|
+
<Card title="Discord" icon="discord" href="https://discord.gg/olane">
|
|
1402
|
+
Join our community
|
|
1403
|
+
</Card>
|
|
1404
|
+
</CardGroup>
|
|
1405
|
+
|
|
1406
|
+
### Commercial Support {#commercial-support}
|
|
1130
1407
|
|
|
1131
|
-
### Examples
|
|
1132
|
-
- [Basic Network Setup](/examples/basic-network)
|
|
1133
|
-
- [Secure Network](/examples/secure-network)
|
|
1134
|
-
- [Multi-Region Federation](/examples/multi-region)
|
|
1135
|
-
- [Health Monitoring](/examples/health-monitoring)
|
|
1136
|
-
|
|
1137
|
-
### Community
|
|
1138
|
-
- GitHub Issues: [Report bugs or request features](https://github.com/olane-labs/olane/issues)
|
|
1139
|
-
- Discussions: [Ask questions and share ideas](https://github.com/olane-labs/olane/discussions)
|
|
1140
|
-
- Discord: [Join our community](https://discord.gg/olane)
|
|
1141
|
-
|
|
1142
|
-
### Commercial Support
|
|
1143
1408
|
For enterprise support, custom implementations, or consulting:
|
|
1144
|
-
- Email
|
|
1145
|
-
- Website
|
|
1409
|
+
- **Email**: support@olane.io
|
|
1410
|
+
- **Website**: [olane.io/enterprise](https://olane.io/enterprise)
|
|
1146
1411
|
|
|
1147
1412
|
---
|
|
1148
1413
|
|
|
1149
|
-
##
|
|
1414
|
+
## Contributing {#contributing}
|
|
1150
1415
|
|
|
1151
1416
|
We welcome contributions! See [CONTRIBUTING.md](../../CONTRIBUTING.md) for guidelines.
|
|
1152
1417
|
|
|
1153
|
-
### Areas for Contribution
|
|
1154
|
-
|
|
1155
|
-
-
|
|
1156
|
-
-
|
|
1157
|
-
-
|
|
1158
|
-
-
|
|
1418
|
+
### Areas for Contribution {#contribution-areas}
|
|
1419
|
+
|
|
1420
|
+
- **Registry Backends**: PostgreSQL, Redis, MongoDB implementations
|
|
1421
|
+
- **Performance**: Optimization and scaling improvements
|
|
1422
|
+
- **Security**: Enhanced validation and access control
|
|
1423
|
+
- **Documentation**: Guides, tutorials, and examples
|
|
1424
|
+
- **Examples**: Real-world use cases and patterns
|
|
1159
1425
|
|
|
1160
1426
|
---
|
|
1161
1427
|
|
|
1162
|
-
## License
|
|
1428
|
+
## License {#license}
|
|
1163
1429
|
|
|
1164
1430
|
ISC License - see [LICENSE](../../LICENSE) for details.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"leader.node.d.ts","sourceRoot":"","sources":["../../src/leader.node.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,QAAQ,EAGT,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,
|
|
1
|
+
{"version":3,"file":"leader.node.d.ts","sourceRoot":"","sources":["../../src/leader.node.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,QAAQ,EAGT,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAmB,MAAM,eAAe,CAAC;AAIjE,qBAAa,WAAY,SAAQ,SAAS;gBAC5B,MAAM,EAAE,eAAe;IAW7B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAa3B,mBAAmB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;IAIpD,kBAAkB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;IAuBnD,eAAe,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;CA0CvD"}
|
package/dist/src/leader.node.js
CHANGED
|
@@ -3,6 +3,7 @@ import { START_METHOD } from './methods/start.method.js';
|
|
|
3
3
|
import { oLaneTool } from '@olane/o-lane';
|
|
4
4
|
import { oSearchResolver } from '@olane/o-node';
|
|
5
5
|
import { RegistryMemoryTool } from './registry/registry-memory.tool.js';
|
|
6
|
+
import { oGatewayResolver } from '@olane/o-gateway-olane';
|
|
6
7
|
export class oLeaderNode extends oLaneTool {
|
|
7
8
|
constructor(config) {
|
|
8
9
|
super({
|
|
@@ -17,6 +18,7 @@ export class oLeaderNode extends oLaneTool {
|
|
|
17
18
|
async initialize() {
|
|
18
19
|
await super.initialize();
|
|
19
20
|
this.router.addResolver(new oSearchResolver(this.address));
|
|
21
|
+
this.router.addResolver(new oGatewayResolver(this.address));
|
|
20
22
|
const registryTool = new RegistryMemoryTool({
|
|
21
23
|
name: 'registry',
|
|
22
24
|
parent: this.address,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@olane/o-leader",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"types": "dist/src/index.d.ts",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"url": "git+https://github.com/olane-labs/olane.git"
|
|
34
34
|
},
|
|
35
35
|
"author": "oLane Inc.",
|
|
36
|
-
"license": "
|
|
36
|
+
"license": "(MIT OR Apache-2.0)",
|
|
37
37
|
"description": "oLane leader node used as the root node for a network",
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@eslint/eslintrc": "^3.3.1",
|
|
@@ -55,11 +55,12 @@
|
|
|
55
55
|
"typescript": "5.4.5"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
|
-
"@olane/o-config": "^0.7.
|
|
59
|
-
"@olane/o-core": "^0.7.
|
|
60
|
-
"@olane/o-
|
|
61
|
-
"@olane/o-
|
|
62
|
-
"@olane/o-
|
|
58
|
+
"@olane/o-config": "^0.7.2",
|
|
59
|
+
"@olane/o-core": "^0.7.2",
|
|
60
|
+
"@olane/o-gateway-olane": "^0.7.2",
|
|
61
|
+
"@olane/o-lane": "^0.7.2",
|
|
62
|
+
"@olane/o-protocol": "^0.7.2",
|
|
63
|
+
"@olane/o-tool": "^0.7.2"
|
|
63
64
|
},
|
|
64
65
|
"dependencies": {
|
|
65
66
|
"debug": "^4.4.1",
|