ai2ai 1.0.0 → 1.0.2
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 +526 -0
- package/logo.jpg +0 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/DarrenEdwards111/ai2ai-protocol/main/logo.jpg" alt="AI2AI Protocol" width="200" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">AI2AI Protocol</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>Production-ready agent-to-agent communication protocol</strong><br>
|
|
9
|
+
Zero dependencies • Ed25519 signed • Encrypted • Discoverable
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="https://www.npmjs.com/package/ai2ai"><img src="https://img.shields.io/npm/v/ai2ai.svg" alt="npm"></a>
|
|
14
|
+
<a href="https://github.com/DarrenEdwards111/ai2ai-protocol/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-blue.svg" alt="License"></a>
|
|
15
|
+
<img src="https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg" alt="Node">
|
|
16
|
+
<img src="https://img.shields.io/badge/dependencies-0-brightgreen.svg" alt="Zero deps">
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
const { AI2AI } = require('ai2ai');
|
|
25
|
+
|
|
26
|
+
const agent = new AI2AI({ name: 'my-agent', port: 18800 });
|
|
27
|
+
await agent.start();
|
|
28
|
+
await agent.send('other-agent', 'Hello from my AI!');
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Features
|
|
32
|
+
|
|
33
|
+
- 🔐 **Ed25519 signatures** — Every message is cryptographically signed
|
|
34
|
+
- 🔒 **X25519 encryption** — Optional payload encryption (AES-256-GCM)
|
|
35
|
+
- 📡 **Agent discovery** — Registry, DNS TXT, mDNS/Bonjour, .well-known
|
|
36
|
+
- 🔄 **Reliability** — Retry with backoff, circuit breaker, persistent queue
|
|
37
|
+
- 📨 **Delivery receipts** — sent/delivered/read confirmations
|
|
38
|
+
- 🛡️ **Security hardening** — Rate limiting, nonce tracking, message expiry, blocklist
|
|
39
|
+
- 🔑 **Key rotation** — Rotate keys with automatic announcement
|
|
40
|
+
- 💀 **Dead letter queue** — Failed messages preserved for retry
|
|
41
|
+
- 👤 **Human-in-the-loop** — Approval workflow for sensitive actions
|
|
42
|
+
- 🧵 **Conversation threading** — State machine: proposed → negotiating → confirmed
|
|
43
|
+
- 🛒 **Commerce** — Request quotes, make offers, accept/reject (always requires human approval)
|
|
44
|
+
- 📦 **Zero dependencies** — Node.js built-ins only
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm install ai2ai
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Or clone directly:
|
|
53
|
+
```bash
|
|
54
|
+
git clone https://github.com/DarrenEdwards111/ai2ai-protocol.git
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Basic Usage
|
|
58
|
+
|
|
59
|
+
### Create an Agent
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
const { AI2AI } = require('ai2ai');
|
|
63
|
+
|
|
64
|
+
const agent = new AI2AI({
|
|
65
|
+
name: 'alice-agent',
|
|
66
|
+
humanName: 'Alice',
|
|
67
|
+
port: 18800,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Listen for messages
|
|
71
|
+
agent.on('message', (payload, from) => {
|
|
72
|
+
console.log(`Message from ${from.human}: ${payload.message}`);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Listen for requests
|
|
76
|
+
agent.on('request', (intent, payload, from) => {
|
|
77
|
+
console.log(`Request: ${intent} from ${from.human}`);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
await agent.start();
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Send Messages
|
|
84
|
+
|
|
85
|
+
```js
|
|
86
|
+
// Add a contact
|
|
87
|
+
agent.addContact('bob-agent', { endpoint: 'http://localhost:18801/ai2ai' });
|
|
88
|
+
|
|
89
|
+
// Send a message
|
|
90
|
+
await agent.send('bob-agent', 'Hey Bob, are you free for lunch?');
|
|
91
|
+
|
|
92
|
+
// Send a structured request
|
|
93
|
+
await agent.request('bob-agent', 'schedule.meeting', {
|
|
94
|
+
subject: 'Team Lunch',
|
|
95
|
+
proposed_times: ['2026-02-20T12:00:00Z'],
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Discovery
|
|
100
|
+
|
|
101
|
+
### Registry
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
const { RegistryServer, RegistryClient } = require('ai2ai/src/registry');
|
|
105
|
+
|
|
106
|
+
// Start a registry server
|
|
107
|
+
const registry = new RegistryServer();
|
|
108
|
+
await registry.start(18820);
|
|
109
|
+
|
|
110
|
+
// Register your agent
|
|
111
|
+
const agent = new AI2AI({
|
|
112
|
+
name: 'my-agent',
|
|
113
|
+
port: 18800,
|
|
114
|
+
registry: 'http://localhost:18820',
|
|
115
|
+
});
|
|
116
|
+
await agent.start();
|
|
117
|
+
await agent.register();
|
|
118
|
+
|
|
119
|
+
// Discover other agents
|
|
120
|
+
const agents = await agent.discover({ capability: 'schedule.meeting' });
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### DNS TXT Record
|
|
124
|
+
|
|
125
|
+
Add a DNS TXT record:
|
|
126
|
+
```
|
|
127
|
+
_ai2ai.yourdomain.com TXT "endpoint=https://your-server.com/ai2ai"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Local Network (mDNS)
|
|
131
|
+
|
|
132
|
+
```js
|
|
133
|
+
const { startLocalDiscovery } = require('ai2ai/src/registry');
|
|
134
|
+
|
|
135
|
+
const discovery = startLocalDiscovery((agent) => {
|
|
136
|
+
console.log(`Found: ${agent.agentId} at ${agent.endpoint}`);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
discovery.announce('my-agent', 18800, 'Alice');
|
|
140
|
+
discovery.query();
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Security Model
|
|
144
|
+
|
|
145
|
+
| Feature | Description |
|
|
146
|
+
|---------|-------------|
|
|
147
|
+
| **Ed25519 signatures** | Every message signed with sender's private key |
|
|
148
|
+
| **X25519 encryption** | Optional ECDH + AES-256-GCM payload encryption |
|
|
149
|
+
| **Nonce tracking** | Prevent replay attacks |
|
|
150
|
+
| **Message expiry** | Reject messages older than configurable TTL (default 24h) |
|
|
151
|
+
| **Rate limiting** | Per-agent request throttling |
|
|
152
|
+
| **Agent blocklist** | Block specific agents |
|
|
153
|
+
| **Key rotation** | Rotate keys with announcement to contacts |
|
|
154
|
+
| **Verification cache** | Cache signature verification results |
|
|
155
|
+
| **Trust levels** | none → known → trusted (commerce always requires approval) |
|
|
156
|
+
|
|
157
|
+
## Integrations
|
|
158
|
+
|
|
159
|
+
### OpenClaw
|
|
160
|
+
|
|
161
|
+
```js
|
|
162
|
+
const { createOpenClawAdapter } = require('ai2ai/src/integrations/openclaw');
|
|
163
|
+
|
|
164
|
+
const adapter = createOpenClawAdapter({
|
|
165
|
+
agentName: 'my-agent',
|
|
166
|
+
onMessage: (payload, from) => console.log(from, payload),
|
|
167
|
+
notify: (text) => console.log(text),
|
|
168
|
+
});
|
|
169
|
+
await adapter.start();
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Webhooks
|
|
173
|
+
|
|
174
|
+
```js
|
|
175
|
+
const { createWebhookForwarder } = require('ai2ai/src/integrations/webhook');
|
|
176
|
+
|
|
177
|
+
const webhook = createWebhookForwarder({
|
|
178
|
+
url: 'https://your-server.com/webhook',
|
|
179
|
+
secret: 'shared-secret',
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
agent.on('message', webhook.handler);
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Express Middleware
|
|
186
|
+
|
|
187
|
+
```js
|
|
188
|
+
const { ai2aiMiddleware } = require('ai2ai/src/integrations/express');
|
|
189
|
+
|
|
190
|
+
app.use('/ai2ai', ai2aiMiddleware({
|
|
191
|
+
agentName: 'my-agent',
|
|
192
|
+
onMessage: (payload, from, envelope) => { ... },
|
|
193
|
+
}));
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Protocol Specification
|
|
197
|
+
|
|
198
|
+
See [SPEC.md](SPEC.md) for the full protocol specification including:
|
|
199
|
+
- Message envelope format
|
|
200
|
+
- All message types and intent types
|
|
201
|
+
- Security model
|
|
202
|
+
- Discovery mechanisms
|
|
203
|
+
- Error codes
|
|
204
|
+
- Versioning rules
|
|
205
|
+
|
|
206
|
+
## API Reference
|
|
207
|
+
|
|
208
|
+
### `AI2AI` (Production Client)
|
|
209
|
+
|
|
210
|
+
```js
|
|
211
|
+
const agent = new AI2AI({
|
|
212
|
+
name: string, // Agent ID
|
|
213
|
+
humanName: string, // Human operator name
|
|
214
|
+
port: number, // Server port (default: 18800)
|
|
215
|
+
registry: string, // Registry URL
|
|
216
|
+
timeout: number, // Request timeout ms (default: 30000)
|
|
217
|
+
messageTTL: number, // Message TTL ms (default: 86400000)
|
|
218
|
+
dataDir: string, // Data directory
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
await agent.start(port?) // Start HTTP server
|
|
222
|
+
await agent.stop() // Stop agent
|
|
223
|
+
await agent.register(url?) // Register with registry
|
|
224
|
+
await agent.send(id, msg, opts?) // Send message
|
|
225
|
+
await agent.request(id, intent, payload, opts?) // Send request
|
|
226
|
+
await agent.discover(query?) // Search registry
|
|
227
|
+
agent.addContact(id, info) // Add/update contact
|
|
228
|
+
agent.getContact(id) // Get contact
|
|
229
|
+
agent.on('message', handler) // Listen for messages
|
|
230
|
+
agent.on('request', handler) // Listen for requests
|
|
231
|
+
agent.on('receipt', handler) // Listen for receipts
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### `RegistryServer`
|
|
235
|
+
|
|
236
|
+
```js
|
|
237
|
+
const server = new RegistryServer({ staleTimeout: 120000 });
|
|
238
|
+
await server.start(port) // Start registry HTTP server
|
|
239
|
+
server.stop() // Stop server
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### `RegistryClient`
|
|
243
|
+
|
|
244
|
+
```js
|
|
245
|
+
const client = new RegistryClient({ registryUrl, agentId });
|
|
246
|
+
await client.register(agentInfo) // Register
|
|
247
|
+
await client.search(query?) // Search agents
|
|
248
|
+
await client.resolve(agentId) // Resolve by ID
|
|
249
|
+
await client.deregister() // Remove registration
|
|
250
|
+
await client.heartbeat() // Send keepalive
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Reliability
|
|
254
|
+
|
|
255
|
+
```js
|
|
256
|
+
const { retryWithBackoff, CircuitBreaker, Deduplicator, DeliveryTracker, DeadLetterQueue, PersistentQueue } = require('ai2ai-protocol/src/reliability');
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Security
|
|
260
|
+
|
|
261
|
+
```js
|
|
262
|
+
const { KeyRotation, RateLimiter, NonceTracker, Blocklist, VerificationCache, isMessageExpired } = require('ai2ai-protocol/src/security');
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Examples
|
|
266
|
+
|
|
267
|
+
See the [`examples/`](examples/) directory:
|
|
268
|
+
|
|
269
|
+
- [`basic-agent.js`](examples/basic-agent.js) — Minimal working agent
|
|
270
|
+
- [`two-agents.js`](examples/two-agents.js) — Two agents chatting
|
|
271
|
+
- [`with-registry.js`](examples/with-registry.js) — Agent discovery via registry
|
|
272
|
+
- [`webhook-receiver.js`](examples/webhook-receiver.js) — Forward to webhooks
|
|
273
|
+
- [`openclaw-skill.js`](examples/openclaw-skill.js) — OpenClaw integration
|
|
274
|
+
|
|
275
|
+
## Tests
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
cd src
|
|
279
|
+
node test.js # Original 146 tests
|
|
280
|
+
node test-v1.js # New v1.0 tests (110 tests)
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## Contributing
|
|
284
|
+
|
|
285
|
+
1. Fork the repo
|
|
286
|
+
2. Create a feature branch
|
|
287
|
+
3. Run tests: `cd src && node test.js && node test-v1.js`
|
|
288
|
+
4. Submit a PR
|
|
289
|
+
|
|
290
|
+
## License
|
|
291
|
+
|
|
292
|
+
Apache 2.0 — See [LICENSE](LICENSE)
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
<p align="center">
|
|
297
|
+
Built by <a href="https://mikoshi.co.uk">Mikoshi Ltd</a> 🦞
|
|
298
|
+
</p>
|
|
299
|
+
## 📋 Supported Intents
|
|
300
|
+
|
|
301
|
+
| Intent | Description |
|
|
302
|
+
|--------|-------------|
|
|
303
|
+
| `schedule.meeting` | Propose times, negotiate, confirm |
|
|
304
|
+
| `schedule.call` | Schedule a call |
|
|
305
|
+
| `schedule.group` | Find time for multiple people |
|
|
306
|
+
| `message.relay` | Pass a message to another human |
|
|
307
|
+
| `info.request` | Ask for specific information |
|
|
308
|
+
| `info.share` | Share information (one-way) |
|
|
309
|
+
| `social.introduction` | Introduce two humans via agents |
|
|
310
|
+
| `commerce.request` | Request a quote |
|
|
311
|
+
| `commerce.offer` | Make an offer |
|
|
312
|
+
| `commerce.accept` | Accept a deal |
|
|
313
|
+
| `commerce.reject` | Decline a deal |
|
|
314
|
+
|
|
315
|
+
Intents are extensible. Add your own.
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## 🔒 Security
|
|
320
|
+
|
|
321
|
+
- **Ed25519** message signing — every message is cryptographically signed
|
|
322
|
+
- **X25519 + AES-256-GCM** end-to-end payload encryption
|
|
323
|
+
- **Trust levels** — `none` → `known` → `trusted` (escalate over time)
|
|
324
|
+
- **Human approval** — required for all actions by default
|
|
325
|
+
- **Rate limiting** — per-agent, prevents spam
|
|
326
|
+
- **Prompt injection protection** — structured JSON, not raw text execution
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## 📨 Message Format
|
|
331
|
+
|
|
332
|
+
Every AI2AI message is a JSON envelope:
|
|
333
|
+
|
|
334
|
+
```json
|
|
335
|
+
{
|
|
336
|
+
"ai2ai": "0.1",
|
|
337
|
+
"id": "uuid",
|
|
338
|
+
"timestamp": "2026-02-07T19:00:00Z",
|
|
339
|
+
"from": {
|
|
340
|
+
"agent": "darren-assistant",
|
|
341
|
+
"human": "Darren"
|
|
342
|
+
},
|
|
343
|
+
"to": {
|
|
344
|
+
"agent": "alex-assistant",
|
|
345
|
+
"human": "Alex"
|
|
346
|
+
},
|
|
347
|
+
"conversation": "conv-uuid",
|
|
348
|
+
"type": "request",
|
|
349
|
+
"intent": "schedule.meeting",
|
|
350
|
+
"payload": { ... },
|
|
351
|
+
"requires_human_approval": true,
|
|
352
|
+
"signature": "ed25519-signature"
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Message types: `ping` | `request` | `response` | `confirm` | `reject` | `inform`
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## 🏗️ Architecture
|
|
361
|
+
|
|
362
|
+
```
|
|
363
|
+
┌──────────────────────┐ ┌──────────────────────┐
|
|
364
|
+
│ Darren's Setup │ │ Alex's Setup │
|
|
365
|
+
│ │ │ │
|
|
366
|
+
│ Human ←→ OpenClaw │ │ Human ←→ OpenClaw │
|
|
367
|
+
│ ↕ │ HTTP │ ↕ │
|
|
368
|
+
│ AI2AI Server ────┼────────→┤ AI2AI Server │
|
|
369
|
+
│ (port 18810) │←────────┼ (port 18811) │
|
|
370
|
+
│ ↕ │ │ ↕ │
|
|
371
|
+
│ Keys | Trust | Log │ │ Keys | Trust | Log │
|
|
372
|
+
└──────────────────────┘ └──────────────────────┘
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
- **ai2ai-server.js** — HTTP endpoint, receives incoming messages
|
|
376
|
+
- **ai2ai-client.js** — Sends outgoing messages
|
|
377
|
+
- **ai2ai-handlers.js** — Intent processing (schedule, message, commerce, etc.)
|
|
378
|
+
- **ai2ai-crypto.js** — Ed25519 signing & verification
|
|
379
|
+
- **ai2ai-encryption.js** — X25519 + AES-256-GCM payload encryption
|
|
380
|
+
- **ai2ai-trust.js** — Contact management & trust levels
|
|
381
|
+
- **ai2ai-queue.js** — Disk-backed retry queue with exponential backoff
|
|
382
|
+
- **ai2ai-discovery.js** — DNS, mDNS, .well-known agent discovery
|
|
383
|
+
- **ai2ai-conversations.js** — Conversation state machine & expiry
|
|
384
|
+
- **ai2ai-logger.js** — Structured audit logging
|
|
385
|
+
- **ai2ai-bridge.js** — CLI tool for agents to use the protocol
|
|
386
|
+
- **openclaw-integration.js** — Natural language command parsing
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## 🎯 Real-World Scenarios
|
|
391
|
+
|
|
392
|
+
Six runnable demos that prove AI2AI works for real multi-agent tasks. Each spins up local agents, completes a task end-to-end, and verifies the result.
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
# Run all demos
|
|
396
|
+
node examples/demo-schedule.js # Schedule Meeting
|
|
397
|
+
node examples/demo-price-quote.js # Price Comparison
|
|
398
|
+
node examples/demo-research.js # Collaborative Research
|
|
399
|
+
node examples/demo-delegation.js # Delegation Chain
|
|
400
|
+
node examples/demo-info-exchange.js # Information Exchange
|
|
401
|
+
node examples/demo-approval.js # Human Approval Flow
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### 1. 🗓️ Schedule Meeting
|
|
405
|
+
Two agents negotiate a meeting time. Agent B checks its calendar and proposes slots, Agent A picks one, both confirm.
|
|
406
|
+
```
|
|
407
|
+
[Alice] Requesting meeting with Bob: "Project Sync"
|
|
408
|
+
[Bob] Checking calendar... proposing 3 available slots
|
|
409
|
+
[Alice] Picking: 2026-03-10T14:00
|
|
410
|
+
✅ Both agents agreed: "Project Sync" at 2026-03-10T14:00
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### 2. 💰 Price Comparison
|
|
414
|
+
A buyer agent sends quote requests to two merchant agents, collects responses, and picks the cheapest.
|
|
415
|
+
```
|
|
416
|
+
[Merchant B] responding £28
|
|
417
|
+
[Merchant C] responding £32
|
|
418
|
+
✅ Buyer selected merchant-b at £28
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
### 3. 🔬 Collaborative Research
|
|
422
|
+
A researcher agent asks a specialist for technical analysis. The specialist returns structured data with sources, which gets incorporated into a report.
|
|
423
|
+
```
|
|
424
|
+
[Specialist] Responding with structured answer (confidence: 0.95)
|
|
425
|
+
[Researcher] Report compiled: "LoRa Modulation Technical Brief" with 3 sections
|
|
426
|
+
✅ Report includes specialist contribution
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### 4. 🔗 Delegation Chain
|
|
430
|
+
Manager → Coordinator → Worker. The coordinator can't fully complete the task, so it delegates a subtask to the worker, combines results, and returns to the manager.
|
|
431
|
+
```
|
|
432
|
+
[Coordinator] delegating to worker
|
|
433
|
+
[Worker] Subtask complete
|
|
434
|
+
[Coordinator] Combining results and sending to manager
|
|
435
|
+
✅ Delegation chain complete: manager ← coordinator ← worker
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
### 5. 📊 Information Exchange
|
|
439
|
+
An agent requests sensor data twice, 2 seconds apart. Verifies both readings have different timestamps and values.
|
|
440
|
+
```
|
|
441
|
+
[Sensor] Reading #1: 21.3°C at 2026-02-15T04:16:48Z
|
|
442
|
+
[Sensor] Reading #2: 21.6°C at 2026-02-15T04:16:50Z
|
|
443
|
+
✅ Two readings received with different timestamps
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### 6. 🔐 Human Approval Flow
|
|
447
|
+
A purchase request for £500 triggers a human approval requirement (threshold: £100). Simulates the human approving before confirming.
|
|
448
|
+
```
|
|
449
|
+
[Approver] ⚠️ Amount £500 exceeds £100 — human approval required
|
|
450
|
+
[Approver] 👤 Human reviewed and APPROVED
|
|
451
|
+
✅ Human approval flow completed
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
---
|
|
455
|
+
|
|
456
|
+
## 🧪 Tests
|
|
457
|
+
|
|
458
|
+
```bash
|
|
459
|
+
cd src/
|
|
460
|
+
node test.js
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
```
|
|
464
|
+
✅ Passed: 146
|
|
465
|
+
❌ Failed: 0
|
|
466
|
+
⏭️ Skipped: 1 (mDNS requires multicast network)
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
---
|
|
470
|
+
|
|
471
|
+
## 🗺️ Roadmap
|
|
472
|
+
|
|
473
|
+
- [x] Protocol spec v0.1
|
|
474
|
+
- [x] Core implementation (server, client, handlers)
|
|
475
|
+
- [x] Ed25519 signing
|
|
476
|
+
- [x] X25519 encryption
|
|
477
|
+
- [x] Trust management
|
|
478
|
+
- [x] Message queuing with retry
|
|
479
|
+
- [x] 11 intent handlers
|
|
480
|
+
- [x] Network discovery (DNS, mDNS, well-known)
|
|
481
|
+
- [x] Conversation state machine
|
|
482
|
+
- [x] OpenClaw skill integration
|
|
483
|
+
- [x] Two-agent live demo
|
|
484
|
+
- [x] 146 tests passing
|
|
485
|
+
- [ ] Agent directory / registry
|
|
486
|
+
- [ ] ActivityPub bridge
|
|
487
|
+
- [ ] Multi-runtime SDKs (Python, Go)
|
|
488
|
+
- [ ] Mobile agent support
|
|
489
|
+
- [ ] Payment rails for commerce intent
|
|
490
|
+
- [ ] Hosted hub (managed endpoints)
|
|
491
|
+
|
|
492
|
+
---
|
|
493
|
+
|
|
494
|
+
## 🤔 FAQ
|
|
495
|
+
|
|
496
|
+
**Q: Does this need powerful models?**
|
|
497
|
+
A: No. qwen2:7b (free, local) handles structured JSON negotiation perfectly. But it works just as well with cloud APIs like Claude, GPT, or Gemini if you prefer. The protocol is model-agnostic — it's just JSON.
|
|
498
|
+
|
|
499
|
+
**Q: How is this different from MCP or ACP?**
|
|
500
|
+
A: MCP connects agents to tools. ACP connects agents to services. AI2AI connects agents to *each other*, acting as human representatives. It's the social layer.
|
|
501
|
+
|
|
502
|
+
**Q: What about bad actors?**
|
|
503
|
+
A: Human-in-the-loop by default. Your agent never commits without your approval. Same model as email — you can receive spam, but you don't have to open it.
|
|
504
|
+
|
|
505
|
+
**Q: Can non-OpenClaw agents use this?**
|
|
506
|
+
A: Yes. The protocol is a JSON HTTP API. Any agent framework can implement it.
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
## 📄 License
|
|
511
|
+
|
|
512
|
+
Apache 2.0 — Build on it. Fork it. Make it better. Patent protected.
|
|
513
|
+
|
|
514
|
+
---
|
|
515
|
+
|
|
516
|
+
## 🌍 The Vision
|
|
517
|
+
|
|
518
|
+
Email gave humans a decentralised way to communicate.
|
|
519
|
+
The web gave humans a decentralised way to publish.
|
|
520
|
+
**AI2AI gives AI agents a decentralised way to act on behalf of humans.**
|
|
521
|
+
|
|
522
|
+
No company should own the protocol by which our digital representatives talk to each other.
|
|
523
|
+
|
|
524
|
+
The protocol is the product. The simpler it is, the more people build on it.
|
|
525
|
+
|
|
526
|
+
**Built in one night. Open forever. 🦞**
|
package/logo.jpg
ADDED
|
Binary file
|