ai2ai 0.1.0 → 1.0.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/.keys/agent.key +3 -0
- package/.keys/agent.pub +3 -0
- package/.keys/x25519.key.der +0 -0
- package/.keys/x25519.pub.der +0 -0
- package/README.md +449 -107
- package/SKILL.md +39 -0
- package/ai2ai-client.js +351 -0
- package/ai2ai-conversations.js +324 -0
- package/{lib/crypto.js → ai2ai-crypto.js} +19 -39
- package/ai2ai-discovery.js +398 -0
- package/ai2ai-encryption.js +292 -0
- package/ai2ai-handlers.js +392 -0
- package/ai2ai-logger.js +148 -0
- package/ai2ai-queue.js +281 -0
- package/ai2ai-server.js +433 -0
- package/ai2ai-trust.js +137 -0
- package/client.js +434 -0
- package/contacts.example.json +45 -0
- package/contacts.json +57 -0
- package/conversations/06dfc9fc-e0fb-47a6-80ea-6f89b805dcc9.jsonl +1 -0
- package/conversations/06dfc9fc-e0fb-47a6-80ea-6f89b805dcc9.meta.json +31 -0
- package/conversations/132889ee-3c68-4a86-a465-829c467f6782.jsonl +1 -0
- package/conversations/132889ee-3c68-4a86-a465-829c467f6782.meta.json +27 -0
- package/conversations/16c99cf3-7250-4136-8d4a-f5214bcd32ba.jsonl +1 -0
- package/conversations/16c99cf3-7250-4136-8d4a-f5214bcd32ba.meta.json +27 -0
- package/conversations/3f62daf5-49cb-4f9b-9d25-de70625f46e2.jsonl +1 -0
- package/conversations/3f62daf5-49cb-4f9b-9d25-de70625f46e2.meta.json +31 -0
- package/conversations/532b39ab-d513-4e40-98ff-2d3df2d5f256.jsonl +1 -0
- package/conversations/532b39ab-d513-4e40-98ff-2d3df2d5f256.meta.json +27 -0
- package/conversations/5549dc7a-d62e-49f6-93b6-977da7908a11.jsonl +1 -0
- package/conversations/5549dc7a-d62e-49f6-93b6-977da7908a11.meta.json +27 -0
- package/conversations/610ab34a-c7f4-4d24-98b1-75e3f98835d3.jsonl +1 -0
- package/conversations/610ab34a-c7f4-4d24-98b1-75e3f98835d3.meta.json +31 -0
- package/conversations/611610be-28f2-4b31-9afc-b5e278334d8a.jsonl +1 -0
- package/conversations/611610be-28f2-4b31-9afc-b5e278334d8a.meta.json +27 -0
- package/conversations/69ed7660-73bc-4994-9070-db4b264ccd18.jsonl +1 -0
- package/conversations/69ed7660-73bc-4994-9070-db4b264ccd18.meta.json +27 -0
- package/conversations/85eb0bf1-8a1a-4e9b-8b98-963f6b274913.jsonl +1 -0
- package/conversations/85eb0bf1-8a1a-4e9b-8b98-963f6b274913.meta.json +27 -0
- package/conversations/8b1ee339-fcc5-4587-81cd-dc32ea69cfe0.jsonl +1 -0
- package/conversations/8b1ee339-fcc5-4587-81cd-dc32ea69cfe0.meta.json +31 -0
- package/conversations/9b628dc0-0a71-456b-9ba7-8ca2b0872c63.jsonl +1 -0
- package/conversations/9b628dc0-0a71-456b-9ba7-8ca2b0872c63.meta.json +27 -0
- package/conversations/ad3ef614-306b-414c-a5c5-ae0f2bd4e3d8.jsonl +1 -0
- package/conversations/ad3ef614-306b-414c-a5c5-ae0f2bd4e3d8.meta.json +27 -0
- package/conversations/b71f8bc4-3f34-4667-aad1-5ab899339fb0.jsonl +1 -0
- package/conversations/b71f8bc4-3f34-4667-aad1-5ab899339fb0.meta.json +27 -0
- package/conversations/daf8a65b-83eb-4f7e-8052-714457a8f6b0.jsonl +1 -0
- package/conversations/daf8a65b-83eb-4f7e-8052-714457a8f6b0.meta.json +27 -0
- package/conversations/f2728631-64b9-4267-a793-2d39e3ce8f5e.jsonl +1 -0
- package/conversations/f2728631-64b9-4267-a793-2d39e3ce8f5e.meta.json +27 -0
- package/conversations/test-conv-1771128087319.meta.json +27 -0
- package/conversations/test-conv-1771128515164.meta.json +27 -0
- package/conversations/test-conv-1771128546424.meta.json +27 -0
- package/conversations/test-conv-1771128606354.meta.json +27 -0
- package/conversations/test-group-1771128087322.meta.json +27 -0
- package/conversations/test-group-1771128515165.meta.json +27 -0
- package/conversations/test-group-1771128546425.meta.json +27 -0
- package/conversations/test-group-1771128606355.meta.json +27 -0
- package/demo-two-agents.js +395 -0
- package/integrations/express.js +96 -0
- package/integrations/openclaw.js +62 -0
- package/integrations/webhook.js +111 -0
- package/logo.jpg +0 -0
- package/logs/ai2ai-2026-02-15.log +40 -0
- package/openclaw-integration.js +540 -0
- package/package.json +17 -24
- package/package.json.bak +24 -0
- package/pending/139dcb76-7778-4130-b448-c7828184a53f.json +28 -0
- package/pending/187a69f5-9391-41d0-87d6-34d479a6cc50.json +28 -0
- package/pending/2d07e1bb-51f8-4e13-b08b-f1b5b1dc3d1e.json +34 -0
- package/pending/2d13bdf4-a818-4629-bfdf-ac29b1a64ba5.json +28 -0
- package/pending/3029f00d-97a4-4928-9ff8-3500541c381d.json +31 -0
- package/pending/37a3fddb-73e1-4b85-8de5-2def875216bf.json +34 -0
- package/pending/4babfd35-aba7-479f-bc0f-f0c83e31d3db.json +34 -0
- package/pending/602c0022-993a-4b8a-9ba9-04e56ec59bb5.json +34 -0
- package/pending/af925c5f-bed5-4a46-83c3-d16c97d47627.json +28 -0
- package/pending/ba1474fe-41b7-412e-b702-0b74307510b9.json +31 -0
- package/pending/bcf800f6-c5bb-44a9-8e39-195bd624ff92.json +31 -0
- package/pending/c6683665-1321-49ed-8d21-5ae4250848e8.json +31 -0
- package/registry.js +406 -0
- package/reliability.js +467 -0
- package/security.js +386 -0
- package/test-v1.js +540 -0
- package/test.js +705 -0
- package/bin/ai2ai.js +0 -87
- package/lib/approve.js +0 -137
- package/lib/config.js +0 -120
- package/lib/connect.js +0 -89
- package/lib/contacts.js +0 -62
- package/lib/init.js +0 -148
- package/lib/pending.js +0 -114
- package/lib/protocol.js +0 -161
- package/lib/send.js +0 -135
- package/lib/start.js +0 -318
- package/lib/status.js +0 -70
package/.keys/agent.key
ADDED
package/.keys/agent.pub
ADDED
|
Binary file
|
|
Binary file
|
package/README.md
CHANGED
|
@@ -1,184 +1,526 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/DarrenEdwards111/ai2ai-protocol/main/logo.jpg" alt="AI2AI Protocol" width="200" />
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<h1 align="center">AI2AI Protocol</h1>
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>Production-ready agent-to-agent communication protocol</strong><br>
|
|
9
|
+
Zero dependencies • Ed25519 signed • Encrypted • Discoverable
|
|
10
|
+
</p>
|
|
6
11
|
|
|
7
|
-
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="https://www.npmjs.com/package/ai2ai-protocol"><img src="https://img.shields.io/npm/v/ai2ai-protocol.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>
|
|
8
18
|
|
|
9
|
-
|
|
10
|
-
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
const { AI2AI } = require('ai2ai-protocol/src/client');
|
|
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!');
|
|
11
29
|
```
|
|
12
30
|
|
|
13
|
-
|
|
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
|
|
14
47
|
|
|
15
48
|
```bash
|
|
16
|
-
|
|
49
|
+
npm install ai2ai-protocol
|
|
17
50
|
```
|
|
18
51
|
|
|
19
|
-
|
|
52
|
+
Or clone directly:
|
|
53
|
+
```bash
|
|
54
|
+
git clone https://github.com/DarrenEdwards111/ai2ai-protocol.git
|
|
55
|
+
```
|
|
20
56
|
|
|
21
|
-
|
|
57
|
+
## Basic Usage
|
|
22
58
|
|
|
23
|
-
|
|
24
|
-
|
|
59
|
+
### Create an Agent
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
const { AI2AI } = require('ai2ai-protocol/src/client');
|
|
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();
|
|
25
81
|
```
|
|
26
82
|
|
|
27
|
-
|
|
83
|
+
### Send Messages
|
|
28
84
|
|
|
29
|
-
|
|
85
|
+
```js
|
|
86
|
+
// Add a contact
|
|
87
|
+
agent.addContact('bob-agent', { endpoint: 'http://localhost:18801/ai2ai' });
|
|
30
88
|
|
|
31
|
-
|
|
32
|
-
|
|
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
|
+
});
|
|
33
97
|
```
|
|
34
98
|
|
|
35
|
-
|
|
99
|
+
## Discovery
|
|
36
100
|
|
|
37
|
-
###
|
|
101
|
+
### Registry
|
|
38
102
|
|
|
39
|
-
```
|
|
40
|
-
|
|
103
|
+
```js
|
|
104
|
+
const { RegistryServer, RegistryClient } = require('ai2ai-protocol/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' });
|
|
41
121
|
```
|
|
42
122
|
|
|
43
|
-
|
|
123
|
+
### DNS TXT Record
|
|
44
124
|
|
|
45
|
-
|
|
125
|
+
Add a DNS TXT record:
|
|
126
|
+
```
|
|
127
|
+
_ai2ai.yourdomain.com TXT "endpoint=https://your-server.com/ai2ai"
|
|
128
|
+
```
|
|
46
129
|
|
|
47
|
-
|
|
48
|
-
# Simple message
|
|
49
|
-
ai2ai send alex "Hey, are you free this weekend?"
|
|
130
|
+
### Local Network (mDNS)
|
|
50
131
|
|
|
51
|
-
|
|
52
|
-
|
|
132
|
+
```js
|
|
133
|
+
const { startLocalDiscovery } = require('ai2ai-protocol/src/registry');
|
|
53
134
|
|
|
54
|
-
|
|
55
|
-
|
|
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();
|
|
56
141
|
```
|
|
57
142
|
|
|
58
|
-
|
|
59
|
-
- **Scheduling keywords** → `schedule.meeting` intent
|
|
60
|
-
- **Questions** → `info.request` intent
|
|
61
|
-
- **Everything else** → `message.relay` intent
|
|
143
|
+
## Security Model
|
|
62
144
|
|
|
63
|
-
|
|
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-protocol/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
|
+
```
|
|
64
171
|
|
|
65
|
-
|
|
66
|
-
|
|
172
|
+
### Webhooks
|
|
173
|
+
|
|
174
|
+
```js
|
|
175
|
+
const { createWebhookForwarder } = require('ai2ai-protocol/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-protocol/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
|
|
67
232
|
```
|
|
68
233
|
|
|
69
|
-
###
|
|
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
|
|
70
276
|
|
|
71
277
|
```bash
|
|
72
|
-
|
|
73
|
-
|
|
278
|
+
cd src
|
|
279
|
+
node test.js # Original 146 tests
|
|
280
|
+
node test-v1.js # New v1.0 tests (110 tests)
|
|
74
281
|
```
|
|
75
282
|
|
|
76
|
-
##
|
|
283
|
+
## Contributing
|
|
77
284
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
|
89
327
|
|
|
90
|
-
|
|
328
|
+
---
|
|
91
329
|
|
|
92
|
-
|
|
330
|
+
## 📨 Message Format
|
|
331
|
+
|
|
332
|
+
Every AI2AI message is a JSON envelope:
|
|
93
333
|
|
|
94
334
|
```json
|
|
95
335
|
{
|
|
96
336
|
"ai2ai": "0.1",
|
|
97
337
|
"id": "uuid",
|
|
98
|
-
"timestamp": "
|
|
338
|
+
"timestamp": "2026-02-07T19:00:00Z",
|
|
99
339
|
"from": {
|
|
100
340
|
"agent": "darren-assistant",
|
|
101
|
-
"node": "darren-assistant-node",
|
|
102
341
|
"human": "Darren"
|
|
103
342
|
},
|
|
104
343
|
"to": {
|
|
105
344
|
"agent": "alex-assistant",
|
|
106
|
-
"node": "alex-assistant-node",
|
|
107
345
|
"human": "Alex"
|
|
108
346
|
},
|
|
109
|
-
"conversation": "uuid",
|
|
347
|
+
"conversation": "conv-uuid",
|
|
110
348
|
"type": "request",
|
|
111
|
-
"intent": "
|
|
112
|
-
"payload": {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
"reply_requested": true
|
|
116
|
-
},
|
|
117
|
-
"signature": "base64-ed25519-signature"
|
|
349
|
+
"intent": "schedule.meeting",
|
|
350
|
+
"payload": { ... },
|
|
351
|
+
"requires_human_approval": true,
|
|
352
|
+
"signature": "ed25519-signature"
|
|
118
353
|
}
|
|
119
354
|
```
|
|
120
355
|
|
|
121
|
-
|
|
356
|
+
Message types: `ping` | `request` | `response` | `confirm` | `reject` | `inform`
|
|
122
357
|
|
|
123
|
-
|
|
124
|
-
- **`request`** — Ask another agent to do something
|
|
125
|
-
- **`response`** — Reply to a request
|
|
126
|
-
- **`confirm`** — Accept a proposal
|
|
127
|
-
- **`reject`** — Decline a proposal
|
|
128
|
-
- **`inform`** — One-way notification
|
|
358
|
+
---
|
|
129
359
|
|
|
130
|
-
|
|
360
|
+
## 🏗️ Architecture
|
|
131
361
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
+
```
|
|
138
374
|
|
|
139
|
-
|
|
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
|
|
140
387
|
|
|
141
|
-
|
|
142
|
-
- **Key exchange** — Public keys are exchanged during the `connect` handshake
|
|
143
|
-
- **Signature verification** — Incoming messages from known contacts are verified
|
|
144
|
-
- **Trust levels** — Contacts have trust levels (`none`, `known`, `trusted`)
|
|
145
|
-
- **Rate limiting** — 20 messages per minute per agent
|
|
146
|
-
- **Human approval** — All incoming requests go to a pending queue for human review
|
|
388
|
+
---
|
|
147
389
|
|
|
148
|
-
##
|
|
390
|
+
## 🎯 Real-World Scenarios
|
|
149
391
|
|
|
150
|
-
|
|
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
|
+
```
|
|
151
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.
|
|
152
406
|
```
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
│ ├── agent.pub # Ed25519 public key
|
|
158
|
-
│ └── agent.key # Ed25519 private key (mode 0600)
|
|
159
|
-
├── pending/ # Messages awaiting approval
|
|
160
|
-
├── conversations/ # Conversation history
|
|
161
|
-
└── logs/ # Server logs
|
|
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
|
|
162
411
|
```
|
|
163
412
|
|
|
164
|
-
|
|
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
|
+
```
|
|
165
428
|
|
|
166
|
-
|
|
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
|
+
```
|
|
167
437
|
|
|
438
|
+
### 5. 📊 Information Exchange
|
|
439
|
+
An agent requests sensor data twice, 2 seconds apart. Verifies both readings have different timestamps and values.
|
|
168
440
|
```
|
|
169
|
-
|
|
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
|
|
170
444
|
```
|
|
171
445
|
|
|
172
|
-
|
|
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
|
+
```
|
|
173
453
|
|
|
174
|
-
|
|
175
|
-
- **Zero external dependencies** — Uses only Node.js built-in modules
|
|
454
|
+
---
|
|
176
455
|
|
|
177
|
-
##
|
|
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.**
|
|
178
521
|
|
|
179
|
-
|
|
522
|
+
No company should own the protocol by which our digital representatives talk to each other.
|
|
180
523
|
|
|
181
|
-
|
|
524
|
+
The protocol is the product. The simpler it is, the more people build on it.
|
|
182
525
|
|
|
183
|
-
|
|
184
|
-
- [Report Issues](https://github.com/DarrenEdwards111/ai2ai-protocol/issues)
|
|
526
|
+
**Built in one night. Open forever. 🦞**
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# AI2AI — Agent-to-Agent Communication Skill
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
Enables your OpenClaw agent to communicate with other AI agents on behalf of your human. Implements the AI2AI protocol for decentralized agent negotiation.
|
|
5
|
+
|
|
6
|
+
## Commands
|
|
7
|
+
|
|
8
|
+
The human can say:
|
|
9
|
+
- **"Talk to [name]'s AI at [address]"** — Initiate handshake with another agent
|
|
10
|
+
- **"Schedule [event] with [name]"** — Start a schedule negotiation
|
|
11
|
+
- **"Send [name] a message via their AI"** — Relay a message through agents
|
|
12
|
+
- **"Show AI2AI contacts"** — List known agents
|
|
13
|
+
- **"AI2AI status"** — Show connection status and recent conversations
|
|
14
|
+
|
|
15
|
+
## How It Works
|
|
16
|
+
|
|
17
|
+
1. Human tells their agent what they want
|
|
18
|
+
2. Agent formats an AI2AI message and sends it to the other agent's endpoint
|
|
19
|
+
3. Other agent receives it, interprets it, and asks their human
|
|
20
|
+
4. Response comes back
|
|
21
|
+
5. Your agent tells you the result
|
|
22
|
+
|
|
23
|
+
All communication is structured JSON. Humans approve everything (unless trust is elevated).
|
|
24
|
+
|
|
25
|
+
## Files
|
|
26
|
+
- `ai2ai-server.js` — HTTP endpoint that receives incoming AI2AI messages
|
|
27
|
+
- `ai2ai-client.js` — Sends outgoing AI2AI messages
|
|
28
|
+
- `ai2ai-handlers.js` — Intent handlers (schedule, message, etc.)
|
|
29
|
+
- `ai2ai-trust.js` — Trust management and approval flow
|
|
30
|
+
- `ai2ai-crypto.js` — Ed25519 signing and verification
|
|
31
|
+
- `contacts.json` — Known agents and trust levels
|
|
32
|
+
- `conversations/` — Conversation history
|
|
33
|
+
|
|
34
|
+
## Configuration
|
|
35
|
+
Set in your OpenClaw config or via environment:
|
|
36
|
+
- `AI2AI_PORT` — Port for incoming connections (default: 18800)
|
|
37
|
+
- `AI2AI_AGENT_NAME` — Your agent's display name
|
|
38
|
+
- `AI2AI_HUMAN_NAME` — Your human's display name
|
|
39
|
+
- `AI2AI_TIMEZONE` — Your timezone
|