@nxuss/lemma 0.3.3 → 0.4.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.
- package/README.md +42 -330
- package/dashboard/README.md +351 -0
- package/dashboard/dist/assets/index-CIx8ECj8.css +1 -0
- package/dashboard/dist/assets/index-zTlIPJOp.js +478 -0
- package/dashboard/dist/assets/index-zTlIPJOp.js.map +1 -0
- package/dashboard/dist/index.html +14 -0
- package/dist/cjs/api/server.js +1 -1
- package/dist/cjs/cli/stack.d.ts +20 -0
- package/dist/cjs/cli/stack.d.ts.map +1 -0
- package/dist/cjs/cli/stack.js +76 -0
- package/dist/cjs/cli/stack.js.map +1 -0
- package/dist/cjs/cloud/TenantCache.d.ts +1 -0
- package/dist/cjs/cloud/TenantCache.d.ts.map +1 -1
- package/dist/cjs/cloud/TenantCache.js +25 -3
- package/dist/cjs/cloud/TenantCache.js.map +1 -1
- package/dist/cjs/config/index.d.ts.map +1 -1
- package/dist/cjs/config/index.js +4 -0
- package/dist/cjs/config/index.js.map +1 -1
- package/dist/cjs/index.d.ts +3 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +29 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/observability/IdeContextSync.d.ts +39 -0
- package/dist/cjs/observability/IdeContextSync.d.ts.map +1 -0
- package/dist/cjs/observability/IdeContextSync.js +169 -0
- package/dist/cjs/observability/IdeContextSync.js.map +1 -0
- package/dist/cjs/types/index.d.ts +11 -0
- package/dist/cjs/types/index.d.ts.map +1 -1
- package/dist/cjs/types/index.js.map +1 -1
- package/dist/esm/api/server.js +1 -1
- package/dist/esm/cli/stack.d.ts +20 -0
- package/dist/esm/cli/stack.d.ts.map +1 -0
- package/dist/esm/cli/stack.js +73 -0
- package/dist/esm/cli/stack.js.map +1 -0
- package/dist/esm/cloud/TenantCache.d.ts +1 -0
- package/dist/esm/cloud/TenantCache.d.ts.map +1 -1
- package/dist/esm/cloud/TenantCache.js +25 -3
- package/dist/esm/cloud/TenantCache.js.map +1 -1
- package/dist/esm/config/index.d.ts.map +1 -1
- package/dist/esm/config/index.js +4 -0
- package/dist/esm/config/index.js.map +1 -1
- package/dist/esm/index.d.ts +3 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +29 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/observability/IdeContextSync.d.ts +39 -0
- package/dist/esm/observability/IdeContextSync.d.ts.map +1 -0
- package/dist/esm/observability/IdeContextSync.js +162 -0
- package/dist/esm/observability/IdeContextSync.js.map +1 -0
- package/dist/esm/types/index.d.ts +11 -0
- package/dist/esm/types/index.d.ts.map +1 -1
- package/dist/esm/types/index.js.map +1 -1
- package/lemma-proxy.cjs +177 -25
- package/package.json +15 -13
- package/src/cloud/CloudSyncClient.js +35 -0
- package/src/protocol/README.md +576 -0
- package/src/proxy/ComplexityRouter.js +37 -0
- package/src/security/SemanticScrubber.js +54 -0
- package/src/speculative/worker.js +96 -0
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
# Inter-Agent Protocol (I.A.P.) v1.0.0
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The **Inter-Agent Protocol (I.A.P.)** is a lightweight, WebSocket-based communication standard that enables autonomous AI agents to discover, negotiate, and collaborate seamlessly across different frameworks and platforms.
|
|
6
|
+
|
|
7
|
+
I.A.P. solves the fragmentation problem in multi-agent systems by providing a common language for:
|
|
8
|
+
- **Agent identification and capability broadcasting**
|
|
9
|
+
- **Dynamic task negotiation and bidding**
|
|
10
|
+
- **Stateful context transfer between agents**
|
|
11
|
+
- **Real-time performance monitoring**
|
|
12
|
+
|
|
13
|
+
## Core Concepts
|
|
14
|
+
|
|
15
|
+
### 1. Agent Identity
|
|
16
|
+
|
|
17
|
+
Every agent in the network has a unique `AgentId` and advertises its capabilities through a structured handshake process.
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
interface AgentHandshake {
|
|
21
|
+
agentId: string;
|
|
22
|
+
name: string;
|
|
23
|
+
version: string;
|
|
24
|
+
framework?: string;
|
|
25
|
+
capabilities: AgentCapability[];
|
|
26
|
+
maxConcurrentTasks?: number;
|
|
27
|
+
currentLoad?: number;
|
|
28
|
+
protocolVersion: string;
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 2. Capabilities
|
|
33
|
+
|
|
34
|
+
Capabilities define what an agent can do. Each capability includes:
|
|
35
|
+
- **Type**: Predefined category (text generation, code execution, etc.)
|
|
36
|
+
- **Input/Output schemas**: JSON Schema definitions
|
|
37
|
+
- **Performance metrics**: Estimated cost and latency
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
interface AgentCapability {
|
|
41
|
+
id: string;
|
|
42
|
+
type: CapabilityType;
|
|
43
|
+
name: string;
|
|
44
|
+
description: string;
|
|
45
|
+
inputSchema?: Record<string, any>;
|
|
46
|
+
outputSchema?: Record<string, any>;
|
|
47
|
+
estimatedCost?: number;
|
|
48
|
+
averageLatency?: number;
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 3. Task Negotiation
|
|
53
|
+
|
|
54
|
+
Tasks flow through a bidding process:
|
|
55
|
+
1. **Proposal**: An agent proposes a task with requirements
|
|
56
|
+
2. **Bidding**: Capable agents submit bids with cost/latency estimates
|
|
57
|
+
3. **Assignment**: Router selects the optimal agent
|
|
58
|
+
4. **Execution**: Assigned agent executes and returns results
|
|
59
|
+
|
|
60
|
+
### 4. Context Transfer
|
|
61
|
+
|
|
62
|
+
Agents can pass stateful information without re-summarizing:
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
interface ContextTransfer {
|
|
66
|
+
fromAgent: AgentId;
|
|
67
|
+
toAgent: AgentId;
|
|
68
|
+
taskId: TaskId;
|
|
69
|
+
contextType: string;
|
|
70
|
+
data: Record<string, any>;
|
|
71
|
+
embedding?: number[]; // For semantic indexing
|
|
72
|
+
compression?: 'gzip' | 'brotli' | 'none';
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Protocol Flows
|
|
77
|
+
|
|
78
|
+
### Connection Flow
|
|
79
|
+
|
|
80
|
+
```mermaid
|
|
81
|
+
sequenceDiagram
|
|
82
|
+
participant Agent
|
|
83
|
+
participant Router
|
|
84
|
+
|
|
85
|
+
Agent->>Router: HANDSHAKE (capabilities)
|
|
86
|
+
Router->>Agent: HANDSHAKE_ACK (session)
|
|
87
|
+
loop Maintain Connection
|
|
88
|
+
Agent->>Router: HEARTBEAT
|
|
89
|
+
end
|
|
90
|
+
Agent->>Router: DISCONNECT
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Steps:**
|
|
94
|
+
1. Agent sends `HANDSHAKE` with capabilities
|
|
95
|
+
2. Router responds with `HANDSHAKE_ACK` and session ID
|
|
96
|
+
3. Agent sends periodic `HEARTBEAT` messages
|
|
97
|
+
4. Agent sends `DISCONNECT` when leaving
|
|
98
|
+
|
|
99
|
+
### Discovery Flow
|
|
100
|
+
|
|
101
|
+
```mermaid
|
|
102
|
+
sequenceDiagram
|
|
103
|
+
participant Agent A
|
|
104
|
+
participant Router
|
|
105
|
+
|
|
106
|
+
Agent A->>Router: CAPABILITY_DISCOVERY
|
|
107
|
+
Router->>Agent A: CAPABILITY_RESPONSE (all agents)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Steps:**
|
|
111
|
+
1. Agent sends `CAPABILITY_DISCOVERY` request
|
|
112
|
+
2. Router responds with all available agents and their capabilities
|
|
113
|
+
|
|
114
|
+
### Task Negotiation Flow
|
|
115
|
+
|
|
116
|
+
```mermaid
|
|
117
|
+
sequenceDiagram
|
|
118
|
+
participant Agent A
|
|
119
|
+
participant Router
|
|
120
|
+
participant Agent B
|
|
121
|
+
participant Agent C
|
|
122
|
+
|
|
123
|
+
Agent A->>Router: TASK_PROPOSAL
|
|
124
|
+
Router->>Agent B: TASK_PROPOSAL (broadcast)
|
|
125
|
+
Router->>Agent C: TASK_PROPOSAL (broadcast)
|
|
126
|
+
Agent B->>Router: TASK_BID
|
|
127
|
+
Agent C->>Router: TASK_BID
|
|
128
|
+
Router->>Agent B: TASK_ASSIGNMENT (best bid)
|
|
129
|
+
Agent B->>Router: TASK_ACCEPTANCE
|
|
130
|
+
Agent B->>Router: TASK_RESULT
|
|
131
|
+
Router->>Agent A: TASK_RESULT
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Steps:**
|
|
135
|
+
1. Agent A proposes a task to the router
|
|
136
|
+
2. Router broadcasts to all capable agents
|
|
137
|
+
3. Agents B and C submit bids
|
|
138
|
+
4. Router assigns to best bidder (Agent B)
|
|
139
|
+
5. Agent B accepts and executes
|
|
140
|
+
6. Agent B returns result to router
|
|
141
|
+
7. Router forwards result to Agent A
|
|
142
|
+
|
|
143
|
+
### Context Transfer Flow
|
|
144
|
+
|
|
145
|
+
```mermaid
|
|
146
|
+
sequenceDiagram
|
|
147
|
+
participant Agent A
|
|
148
|
+
participant Router
|
|
149
|
+
participant Agent B
|
|
150
|
+
|
|
151
|
+
Agent A->>Router: CONTEXT_TRANSFER
|
|
152
|
+
Router->>Agent B: CONTEXT_TRANSFER
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Steps:**
|
|
156
|
+
1. Agent A sends context to router
|
|
157
|
+
2. Router forwards to Agent B
|
|
158
|
+
3. Agent B continues execution with transferred state
|
|
159
|
+
|
|
160
|
+
## Message Types
|
|
161
|
+
|
|
162
|
+
### Core Messages
|
|
163
|
+
|
|
164
|
+
| Type | Direction | Purpose |
|
|
165
|
+
|------|-----------|---------|
|
|
166
|
+
| `HANDSHAKE` | Agent → Router | Initial connection and capability registration |
|
|
167
|
+
| `HANDSHAKE_ACK` | Router → Agent | Connection acknowledgment |
|
|
168
|
+
| `CAPABILITY_DISCOVERY` | Agent → Router | Query available capabilities |
|
|
169
|
+
| `CAPABILITY_RESPONSE` | Router → Agent | List of agents and capabilities |
|
|
170
|
+
| `TASK_PROPOSAL` | Agent → Router | Propose a task for execution |
|
|
171
|
+
| `TASK_BID` | Agent → Router | Bid on a proposed task |
|
|
172
|
+
| `TASK_ASSIGNMENT` | Router → Agent | Assign task to winning bidder |
|
|
173
|
+
| `TASK_ACCEPTANCE` | Agent → Router | Accept assigned task |
|
|
174
|
+
| `TASK_REJECTION` | Agent → Router | Reject assigned task |
|
|
175
|
+
| `CONTEXT_TRANSFER` | Agent ↔ Agent | Transfer execution context |
|
|
176
|
+
| `TASK_RESULT` | Agent → Router | Return task execution result |
|
|
177
|
+
| `ERROR` | Any → Any | Error notification |
|
|
178
|
+
| `HEARTBEAT` | Agent → Router | Keep-alive signal |
|
|
179
|
+
| `DISCONNECT` | Agent → Router | Graceful disconnect |
|
|
180
|
+
|
|
181
|
+
## Message Structure
|
|
182
|
+
|
|
183
|
+
All I.A.P. messages follow a common structure:
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
interface IAPMessage {
|
|
187
|
+
messageId: string; // Unique message identifier
|
|
188
|
+
type: MessageType; // Message type
|
|
189
|
+
from: AgentId; // Sender
|
|
190
|
+
to: AgentId | 'router'; // Recipient
|
|
191
|
+
timestamp: string; // ISO 8601 timestamp
|
|
192
|
+
protocolVersion: string; // Protocol version (1.0.0)
|
|
193
|
+
payload: any; // Type-specific payload
|
|
194
|
+
correlationId?: string; // For request-response tracking
|
|
195
|
+
metadata?: Record<string, any>;
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Usage Examples
|
|
200
|
+
|
|
201
|
+
### 1. Agent Registration
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
import {
|
|
205
|
+
createHandshakeMessage,
|
|
206
|
+
AgentHandshake,
|
|
207
|
+
CapabilityType
|
|
208
|
+
} from './protocol';
|
|
209
|
+
|
|
210
|
+
const handshake: AgentHandshake = {
|
|
211
|
+
agentId: 'agent_langchain_001',
|
|
212
|
+
name: 'LangChain Code Assistant',
|
|
213
|
+
version: '1.0.0',
|
|
214
|
+
framework: 'LangChain',
|
|
215
|
+
protocolVersion: '1.0.0',
|
|
216
|
+
capabilities: [
|
|
217
|
+
{
|
|
218
|
+
id: 'code_gen_python',
|
|
219
|
+
type: CapabilityType.CODE_EXECUTION,
|
|
220
|
+
name: 'Python Code Generation',
|
|
221
|
+
description: 'Generate and execute Python code',
|
|
222
|
+
estimatedCost: 100,
|
|
223
|
+
averageLatency: 2000
|
|
224
|
+
}
|
|
225
|
+
],
|
|
226
|
+
maxConcurrentTasks: 5,
|
|
227
|
+
currentLoad: 0.2
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const message = createHandshakeMessage(handshake);
|
|
231
|
+
websocket.send(JSON.stringify(message));
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### 2. Task Proposal
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
import {
|
|
238
|
+
createTaskProposalMessage,
|
|
239
|
+
TaskProposal,
|
|
240
|
+
CapabilityType,
|
|
241
|
+
generateTaskId
|
|
242
|
+
} from './protocol';
|
|
243
|
+
|
|
244
|
+
const proposal: TaskProposal = {
|
|
245
|
+
taskId: generateTaskId(),
|
|
246
|
+
proposerId: 'agent_main_001',
|
|
247
|
+
description: 'Analyze CSV file and generate summary statistics',
|
|
248
|
+
requiredCapability: CapabilityType.DATA_ANALYSIS,
|
|
249
|
+
input: {
|
|
250
|
+
filePath: '/data/sales.csv',
|
|
251
|
+
operations: ['mean', 'median', 'std']
|
|
252
|
+
},
|
|
253
|
+
maxLatency: 5000,
|
|
254
|
+
maxCost: 200,
|
|
255
|
+
priority: 7
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
const message = createTaskProposalMessage(proposal);
|
|
259
|
+
websocket.send(JSON.stringify(message));
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### 3. Submitting a Bid
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
import { createTaskBidMessage, TaskBid } from './protocol';
|
|
266
|
+
|
|
267
|
+
const bid: TaskBid = {
|
|
268
|
+
taskId: 'task_abc123',
|
|
269
|
+
bidderId: 'agent_data_001',
|
|
270
|
+
estimatedLatency: 3000,
|
|
271
|
+
estimatedCost: 150,
|
|
272
|
+
confidence: 0.95,
|
|
273
|
+
queueDepth: 2,
|
|
274
|
+
notes: 'Specialized in CSV analysis with pandas'
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
const message = createTaskBidMessage(bid, 'agent_data_001');
|
|
278
|
+
websocket.send(JSON.stringify(message));
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### 4. Context Transfer
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
import { createContextTransferMessage, ContextTransfer } from './protocol';
|
|
285
|
+
|
|
286
|
+
const transfer: ContextTransfer = {
|
|
287
|
+
fromAgent: 'agent_a',
|
|
288
|
+
toAgent: 'agent_b',
|
|
289
|
+
taskId: 'task_xyz789',
|
|
290
|
+
contextType: 'conversation_history',
|
|
291
|
+
data: {
|
|
292
|
+
messages: [
|
|
293
|
+
{ role: 'user', content: 'Hello' },
|
|
294
|
+
{ role: 'assistant', content: 'Hi there!' }
|
|
295
|
+
],
|
|
296
|
+
metadata: { sessionId: 'session_123' }
|
|
297
|
+
},
|
|
298
|
+
compression: 'none'
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
const message = createContextTransferMessage(transfer);
|
|
302
|
+
websocket.send(JSON.stringify(message));
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### 5. Message Validation
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
import { validateIAPMessage, validateHandshake } from './protocol';
|
|
309
|
+
|
|
310
|
+
// Validate complete message
|
|
311
|
+
const result = validateIAPMessage(incomingMessage);
|
|
312
|
+
if (!result.valid) {
|
|
313
|
+
console.error('Validation errors:', result.errors);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Validate specific payload
|
|
317
|
+
const handshakeResult = validateHandshake(handshakePayload);
|
|
318
|
+
if (!handshakeResult.valid) {
|
|
319
|
+
console.error('Invalid handshake:', handshakeResult.errors);
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
## State Management
|
|
324
|
+
|
|
325
|
+
### Flow States
|
|
326
|
+
|
|
327
|
+
The protocol defines a state machine for tracking agent and task states:
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
enum FlowState {
|
|
331
|
+
DISCONNECTED = 'disconnected',
|
|
332
|
+
HANDSHAKING = 'handshaking',
|
|
333
|
+
CONNECTED = 'connected',
|
|
334
|
+
IDLE = 'idle',
|
|
335
|
+
DISCOVERING = 'discovering',
|
|
336
|
+
PROPOSING = 'proposing',
|
|
337
|
+
BIDDING = 'bidding',
|
|
338
|
+
ASSIGNING = 'assigning',
|
|
339
|
+
EXECUTING = 'executing',
|
|
340
|
+
TRANSFERRING_CONTEXT = 'transferring_context',
|
|
341
|
+
COMPLETING = 'completing',
|
|
342
|
+
ERROR = 'error',
|
|
343
|
+
DISCONNECTING = 'disconnecting'
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Task Lifecycle
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
enum TaskStatus {
|
|
351
|
+
PROPOSED = 'proposed',
|
|
352
|
+
BIDDING = 'bidding',
|
|
353
|
+
ASSIGNED = 'assigned',
|
|
354
|
+
IN_PROGRESS = 'in_progress',
|
|
355
|
+
COMPLETED = 'completed',
|
|
356
|
+
FAILED = 'failed',
|
|
357
|
+
CANCELLED = 'cancelled'
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### State Transitions
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
import {
|
|
365
|
+
createFlowContext,
|
|
366
|
+
transitionFlow,
|
|
367
|
+
MessageType
|
|
368
|
+
} from './protocol';
|
|
369
|
+
|
|
370
|
+
// Create initial context
|
|
371
|
+
const context = createFlowContext('agent_001');
|
|
372
|
+
|
|
373
|
+
// Transition through states
|
|
374
|
+
const newContext = transitionFlow(context, MessageType.HANDSHAKE);
|
|
375
|
+
// context.currentState: DISCONNECTED -> HANDSHAKING
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## Performance Considerations
|
|
379
|
+
|
|
380
|
+
### Message Size
|
|
381
|
+
|
|
382
|
+
- Keep payloads under 10KB for optimal performance
|
|
383
|
+
- Use compression for larger context transfers
|
|
384
|
+
- Consider chunking for very large data transfers
|
|
385
|
+
|
|
386
|
+
### Latency Targets
|
|
387
|
+
|
|
388
|
+
- **Handshake**: < 100ms
|
|
389
|
+
- **Discovery**: < 50ms
|
|
390
|
+
- **Task Assignment**: < 100ms
|
|
391
|
+
- **Context Transfer**: < 200ms (depends on size)
|
|
392
|
+
|
|
393
|
+
### Heartbeat Interval
|
|
394
|
+
|
|
395
|
+
Recommended: 30 seconds
|
|
396
|
+
- Balances connection monitoring with network overhead
|
|
397
|
+
- Adjust based on network reliability
|
|
398
|
+
|
|
399
|
+
## Error Handling
|
|
400
|
+
|
|
401
|
+
### Error Codes
|
|
402
|
+
|
|
403
|
+
| Code | Description | Recoverable |
|
|
404
|
+
|------|-------------|-------------|
|
|
405
|
+
| `VALIDATION_ERROR` | Message validation failed | Yes |
|
|
406
|
+
| `CAPABILITY_NOT_FOUND` | Required capability unavailable | Yes |
|
|
407
|
+
| `TASK_TIMEOUT` | Task execution exceeded deadline | No |
|
|
408
|
+
| `AGENT_OVERLOAD` | Agent at maximum capacity | Yes |
|
|
409
|
+
| `CONTEXT_TRANSFER_FAILED` | Context transfer failed | Yes |
|
|
410
|
+
| `PROTOCOL_VERSION_MISMATCH` | Incompatible protocol versions | No |
|
|
411
|
+
|
|
412
|
+
### Error Message Example
|
|
413
|
+
|
|
414
|
+
```typescript
|
|
415
|
+
import { createErrorMessage, ErrorMessage } from './protocol';
|
|
416
|
+
|
|
417
|
+
const error: ErrorMessage = {
|
|
418
|
+
code: 'TASK_TIMEOUT',
|
|
419
|
+
message: 'Task execution exceeded 5000ms deadline',
|
|
420
|
+
relatedTaskId: 'task_abc123',
|
|
421
|
+
details: { actualLatency: 6500 },
|
|
422
|
+
recoverable: false
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
const message = createErrorMessage(
|
|
426
|
+
'agent_001',
|
|
427
|
+
'router',
|
|
428
|
+
error,
|
|
429
|
+
'msg_original_123'
|
|
430
|
+
);
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
## Security Considerations
|
|
434
|
+
|
|
435
|
+
### Authentication
|
|
436
|
+
|
|
437
|
+
- Implement agent authentication at the WebSocket layer
|
|
438
|
+
- Use JWT tokens or API keys for agent identification
|
|
439
|
+
- Validate agent identity during handshake
|
|
440
|
+
|
|
441
|
+
### Authorization
|
|
442
|
+
|
|
443
|
+
- Enforce capability-based access control
|
|
444
|
+
- Validate task permissions before assignment
|
|
445
|
+
- Audit all agent actions
|
|
446
|
+
|
|
447
|
+
### Data Protection
|
|
448
|
+
|
|
449
|
+
- Encrypt sensitive data in context transfers
|
|
450
|
+
- Use checksums to verify data integrity
|
|
451
|
+
- Implement rate limiting to prevent abuse
|
|
452
|
+
|
|
453
|
+
## Integration with Subconscious Router
|
|
454
|
+
|
|
455
|
+
The I.A.P. protocol is designed to work seamlessly with the Subconscious Router's semantic caching:
|
|
456
|
+
|
|
457
|
+
1. **Semantic Interception**: Router checks incoming tasks against vector database
|
|
458
|
+
2. **Cache Hit**: Return cached result (< 50ms) without agent execution
|
|
459
|
+
3. **Cache Miss**: Route to appropriate agent via I.A.P. negotiation
|
|
460
|
+
4. **Result Caching**: Store result with embedding for future hits
|
|
461
|
+
|
|
462
|
+
```typescript
|
|
463
|
+
// Pseudo-code for router integration
|
|
464
|
+
async function handleTaskProposal(proposal: TaskProposal) {
|
|
465
|
+
// Check semantic cache
|
|
466
|
+
const cached = await semanticCache.query(proposal.description);
|
|
467
|
+
|
|
468
|
+
if (cached && cached.similarity > 0.95) {
|
|
469
|
+
// Instant response from cache
|
|
470
|
+
return cached.result;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// Route via I.A.P. negotiation
|
|
474
|
+
const bids = await broadcastTaskProposal(proposal);
|
|
475
|
+
const winner = selectBestBid(bids);
|
|
476
|
+
const result = await assignAndExecute(winner, proposal);
|
|
477
|
+
|
|
478
|
+
// Cache for future
|
|
479
|
+
await semanticCache.store(proposal.description, result);
|
|
480
|
+
|
|
481
|
+
return result;
|
|
482
|
+
}
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
## Framework Integration
|
|
486
|
+
|
|
487
|
+
### LangChain
|
|
488
|
+
|
|
489
|
+
```typescript
|
|
490
|
+
import { LangChainAgent } from '@langchain/core';
|
|
491
|
+
import { IAPClient } from './iap-client';
|
|
492
|
+
|
|
493
|
+
const agent = new LangChainAgent(/* config */);
|
|
494
|
+
const iapClient = new IAPClient('ws://router:8080');
|
|
495
|
+
|
|
496
|
+
await iapClient.connect({
|
|
497
|
+
agentId: 'langchain_001',
|
|
498
|
+
name: 'LangChain Agent',
|
|
499
|
+
capabilities: agent.getCapabilities()
|
|
500
|
+
});
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
### CrewAI
|
|
504
|
+
|
|
505
|
+
```python
|
|
506
|
+
from crewai import Agent
|
|
507
|
+
from iap_client import IAPClient
|
|
508
|
+
|
|
509
|
+
agent = Agent(role="researcher", goal="Research topics")
|
|
510
|
+
iap_client = IAPClient("ws://router:8080")
|
|
511
|
+
|
|
512
|
+
await iap_client.connect(
|
|
513
|
+
agent_id="crewai_001",
|
|
514
|
+
name="CrewAI Researcher",
|
|
515
|
+
capabilities=agent.get_capabilities()
|
|
516
|
+
)
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
### AutoGPT
|
|
520
|
+
|
|
521
|
+
```typescript
|
|
522
|
+
import { AutoGPTAgent } from 'autogpt';
|
|
523
|
+
import { IAPClient } from './iap-client';
|
|
524
|
+
|
|
525
|
+
const agent = new AutoGPTAgent(/* config */);
|
|
526
|
+
const iapClient = new IAPClient('ws://router:8080');
|
|
527
|
+
|
|
528
|
+
await iapClient.connect({
|
|
529
|
+
agentId: 'autogpt_001',
|
|
530
|
+
name: 'AutoGPT Agent',
|
|
531
|
+
capabilities: agent.listCapabilities()
|
|
532
|
+
});
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
## Versioning
|
|
536
|
+
|
|
537
|
+
The protocol follows semantic versioning (MAJOR.MINOR.PATCH):
|
|
538
|
+
|
|
539
|
+
- **MAJOR**: Breaking changes to message structure or flow
|
|
540
|
+
- **MINOR**: New message types or optional fields
|
|
541
|
+
- **PATCH**: Bug fixes and clarifications
|
|
542
|
+
|
|
543
|
+
Current version: **1.0.0**
|
|
544
|
+
|
|
545
|
+
### Version Compatibility
|
|
546
|
+
|
|
547
|
+
- Agents must specify `protocolVersion` in handshake
|
|
548
|
+
- Router validates version compatibility (same major version)
|
|
549
|
+
- Incompatible versions receive `PROTOCOL_VERSION_MISMATCH` error
|
|
550
|
+
|
|
551
|
+
## Future Enhancements
|
|
552
|
+
|
|
553
|
+
### v1.1.0 (Planned)
|
|
554
|
+
- Message batching for high-throughput scenarios
|
|
555
|
+
- Streaming responses for long-running tasks
|
|
556
|
+
- Agent reputation and trust scoring
|
|
557
|
+
|
|
558
|
+
### v2.0.0 (Roadmap)
|
|
559
|
+
- Direct agent-to-agent communication (bypass router)
|
|
560
|
+
- Multi-router federation
|
|
561
|
+
- Advanced consensus mechanisms
|
|
562
|
+
|
|
563
|
+
## Contributing
|
|
564
|
+
|
|
565
|
+
Contributions to the I.A.P. specification are welcome! Please submit issues and pull requests to the [GitHub repository](https://github.com/subconscious-router/iap).
|
|
566
|
+
|
|
567
|
+
## License
|
|
568
|
+
|
|
569
|
+
MIT License - See LICENSE file for details
|
|
570
|
+
|
|
571
|
+
## References
|
|
572
|
+
|
|
573
|
+
- [Subconscious Router Technical Specification](../../TECHNICAL_SPEC.md)
|
|
574
|
+
- [WebSocket Protocol (RFC 6455)](https://tools.ietf.org/html/rfc6455)
|
|
575
|
+
- [JSON Schema](https://json-schema.org/)
|
|
576
|
+
- [Semantic Versioning](https://semver.org/)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Complexity Router - Evaluates prompt complexity to optimize LLM cost
|
|
2
|
+
class ComplexityRouter {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.cheapModel = 'gpt-4o-mini';
|
|
5
|
+
this.complexKeywords = ['architecture', 'design', 'debug', 'trace', 'system', 'microservices', 'explain', 'why', 'refactor', 'optimize'];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
evaluate(prompt, originalModel) {
|
|
9
|
+
if (!prompt || prompt.length < 10) return { model: this.cheapModel, complexity: 'low' };
|
|
10
|
+
|
|
11
|
+
const lower = prompt.toLowerCase();
|
|
12
|
+
let isComplex = false;
|
|
13
|
+
|
|
14
|
+
// Heuristic 1: Prompt Length
|
|
15
|
+
if (prompt.length > 500) {
|
|
16
|
+
isComplex = true;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Heuristic 2: Keywords that imply deep reasoning
|
|
20
|
+
for (const kw of this.complexKeywords) {
|
|
21
|
+
if (lower.includes(kw)) {
|
|
22
|
+
isComplex = true;
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (isComplex) {
|
|
28
|
+
console.log(`[ComplexityRouter] High complexity detected. Routing to ${originalModel}`);
|
|
29
|
+
return { model: originalModel || 'gpt-4o', complexity: 'high' };
|
|
30
|
+
} else {
|
|
31
|
+
console.log(`[ComplexityRouter] Low complexity detected. Routing to ${this.cheapModel}`);
|
|
32
|
+
return { model: this.cheapModel, complexity: 'low' };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = ComplexityRouter;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Privacy Firewall - Semantic Scrubber for PII and Secrets
|
|
2
|
+
class SemanticScrubber {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.patterns = [
|
|
5
|
+
{ name: 'API_KEY', regex: /(sk-[a-zA-Z0-9\-]{20,})/g },
|
|
6
|
+
{ name: 'EMAIL', regex: /([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/g },
|
|
7
|
+
{ name: 'TOKEN', regex: /(Bearer\s+[a-zA-Z0-9\-._~+/]+=*)/gi }
|
|
8
|
+
];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
mask(prompt) {
|
|
12
|
+
let maskedPrompt = prompt;
|
|
13
|
+
const tokenMap = {};
|
|
14
|
+
let counter = 1;
|
|
15
|
+
|
|
16
|
+
for (const pattern of this.patterns) {
|
|
17
|
+
maskedPrompt = maskedPrompt.replace(pattern.regex, (match) => {
|
|
18
|
+
const token = `[${pattern.name}_${counter++}]`;
|
|
19
|
+
tokenMap[token] = match;
|
|
20
|
+
return token;
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (Object.keys(tokenMap).length > 0) {
|
|
25
|
+
console.log(`[PrivacyFirewall] Masked ${Object.keys(tokenMap).length} secrets.`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return { maskedPrompt, tokenMap };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
unmask(responseObj, tokenMap) {
|
|
32
|
+
if (!responseObj || Object.keys(tokenMap).length === 0) return responseObj;
|
|
33
|
+
|
|
34
|
+
let str = typeof responseObj === 'string' ? responseObj : JSON.stringify(responseObj);
|
|
35
|
+
|
|
36
|
+
for (const [token, value] of Object.entries(tokenMap)) {
|
|
37
|
+
str = str.split(token).join(value);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return typeof responseObj === 'string' ? str : JSON.parse(str);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Unmask a single stream chunk string
|
|
44
|
+
unmaskString(str, tokenMap) {
|
|
45
|
+
if (!str || Object.keys(tokenMap).length === 0) return str;
|
|
46
|
+
let unmasked = str;
|
|
47
|
+
for (const [token, value] of Object.entries(tokenMap)) {
|
|
48
|
+
unmasked = unmasked.split(token).join(value);
|
|
49
|
+
}
|
|
50
|
+
return unmasked;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
module.exports = SemanticScrubber;
|