multi-agent-protocol 0.0.4 → 0.0.6
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/docs/07-federation.md +81 -5
- package/docs/09-authentication.md +68 -0
- package/docs/10-environment-awareness.md +242 -0
- package/docs/11-anp-inspired-improvements.md +1079 -0
- package/docs/12-anp-implementation-plan.md +641 -0
- package/package.json +1 -1
- package/schema/meta.json +70 -2
- package/schema/schema.json +521 -12
package/docs/07-federation.md
CHANGED
|
@@ -206,18 +206,94 @@ Sensitive computation isolated in secure system, federated for I/O.
|
|
|
206
206
|
|
|
207
207
|
---
|
|
208
208
|
|
|
209
|
+
## Single-Request Federation Auth
|
|
210
|
+
|
|
211
|
+
Federation connection can be completed in a single round-trip by including auth credentials in the initial `map/federation/connect` request. When the server can validate the credentials immediately, it returns a fully authenticated response — reducing setup from 2 RTT to 1 RTT.
|
|
212
|
+
|
|
213
|
+
### Flow: Single-Request Auth (Optimized)
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
System A System B
|
|
217
|
+
│ │
|
|
218
|
+
│──── map/federation/connect ─────────────────►│
|
|
219
|
+
│ { systemId, endpoint, auth: { ... } } │
|
|
220
|
+
│ │ ← Validates auth inline
|
|
221
|
+
│◄─── response ────────────────────────────────│
|
|
222
|
+
│ { connected: true, sessionId, principal } │
|
|
223
|
+
│ │
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Flow: Auth Negotiation Fallback
|
|
227
|
+
|
|
228
|
+
If no credentials are provided, or validation fails recoverably, the server returns auth requirements:
|
|
229
|
+
|
|
230
|
+
```
|
|
231
|
+
System A System B
|
|
232
|
+
│ │
|
|
233
|
+
│──── map/federation/connect ─────────────────►│
|
|
234
|
+
│ { systemId, endpoint } │
|
|
235
|
+
│ │
|
|
236
|
+
│◄─── response ────────────────────────────────│
|
|
237
|
+
│ { connected: false, │
|
|
238
|
+
│ authRequired: { methods, challenge } } │
|
|
239
|
+
│ │
|
|
240
|
+
│──── map/federation/connect ─────────────────►│
|
|
241
|
+
│ { systemId, endpoint, auth: { ... }, │
|
|
242
|
+
│ authContext: { challenge } } │
|
|
243
|
+
│ │
|
|
244
|
+
│◄─── response ────────────────────────────────│
|
|
245
|
+
│ { connected: true, sessionId, principal } │
|
|
246
|
+
│ │
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
209
251
|
## Security Considerations
|
|
210
252
|
|
|
211
253
|
### Authentication
|
|
212
254
|
|
|
213
255
|
```typescript
|
|
256
|
+
type FederationAuthMethod =
|
|
257
|
+
| "bearer" | "api-key" | "mtls" | "none"
|
|
258
|
+
| "did:wba" | "oauth2" | `x-${string}`;
|
|
259
|
+
|
|
214
260
|
type MAPFederationAuth =
|
|
215
|
-
| { method:
|
|
216
|
-
|
|
|
217
|
-
|
|
218
|
-
|
|
261
|
+
| { method: FederationAuthMethod; credentials?: string; metadata?: Record<string, unknown> }
|
|
262
|
+
| DIDWBACredentials;
|
|
263
|
+
|
|
264
|
+
interface DIDWBACredentials {
|
|
265
|
+
method: "did:wba";
|
|
266
|
+
metadata: { did: string; proof: DIDWBAProof };
|
|
267
|
+
}
|
|
219
268
|
```
|
|
220
269
|
|
|
270
|
+
#### `did:wba` — Decentralized Identity for Federation
|
|
271
|
+
|
|
272
|
+
The `did:wba` method enables domain-anchored decentralized identity for federation. An identity like `did:wba:agents.example.com:gateway` resolves to a DID document at `https://agents.example.com/gateway/did.json` containing public keys and MAP service endpoints.
|
|
273
|
+
|
|
274
|
+
**Authentication flow:**
|
|
275
|
+
1. Connecting system provides its DID and a cryptographic proof (ECDSA P-256 over challenge nonce)
|
|
276
|
+
2. Receiving system resolves the DID document via HTTPS
|
|
277
|
+
3. Receiving system verifies the proof against the public key in the DID document
|
|
278
|
+
4. On success, the connecting system is authenticated as the DID principal
|
|
279
|
+
|
|
280
|
+
```json
|
|
281
|
+
{
|
|
282
|
+
"method": "did:wba",
|
|
283
|
+
"metadata": {
|
|
284
|
+
"did": "did:wba:agents.example.com:gateway",
|
|
285
|
+
"proof": {
|
|
286
|
+
"type": "JsonWebSignature2020",
|
|
287
|
+
"created": "2026-02-10T12:00:00.000Z",
|
|
288
|
+
"challenge": "map_chal_01ABCDEFGHJ0123456789AB",
|
|
289
|
+
"jws": "eyJhbGciOi..."
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
See `docs/09-authentication.md` for full details on all auth methods including `did:wba`, and `docs/11-anp-inspired-improvements.md` Proposal 1 for the design rationale.
|
|
296
|
+
|
|
221
297
|
### Message Signing
|
|
222
298
|
|
|
223
299
|
```typescript
|
|
@@ -253,7 +329,7 @@ interface MAPFederationQueueConfig {
|
|
|
253
329
|
## Open Questions
|
|
254
330
|
|
|
255
331
|
1. **Transitive federation**: If A↔B and B↔C, can A route to C via B?
|
|
256
|
-
2.
|
|
332
|
+
2. ~~**Federation discovery**: Should there be a discovery mechanism for finding peers?~~ — Partially addressed by `did:wba` (DID document service endpoints) and proposed `.well-known` discovery (see `docs/11-anp-inspired-improvements.md` Proposal 2).
|
|
257
333
|
3. **Consistency**: How to handle concurrent updates across federated systems?
|
|
258
334
|
4. **Schema versioning**: What if peers have different protocol versions?
|
|
259
335
|
5. **Audit requirements**: What federation activity must be logged?
|
|
@@ -22,6 +22,7 @@ MAP defines the following standard authentication methods:
|
|
|
22
22
|
| `bearer` | Bearer token (JWT or opaque) | OAuth2, IdP integration, M2M tokens |
|
|
23
23
|
| `api-key` | Simple API key | Simple integrations, internal services |
|
|
24
24
|
| `mtls` | Mutual TLS (transport layer) | High-security service-to-service |
|
|
25
|
+
| `did:wba` | DID-based, domain-anchored | Cross-org federation, open discovery |
|
|
25
26
|
|
|
26
27
|
### Extension Methods
|
|
27
28
|
|
|
@@ -384,6 +385,54 @@ For trusted local connections.
|
|
|
384
385
|
- Reject `none` based on transport type (e.g., require auth for WebSocket)
|
|
385
386
|
- Assign a default principal for anonymous connections
|
|
386
387
|
|
|
388
|
+
### DID:WBA (`did:wba`)
|
|
389
|
+
|
|
390
|
+
Domain-anchored decentralized identity based on the W3C `did:wba` method. Identity is derived from domain ownership: a DID like `did:wba:agents.example.com:gateway` resolves to a DID document hosted at `https://agents.example.com/gateway/did.json`.
|
|
391
|
+
|
|
392
|
+
**Credential format:** DID and cryptographic proof in metadata
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
{
|
|
396
|
+
"method": "did:wba",
|
|
397
|
+
"metadata": {
|
|
398
|
+
"did": "did:wba:agents.example.com:gateway",
|
|
399
|
+
"proof": {
|
|
400
|
+
"type": "JsonWebSignature2020",
|
|
401
|
+
"created": "2026-02-10T12:00:00.000Z",
|
|
402
|
+
"challenge": "map_chal_01ABCDEFGHJ0123456789AB",
|
|
403
|
+
"jws": "base64url-encoded-ecdsa-signature"
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
**DID Document:** The resolved DID document MUST contain:
|
|
410
|
+
- `verificationMethod` with the public key used to verify the proof
|
|
411
|
+
- `authentication` referencing the verification method
|
|
412
|
+
- Optionally, a `service` entry of type `MAPFederationEndpoint` with the MAP WebSocket URL
|
|
413
|
+
|
|
414
|
+
**Proof verification:**
|
|
415
|
+
1. Server generates a challenge nonce (format: `map_chal_<ULID>`)
|
|
416
|
+
2. Client signs `challenge.did.created` using ECDSA P-256 with its private key
|
|
417
|
+
3. Server resolves DID → fetches DID document → extracts public key
|
|
418
|
+
4. Server verifies the JWS signature against the public key and checks proof freshness
|
|
419
|
+
|
|
420
|
+
**Security considerations:**
|
|
421
|
+
- DID documents are fetched over HTTPS — domain ownership proves identity
|
|
422
|
+
- Proof freshness is enforced via the `created` timestamp (default max age: 5 minutes)
|
|
423
|
+
- Servers MAY maintain a trusted domains list to restrict accepted DIDs
|
|
424
|
+
- DID document caching with configurable TTL prevents excessive lookups
|
|
425
|
+
|
|
426
|
+
**When to use:**
|
|
427
|
+
- Cross-organization federation where pre-shared credentials are impractical
|
|
428
|
+
- Open discovery scenarios where peers find each other via DID documents
|
|
429
|
+
- Systems that need globally unique, verifiable agent identities
|
|
430
|
+
|
|
431
|
+
**SDK support:**
|
|
432
|
+
- `DIDWBAAuthenticator` — server-side authenticator (see `ts-sdk/src/server/auth/did-wba-authenticator.ts`)
|
|
433
|
+
- `generateDIDWBAProof()` / `verifyDIDWBAProof()` — proof utilities (see `ts-sdk/src/federation/did-wba/proof.ts`)
|
|
434
|
+
- `DIDWBAResolver` — DID document resolution with caching (see `ts-sdk/src/federation/did-wba/resolver.ts`)
|
|
435
|
+
|
|
387
436
|
---
|
|
388
437
|
|
|
389
438
|
## Token Refresh
|
|
@@ -670,6 +719,25 @@ const server = new MAPServer({
|
|
|
670
719
|
});
|
|
671
720
|
```
|
|
672
721
|
|
|
722
|
+
### Example 5: Federation Server with DID:WBA
|
|
723
|
+
|
|
724
|
+
```typescript
|
|
725
|
+
import { DIDWBAAuthenticator } from '@anthropic/multi-agent-protocol/server/auth';
|
|
726
|
+
|
|
727
|
+
const server = new MAPServer({
|
|
728
|
+
auth: {
|
|
729
|
+
required: true,
|
|
730
|
+
methods: ['did:wba', 'bearer'],
|
|
731
|
+
authenticators: [
|
|
732
|
+
new DIDWBAAuthenticator({
|
|
733
|
+
trustedDomains: ['*.example.com', 'partner.org'],
|
|
734
|
+
}),
|
|
735
|
+
new JWTAuthenticator({ /* ... */ })
|
|
736
|
+
]
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
```
|
|
740
|
+
|
|
673
741
|
---
|
|
674
742
|
|
|
675
743
|
## Open Questions
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# Environment Awareness
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Environment awareness enables agents to advertise and discover information about their compute environments. This facilitates intelligent task routing, filesystem coordination, and resource-aware scheduling in heterogeneous multi-agent systems.
|
|
6
|
+
|
|
7
|
+
## Motivation
|
|
8
|
+
|
|
9
|
+
Agents may run across diverse environments:
|
|
10
|
+
- Different mount points (Agent A at `/home/user/project`, Agent B at `/workspace/project`)
|
|
11
|
+
- Different compute types (local, Docker, Kubernetes, cloud sandbox)
|
|
12
|
+
- Different capabilities (GPU, specific tools, network access)
|
|
13
|
+
- Different constraints (memory limits, ephemeral storage, execution timeouts)
|
|
14
|
+
|
|
15
|
+
Environment awareness enables:
|
|
16
|
+
- **Task routing**: Send GPU workloads to GPU-enabled agents
|
|
17
|
+
- **Filesystem coordination**: Detect shared mounts vs. need for explicit file transfer
|
|
18
|
+
- **Resource optimization**: Choose agents based on cost, latency, or capacity
|
|
19
|
+
- **Security boundaries**: Route sensitive data to appropriately isolated agents
|
|
20
|
+
|
|
21
|
+
## Schema
|
|
22
|
+
|
|
23
|
+
The `AgentEnvironment` type uses a layered approach:
|
|
24
|
+
|
|
25
|
+
- **Layer 1 (Normative)**: Category names are standardized
|
|
26
|
+
- **Layer 2 (Conventions)**: Field names within categories are recommended patterns
|
|
27
|
+
- **Layer 3 (Extensions)**: Custom fields allowed via `additionalProperties`
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
interface AgentEnvironment {
|
|
31
|
+
schemaVersion?: string; // Schema version (e.g., "1.0")
|
|
32
|
+
profiles?: string[]; // Self-declared compliance (e.g., ["cloud-native"])
|
|
33
|
+
|
|
34
|
+
// Standard categories (all optional, all extensible)
|
|
35
|
+
host?: Record<string, unknown>; // CPU, memory, GPU
|
|
36
|
+
os?: Record<string, unknown>; // OS type, version
|
|
37
|
+
process?: Record<string, unknown>; // PID, cwd, runtime
|
|
38
|
+
container?: Record<string, unknown>; // Container runtime info
|
|
39
|
+
cloud?: Record<string, unknown>; // Provider, region, instance type
|
|
40
|
+
k8s?: Record<string, unknown>; // Kubernetes context
|
|
41
|
+
filesystem?: Record<string, unknown>; // Mounts, workspace, VCS
|
|
42
|
+
network?: Record<string, unknown>; // Connectivity, addresses
|
|
43
|
+
tools?: Record<string, unknown>; // Installed tools, runtimes
|
|
44
|
+
resources?: Record<string, unknown>; // Limits and constraints
|
|
45
|
+
security?: Record<string, unknown>; // Isolation, compliance
|
|
46
|
+
services?: Record<string, unknown>; // External APIs, MCP servers
|
|
47
|
+
|
|
48
|
+
[key: string]: unknown; // Additional categories allowed
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Common Field Conventions
|
|
53
|
+
|
|
54
|
+
These field names are **recommended** (not required) for interoperability:
|
|
55
|
+
|
|
56
|
+
| Category | Common Fields |
|
|
57
|
+
|----------|--------------|
|
|
58
|
+
| `host` | `arch`, `cpuCount`, `memoryBytes`, `gpu.count`, `gpu.models` |
|
|
59
|
+
| `os` | `type` (linux/darwin/windows), `version`, `name` |
|
|
60
|
+
| `process` | `pid`, `cwd`, `runtimeName`, `runtimeVersion` |
|
|
61
|
+
| `cloud` | `provider`, `region`, `instanceType`, `accountId` |
|
|
62
|
+
| `network` | `connectivity` (full/restricted/internal/isolated), `addresses` |
|
|
63
|
+
| `filesystem` | `cwd`, `mounts`, `workspace.root`, `workspace.vcs`, `workspace.branch` |
|
|
64
|
+
| `tools` | `installed`, `shell`, `runtimes`, `canInstall` |
|
|
65
|
+
| `resources` | `cpuLimit`, `memoryLimitBytes`, `maxExecutionSeconds`, `costProfile` |
|
|
66
|
+
| `security` | `isolation`, `privileged`, `sandbox`, `dataResidency` |
|
|
67
|
+
| `services` | `aiProviders`, `mcp` (MCP servers) |
|
|
68
|
+
|
|
69
|
+
## Protocol Integration
|
|
70
|
+
|
|
71
|
+
### Agent Registration
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
await connection.register({
|
|
75
|
+
name: 'my-agent',
|
|
76
|
+
environment: {
|
|
77
|
+
schemaVersion: '1.0',
|
|
78
|
+
os: { type: 'linux', version: '22.04' },
|
|
79
|
+
process: { cwd: '/home/user/project' },
|
|
80
|
+
network: { connectivity: 'full' },
|
|
81
|
+
tools: {
|
|
82
|
+
installed: { python: '3.11', node: '20.0' },
|
|
83
|
+
shell: 'bash'
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Connect Response
|
|
90
|
+
|
|
91
|
+
Servers can advertise their environment:
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
interface ConnectResponse {
|
|
95
|
+
// ... existing fields
|
|
96
|
+
serverEnvironment?: AgentEnvironment;
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Environment Updates
|
|
101
|
+
|
|
102
|
+
Agents can update their environment via `map/agents/update`:
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
await connection.update({
|
|
106
|
+
agentId: myAgentId,
|
|
107
|
+
environment: {
|
|
108
|
+
resources: { memoryLimitBytes: 8589934592 } // Updated
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Event: `agent_environment_changed`
|
|
114
|
+
|
|
115
|
+
Emitted when an agent's environment changes:
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
{
|
|
119
|
+
type: 'agent_environment_changed',
|
|
120
|
+
data: {
|
|
121
|
+
agentId: 'agent-123',
|
|
122
|
+
environment: { /* current */ },
|
|
123
|
+
previousEnvironment: { /* previous */ }
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Subscription Filtering
|
|
129
|
+
|
|
130
|
+
Filter events by environment attributes:
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
await client.subscribe({
|
|
134
|
+
filter: {
|
|
135
|
+
eventTypes: ['agent_registered'],
|
|
136
|
+
environmentMatch: {
|
|
137
|
+
'os.type': 'linux',
|
|
138
|
+
'cloud.provider': 'aws'
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Extension Patterns
|
|
145
|
+
|
|
146
|
+
### Adding fields to categories
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"host": {
|
|
151
|
+
"arch": "arm64",
|
|
152
|
+
"memoryBytes": 17179869184,
|
|
153
|
+
"x-apple-silicon": { "chip": "M2 Pro" }
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Adding new categories
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"schemaVersion": "1.0",
|
|
163
|
+
"os": { "type": "linux" },
|
|
164
|
+
"x-anthropic-sandbox": {
|
|
165
|
+
"sandboxId": "sb-abc123",
|
|
166
|
+
"tier": "premium"
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Services with custom providers
|
|
172
|
+
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"services": {
|
|
176
|
+
"aiProviders": {
|
|
177
|
+
"huggingface": { "available": true, "tier": "pro" },
|
|
178
|
+
"openai": { "available": true }
|
|
179
|
+
},
|
|
180
|
+
"mcp": {
|
|
181
|
+
"filesystem": { "available": true, "tools": ["read_file", "write_file"] }
|
|
182
|
+
},
|
|
183
|
+
"x-internal": {
|
|
184
|
+
"userService": { "available": true }
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Use Cases
|
|
191
|
+
|
|
192
|
+
### Task Routing by Capability
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
const agents = await client.agents.list();
|
|
196
|
+
const gpuAgent = agents.find(a =>
|
|
197
|
+
a.environment?.host?.gpu?.count > 0
|
|
198
|
+
);
|
|
199
|
+
if (gpuAgent) {
|
|
200
|
+
await client.send({ to: gpuAgent.id, payload: mlTask });
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Filesystem Coordination
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
// Check if agents share a filesystem
|
|
208
|
+
const myMounts = myAgent.environment?.filesystem?.mounts ?? {};
|
|
209
|
+
const peerMounts = peerAgent.environment?.filesystem?.mounts ?? {};
|
|
210
|
+
|
|
211
|
+
const sharedMount = Object.keys(myMounts).find(name =>
|
|
212
|
+
myMounts[name]?.shared && peerMounts[name]?.shared
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
if (sharedMount) {
|
|
216
|
+
// Can use file paths directly
|
|
217
|
+
} else {
|
|
218
|
+
// Need to transfer file contents via messages
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Network-Aware Routing
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
const agents = await client.agents.list();
|
|
226
|
+
const internetAgent = agents.find(a =>
|
|
227
|
+
a.environment?.network?.connectivity === 'full'
|
|
228
|
+
);
|
|
229
|
+
// Route external API calls through this agent
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Security Considerations
|
|
233
|
+
|
|
234
|
+
1. **Sensitive data**: Filter environment variables before exposing (no API keys, tokens)
|
|
235
|
+
2. **Opt-in exposure**: Agents explicitly choose what to advertise
|
|
236
|
+
3. **Visibility rules**: Environment respects existing MAP visibility/permissions
|
|
237
|
+
4. **Trust boundaries**: Don't implicitly trust environment claims from untrusted agents
|
|
238
|
+
|
|
239
|
+
## References
|
|
240
|
+
|
|
241
|
+
- [OpenTelemetry Resource Semantic Conventions](https://opentelemetry.io/docs/specs/semconv/resource/)
|
|
242
|
+
- [Kubernetes Node Feature Discovery](https://kubernetes-sigs.github.io/node-feature-discovery/)
|