macro-agent 0.0.13 → 0.0.15
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/.claude/settings.local.json +59 -0
- package/dist/agent/agent-manager.d.ts.map +1 -1
- package/dist/agent/agent-manager.js +10 -4
- package/dist/agent/agent-manager.js.map +1 -1
- package/dist/cli/acp.d.ts +6 -0
- package/dist/cli/acp.d.ts.map +1 -1
- package/dist/cli/acp.js +16 -2
- package/dist/cli/acp.js.map +1 -1
- package/dist/map/adapter/index.d.ts +1 -1
- package/dist/map/adapter/index.d.ts.map +1 -1
- package/dist/map/adapter/index.js +1 -1
- package/dist/map/adapter/index.js.map +1 -1
- package/dist/map/utils/address-translation.d.ts +99 -0
- package/dist/map/utils/address-translation.d.ts.map +1 -0
- package/dist/map/utils/address-translation.js +285 -0
- package/dist/map/utils/address-translation.js.map +1 -0
- package/dist/map/utils/index.d.ts +7 -0
- package/dist/map/utils/index.d.ts.map +1 -0
- package/dist/map/utils/index.js +7 -0
- package/dist/map/utils/index.js.map +1 -0
- package/dist/server/combined-server.d.ts.map +1 -1
- package/dist/server/combined-server.js +8 -1
- package/dist/server/combined-server.js.map +1 -1
- package/dist/store/event-store.js +9 -2
- package/dist/store/event-store.js.map +1 -1
- package/dist/store/types/agents.d.ts +2 -0
- package/dist/store/types/agents.d.ts.map +1 -1
- package/package.json +4 -4
- package/references/acp-factory-ref/CHANGELOG.md +33 -0
- package/references/acp-factory-ref/LICENSE +21 -0
- package/references/acp-factory-ref/README.md +341 -0
- package/references/acp-factory-ref/package-lock.json +3102 -0
- package/references/acp-factory-ref/package.json +96 -0
- package/references/acp-factory-ref/python/CHANGELOG.md +33 -0
- package/references/acp-factory-ref/python/LICENSE +21 -0
- package/references/acp-factory-ref/python/Makefile +57 -0
- package/references/acp-factory-ref/python/README.md +253 -0
- package/references/acp-factory-ref/python/pyproject.toml +73 -0
- package/references/acp-factory-ref/python/tests/__init__.py +0 -0
- package/references/acp-factory-ref/python/tests/e2e/__init__.py +1 -0
- package/references/acp-factory-ref/python/tests/e2e/test_codex_e2e.py +349 -0
- package/references/acp-factory-ref/python/tests/e2e/test_gemini_e2e.py +165 -0
- package/references/acp-factory-ref/python/tests/e2e/test_opencode_e2e.py +296 -0
- package/references/acp-factory-ref/python/tests/test_client_handler.py +543 -0
- package/references/acp-factory-ref/python/tests/test_pushable.py +199 -0
- package/references/claude-code-acp/.github/workflows/ci.yml +45 -0
- package/references/claude-code-acp/.github/workflows/publish.yml +34 -0
- package/references/claude-code-acp/.prettierrc.json +4 -0
- package/references/claude-code-acp/CHANGELOG.md +249 -0
- package/references/claude-code-acp/LICENSE +222 -0
- package/references/claude-code-acp/README.md +53 -0
- package/references/claude-code-acp/docs/RELEASES.md +24 -0
- package/references/claude-code-acp/eslint.config.js +48 -0
- package/references/claude-code-acp/package-lock.json +4570 -0
- package/references/claude-code-acp/package.json +88 -0
- package/references/claude-code-acp/scripts/release.sh +119 -0
- package/references/claude-code-acp/src/acp-agent.ts +2079 -0
- package/references/claude-code-acp/src/index.ts +26 -0
- package/references/claude-code-acp/src/lib.ts +38 -0
- package/references/claude-code-acp/src/mcp-server.ts +911 -0
- package/references/claude-code-acp/src/settings.ts +522 -0
- package/references/claude-code-acp/src/tests/.claude/commands/quick-math.md +5 -0
- package/references/claude-code-acp/src/tests/.claude/commands/say-hello.md +6 -0
- package/references/claude-code-acp/src/tests/acp-agent-fork.test.ts +479 -0
- package/references/claude-code-acp/src/tests/acp-agent.test.ts +1502 -0
- package/references/claude-code-acp/src/tests/extract-lines.test.ts +103 -0
- package/references/claude-code-acp/src/tests/fork-session.test.ts +335 -0
- package/references/claude-code-acp/src/tests/replace-and-calculate-location.test.ts +334 -0
- package/references/claude-code-acp/src/tests/settings.test.ts +617 -0
- package/references/claude-code-acp/src/tests/skills-options.test.ts +187 -0
- package/references/claude-code-acp/src/tests/tools.test.ts +318 -0
- package/references/claude-code-acp/src/tests/typescript-declarations.test.ts +558 -0
- package/references/claude-code-acp/src/tools.ts +819 -0
- package/references/claude-code-acp/src/utils.ts +171 -0
- package/references/claude-code-acp/tsconfig.json +18 -0
- package/references/claude-code-acp/vitest.config.ts +19 -0
- package/references/multi-agent-protocol/.sudocode/issues.jsonl +111 -0
- package/references/multi-agent-protocol/.sudocode/specs.jsonl +13 -0
- package/references/multi-agent-protocol/LICENSE +21 -0
- package/references/multi-agent-protocol/README.md +113 -0
- package/references/multi-agent-protocol/docs/00-design-specification.md +496 -0
- package/references/multi-agent-protocol/docs/01-open-questions.md +1050 -0
- package/references/multi-agent-protocol/docs/02-wire-protocol.md +296 -0
- package/references/multi-agent-protocol/docs/03-streaming-semantics.md +252 -0
- package/references/multi-agent-protocol/docs/04-error-handling.md +231 -0
- package/references/multi-agent-protocol/docs/05-connection-model.md +244 -0
- package/references/multi-agent-protocol/docs/06-visibility-permissions.md +243 -0
- package/references/multi-agent-protocol/docs/07-federation.md +259 -0
- package/references/multi-agent-protocol/docs/08-macro-agent-migration.md +253 -0
- package/references/multi-agent-protocol/docs/09-authentication.md +680 -0
- package/references/multi-agent-protocol/docs/10-mail-protocol.md +553 -0
- package/references/multi-agent-protocol/docs/agent-iam-integration.md +877 -0
- package/references/multi-agent-protocol/docs/agentic-mesh-integration-draft.md +459 -0
- package/references/multi-agent-protocol/docs/git-transport-draft.md +251 -0
- package/references/multi-agent-protocol/docs-site/Gemfile +22 -0
- package/references/multi-agent-protocol/docs-site/README.md +82 -0
- package/references/multi-agent-protocol/docs-site/_config.yml +91 -0
- package/references/multi-agent-protocol/docs-site/_includes/head_custom.html +20 -0
- package/references/multi-agent-protocol/docs-site/_sass/color_schemes/map.scss +42 -0
- package/references/multi-agent-protocol/docs-site/_sass/custom/custom.scss +34 -0
- package/references/multi-agent-protocol/docs-site/examples/full-integration.md +510 -0
- package/references/multi-agent-protocol/docs-site/examples/index.md +138 -0
- package/references/multi-agent-protocol/docs-site/examples/simple-chat.md +282 -0
- package/references/multi-agent-protocol/docs-site/examples/task-queue.md +399 -0
- package/references/multi-agent-protocol/docs-site/getting-started/index.md +98 -0
- package/references/multi-agent-protocol/docs-site/getting-started/installation.md +219 -0
- package/references/multi-agent-protocol/docs-site/getting-started/overview.md +172 -0
- package/references/multi-agent-protocol/docs-site/getting-started/quickstart.md +237 -0
- package/references/multi-agent-protocol/docs-site/index.md +136 -0
- package/references/multi-agent-protocol/docs-site/protocol/authentication.md +391 -0
- package/references/multi-agent-protocol/docs-site/protocol/connection-model.md +376 -0
- package/references/multi-agent-protocol/docs-site/protocol/design.md +284 -0
- package/references/multi-agent-protocol/docs-site/protocol/error-handling.md +312 -0
- package/references/multi-agent-protocol/docs-site/protocol/federation.md +449 -0
- package/references/multi-agent-protocol/docs-site/protocol/index.md +129 -0
- package/references/multi-agent-protocol/docs-site/protocol/permissions.md +398 -0
- package/references/multi-agent-protocol/docs-site/protocol/streaming.md +353 -0
- package/references/multi-agent-protocol/docs-site/protocol/wire-protocol.md +369 -0
- package/references/multi-agent-protocol/docs-site/sdk/api/agent.md +357 -0
- package/references/multi-agent-protocol/docs-site/sdk/api/client.md +380 -0
- package/references/multi-agent-protocol/docs-site/sdk/api/index.md +62 -0
- package/references/multi-agent-protocol/docs-site/sdk/api/server.md +453 -0
- package/references/multi-agent-protocol/docs-site/sdk/api/types.md +468 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/agent.md +375 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/authentication.md +405 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/client.md +352 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/index.md +89 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/server.md +360 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/testing.md +446 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/transports.md +363 -0
- package/references/multi-agent-protocol/docs-site/sdk/index.md +206 -0
- package/references/multi-agent-protocol/package-lock.json +3886 -0
- package/references/multi-agent-protocol/package.json +56 -0
- package/references/multi-agent-protocol/schema/meta.json +467 -0
- package/references/multi-agent-protocol/schema/schema.json +2558 -0
- package/src/agent/__tests__/agent-manager.test.ts +67 -1
- package/src/agent/agent-manager.ts +10 -4
- package/src/cli/__tests__/stable-instance-id.test.ts +57 -0
- package/src/cli/acp.ts +17 -2
- package/src/map/adapter/index.ts +3 -0
- package/src/server/combined-server.ts +10 -0
- package/src/store/event-store.ts +10 -3
- package/src/store/types/agents.ts +2 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# MAP Error Handling & Failure Modes
|
|
2
|
+
|
|
3
|
+
This spec details how MAP handles errors, failures, and recovery across single-node and federated deployments.
|
|
4
|
+
|
|
5
|
+
## Design Goals
|
|
6
|
+
|
|
7
|
+
1. **Graceful degradation** - Partial failures don't cascade to total failure
|
|
8
|
+
2. **Clear error taxonomy** - Distinct error types with actionable codes
|
|
9
|
+
3. **Recovery semantics** - Well-defined reconnection and replay behavior
|
|
10
|
+
4. **Federation resilience** - Cross-system failures handled gracefully
|
|
11
|
+
5. **Observability** - Errors are traceable and debuggable
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Error Taxonomy
|
|
16
|
+
|
|
17
|
+
### Error Categories
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
type MAPErrorCategory =
|
|
21
|
+
| "protocol" // Wire protocol violations
|
|
22
|
+
| "auth" // Authentication/authorization
|
|
23
|
+
| "routing" // Message delivery failures
|
|
24
|
+
| "agent" // Agent lifecycle errors
|
|
25
|
+
| "resource" // Resource exhaustion
|
|
26
|
+
| "federation" // Cross-system errors
|
|
27
|
+
| "internal"; // Server internal errors
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Error Structure
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
interface MAPError {
|
|
34
|
+
code: number; // Numeric code
|
|
35
|
+
category: MAPErrorCategory;
|
|
36
|
+
message: string; // Human-readable
|
|
37
|
+
|
|
38
|
+
details?: {
|
|
39
|
+
agentId?: string;
|
|
40
|
+
messageId?: string;
|
|
41
|
+
method?: string;
|
|
42
|
+
retryable?: boolean;
|
|
43
|
+
retryAfter?: number;
|
|
44
|
+
recoveryHint?: string;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
traceId?: string;
|
|
48
|
+
timestamp?: number;
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Error Codes
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
// Protocol errors (-32xxx range, JSON-RPC compatible)
|
|
56
|
+
PARSE_ERROR: -32700,
|
|
57
|
+
INVALID_REQUEST: -32600,
|
|
58
|
+
METHOD_NOT_FOUND: -32601,
|
|
59
|
+
INVALID_PARAMS: -32602,
|
|
60
|
+
INTERNAL_ERROR: -32603,
|
|
61
|
+
|
|
62
|
+
// Authentication errors (1xxx)
|
|
63
|
+
AUTH_REQUIRED: 1000,
|
|
64
|
+
AUTH_FAILED: 1001,
|
|
65
|
+
AUTH_EXPIRED: 1002,
|
|
66
|
+
PERMISSION_DENIED: 1003,
|
|
67
|
+
|
|
68
|
+
// Routing errors (2xxx)
|
|
69
|
+
AGENT_NOT_FOUND: 2000,
|
|
70
|
+
AGENT_STOPPED: 2001,
|
|
71
|
+
AGENT_BUSY: 2002,
|
|
72
|
+
DELIVERY_FAILED: 2006,
|
|
73
|
+
DELIVERY_TIMEOUT: 2007,
|
|
74
|
+
|
|
75
|
+
// Agent lifecycle errors (3xxx)
|
|
76
|
+
AGENT_EXISTS: 3000,
|
|
77
|
+
INVALID_PARENT: 3001,
|
|
78
|
+
HIERARCHY_CYCLE: 3002,
|
|
79
|
+
MAX_AGENTS_EXCEEDED: 3003,
|
|
80
|
+
|
|
81
|
+
// Resource errors (4xxx)
|
|
82
|
+
RATE_LIMITED: 4000,
|
|
83
|
+
QUOTA_EXCEEDED: 4001,
|
|
84
|
+
BUFFER_OVERFLOW: 4002,
|
|
85
|
+
|
|
86
|
+
// Federation errors (5xxx)
|
|
87
|
+
PEER_UNREACHABLE: 5000,
|
|
88
|
+
PEER_TIMEOUT: 5001,
|
|
89
|
+
PEER_REJECTED: 5002,
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Agent Failure Modes
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
1. Graceful Shutdown
|
|
98
|
+
Agent: sends shutdown intent
|
|
99
|
+
Server: drains queue, notifies parent, cleans up
|
|
100
|
+
Recovery: None needed (intentional)
|
|
101
|
+
|
|
102
|
+
2. Crash (Unexpected Termination)
|
|
103
|
+
Detection: Heartbeat timeout, process exit
|
|
104
|
+
Server: Marks stopped, notifies parent, orphan handling
|
|
105
|
+
Recovery: Restart with same ID or spawn replacement
|
|
106
|
+
|
|
107
|
+
3. Hang (Unresponsive)
|
|
108
|
+
Detection: Request timeout, no heartbeat
|
|
109
|
+
Server: Marks blocked, notifies parent
|
|
110
|
+
Recovery: Force restart or manual intervention
|
|
111
|
+
|
|
112
|
+
4. Error Loop (Repeated Failures)
|
|
113
|
+
Detection: Error rate threshold exceeded
|
|
114
|
+
Server: Circuit breaker, reduce routing
|
|
115
|
+
Recovery: Exponential backoff restart
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Orphan Handling Policy
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
interface OrphanPolicy {
|
|
122
|
+
tasks: "reassign" | "return_to_parent" | "fail" | "hold";
|
|
123
|
+
children: "cascade_stop" | "reparent" | "orphan";
|
|
124
|
+
messages: "drop" | "bounce" | "redirect";
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Connection Failures
|
|
131
|
+
|
|
132
|
+
### Reconnection Protocol
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
Client Server
|
|
136
|
+
│ │
|
|
137
|
+
│◄─────── Connection Lost ───────────────│
|
|
138
|
+
│ │
|
|
139
|
+
│ (backoff: 1s, 2s, 4s, 8s...) │
|
|
140
|
+
│ │
|
|
141
|
+
│─────── Reconnect Attempt ─────────────►│
|
|
142
|
+
│ │
|
|
143
|
+
│◄────── Connection Accept ──────────────│
|
|
144
|
+
│ │
|
|
145
|
+
│─────── map/reconnect ─────────────────►│
|
|
146
|
+
│ { lastEventId, subscriptions } │
|
|
147
|
+
│ │
|
|
148
|
+
│◄────── Reconnect Response ─────────────│
|
|
149
|
+
│ { missedEvents, newState } │
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Circuit Breakers
|
|
155
|
+
|
|
156
|
+
### Per-Agent Circuit Breaker
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
interface CircuitBreakerState {
|
|
160
|
+
agentId: string;
|
|
161
|
+
state: "closed" | "open" | "half-open";
|
|
162
|
+
|
|
163
|
+
failureThreshold: number;
|
|
164
|
+
successThreshold: number;
|
|
165
|
+
timeout: number;
|
|
166
|
+
|
|
167
|
+
failureCount: number;
|
|
168
|
+
successCount: number;
|
|
169
|
+
lastFailure: number;
|
|
170
|
+
lastStateChange: number;
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Retry Policies
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
interface RetryPolicy {
|
|
180
|
+
maxAttempts: number;
|
|
181
|
+
backoff: {
|
|
182
|
+
type: "exponential" | "linear" | "constant";
|
|
183
|
+
initial: number;
|
|
184
|
+
max: number;
|
|
185
|
+
multiplier?: number;
|
|
186
|
+
};
|
|
187
|
+
retryableErrors: number[];
|
|
188
|
+
nonRetryableErrors: number[];
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Default policy
|
|
192
|
+
const DEFAULT_RETRY: RetryPolicy = {
|
|
193
|
+
maxAttempts: 3,
|
|
194
|
+
backoff: {
|
|
195
|
+
type: "exponential",
|
|
196
|
+
initial: 1000,
|
|
197
|
+
max: 30000,
|
|
198
|
+
multiplier: 2
|
|
199
|
+
},
|
|
200
|
+
retryableErrors: [2002, 2007, 4000, 5001],
|
|
201
|
+
nonRetryableErrors: [2000, 2001, 1003]
|
|
202
|
+
};
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Error Reporting & Observability
|
|
208
|
+
|
|
209
|
+
### Distributed Tracing Integration
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
interface MAPTraceContext {
|
|
213
|
+
traceId: string;
|
|
214
|
+
spanId: string;
|
|
215
|
+
parentSpanId?: string;
|
|
216
|
+
|
|
217
|
+
// W3C Trace Context compatible
|
|
218
|
+
traceparent?: string;
|
|
219
|
+
tracestate?: string;
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Open Questions
|
|
226
|
+
|
|
227
|
+
1. **Dead letter queue**: Should undeliverable messages go to a DLQ?
|
|
228
|
+
2. **Error aggregation**: How to prevent error storms from overwhelming monitoring?
|
|
229
|
+
3. **Automatic recovery**: How much should the protocol auto-heal vs require intervention?
|
|
230
|
+
4. **Consistency model**: What consistency guarantees during partition recovery?
|
|
231
|
+
5. **Error budget**: Should there be SLO-style error budgets in the protocol?
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# MAP Connection Model & Client Patterns
|
|
2
|
+
|
|
3
|
+
This spec details how clients connect to MAP systems, the flexibility of subscription patterns, and how the protocol supports various usage modes.
|
|
4
|
+
|
|
5
|
+
## Design Principles
|
|
6
|
+
|
|
7
|
+
1. **Single protocol, multiple patterns**: Same wire protocol supports ACP-like single-agent focus through full system observation
|
|
8
|
+
2. **Subscription-driven visibility**: What you see depends on what you subscribe to
|
|
9
|
+
3. **SDK, not protocol, handles conversion**: Protocol stays simple; SDK provides utilities for common patterns
|
|
10
|
+
4. **Multi-agent system is the endpoint**: Clients connect to the system, not individual agents
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Connection Lifecycle
|
|
15
|
+
|
|
16
|
+
### Phase 1: Transport Connection
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
Client MAP System
|
|
20
|
+
│ │
|
|
21
|
+
│─────── Transport Connect ───────────────►│
|
|
22
|
+
│ (WebSocket, stdio, etc.) │
|
|
23
|
+
│ │
|
|
24
|
+
│◄────── Transport Accept ────────────────│
|
|
25
|
+
│ │
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Phase 2: MAP Handshake
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
// Client sends connect request
|
|
32
|
+
{
|
|
33
|
+
"method": "map/connect",
|
|
34
|
+
"params": {
|
|
35
|
+
"clientId": "client_001",
|
|
36
|
+
"clientInfo": {
|
|
37
|
+
"name": "my-dashboard",
|
|
38
|
+
"version": "1.0.0"
|
|
39
|
+
},
|
|
40
|
+
"protocolVersion": "2025-01-01",
|
|
41
|
+
"requestedCapabilities": {
|
|
42
|
+
"streaming": true,
|
|
43
|
+
"maxSubscriptions": 10,
|
|
44
|
+
"federation": false
|
|
45
|
+
},
|
|
46
|
+
"auth": {
|
|
47
|
+
"method": "bearer",
|
|
48
|
+
"token": "..."
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Client Types
|
|
57
|
+
|
|
58
|
+
### Operator Client
|
|
59
|
+
|
|
60
|
+
Full control over the system.
|
|
61
|
+
|
|
62
|
+
**Typical permissions:**
|
|
63
|
+
- Full visibility to all agents, scopes, events
|
|
64
|
+
- Can send messages to any agent
|
|
65
|
+
- Can register/unregister agents
|
|
66
|
+
- Can steer agents (inject context)
|
|
67
|
+
- Can create/delete scopes
|
|
68
|
+
|
|
69
|
+
### Observer Client
|
|
70
|
+
|
|
71
|
+
Read-only visibility into the system.
|
|
72
|
+
|
|
73
|
+
**Typical permissions:**
|
|
74
|
+
- Full or scoped visibility
|
|
75
|
+
- Cannot send messages
|
|
76
|
+
- Cannot modify agents or scopes
|
|
77
|
+
- Useful for dashboards, monitoring
|
|
78
|
+
|
|
79
|
+
### Agent Client
|
|
80
|
+
|
|
81
|
+
An agent connecting to participate in the system.
|
|
82
|
+
|
|
83
|
+
**Typical permissions:**
|
|
84
|
+
- Visibility scoped to hierarchy/relationships
|
|
85
|
+
- Can send messages to permitted agents
|
|
86
|
+
- Receives messages addressed to itself
|
|
87
|
+
- Cannot see full system structure (unless permitted)
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Subscription Patterns
|
|
92
|
+
|
|
93
|
+
### Pattern 1: Single-Agent Focus (ACP-like)
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
await map.subscribe({
|
|
97
|
+
filter: { agents: ["agent_001"] },
|
|
98
|
+
streams: ["messages", "state"]
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Pattern 2: Multi-Agent Dashboard
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
await map.subscribe({
|
|
106
|
+
filter: { agents: ["worker_001", "worker_002", "coordinator"] },
|
|
107
|
+
streams: ["messages", "state"]
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Pattern 3: Role-Based Observation
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
await map.subscribe({
|
|
115
|
+
filter: { roles: ["worker"] },
|
|
116
|
+
streams: ["messages", "state"]
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Pattern 4: Full System Observation
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
await map.subscribe({
|
|
124
|
+
filter: {}, // Empty filter = no filtering
|
|
125
|
+
streams: ["messages", "state", "structure"]
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Pattern 5: Multiple Subscriptions
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
// Subscription 1: High-priority messages only
|
|
133
|
+
const urgentSub = await map.subscribe({
|
|
134
|
+
filter: { messagePriorities: ["urgent", "high"] },
|
|
135
|
+
streams: ["messages"]
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Subscription 2: All state changes
|
|
139
|
+
const stateSub = await map.subscribe({
|
|
140
|
+
filter: {},
|
|
141
|
+
streams: ["state"]
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## SDK Utilities
|
|
148
|
+
|
|
149
|
+
### ACP Session Adapter
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
// Create ACP-compatible session from MAP connection
|
|
153
|
+
const session = mapSdk.createACPSession(connection, "agent_001");
|
|
154
|
+
|
|
155
|
+
// Now use ACP-like API
|
|
156
|
+
await session.prompt("Hello, world");
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Stream Aggregator
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
// Combine multiple subscriptions into one stream
|
|
163
|
+
const aggregated = mapSdk.aggregateStreams([sub1, sub2, sub3]);
|
|
164
|
+
|
|
165
|
+
for await (const event of aggregated) {
|
|
166
|
+
console.log(event.subscriptionId, event.event);
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Agent Proxy
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
// Create a proxy object for an agent
|
|
174
|
+
const agent = mapSdk.createAgentProxy(connection, "agent_001");
|
|
175
|
+
|
|
176
|
+
// Direct method calls become messages
|
|
177
|
+
await agent.send({ type: "task", data: "..." });
|
|
178
|
+
|
|
179
|
+
// State is automatically updated
|
|
180
|
+
console.log(agent.state); // "busy"
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Connection State Management
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
┌──────────┐ connect ┌────────────┐ ready ┌─────────┐
|
|
189
|
+
│ INITIAL │ ─────────► │ CONNECTING │ ────────► │ ACTIVE │
|
|
190
|
+
└──────────┘ └────────────┘ └────┬────┘
|
|
191
|
+
│
|
|
192
|
+
┌────────────────────────────────────────────────┤
|
|
193
|
+
│ │
|
|
194
|
+
│ disconnect error │
|
|
195
|
+
▼ ▼
|
|
196
|
+
┌──────────┐ ┌────────────┐
|
|
197
|
+
│ CLOSED │ ◄───────────────────────────── │ RECONNECT │
|
|
198
|
+
└──────────┘ max retries └────────────┘
|
|
199
|
+
exceeded
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Capability Negotiation
|
|
205
|
+
|
|
206
|
+
### Client Capabilities
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
interface MAPClientCapabilities {
|
|
210
|
+
streaming: boolean;
|
|
211
|
+
maxConcurrentStreams?: number;
|
|
212
|
+
maxSubscriptions?: number;
|
|
213
|
+
maxMessageSize?: number;
|
|
214
|
+
supportedEncodings?: string[];
|
|
215
|
+
federation?: boolean;
|
|
216
|
+
replay?: boolean;
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### System Capabilities
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
interface MAPSystemCapabilities {
|
|
224
|
+
protocolVersions: string[];
|
|
225
|
+
streaming: boolean;
|
|
226
|
+
federation: boolean;
|
|
227
|
+
replay: boolean;
|
|
228
|
+
replayWindow?: number;
|
|
229
|
+
maxSubscriptions: number;
|
|
230
|
+
maxMessageSize: number;
|
|
231
|
+
maxConcurrentConnections: number;
|
|
232
|
+
extensions?: string[];
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Open Questions
|
|
239
|
+
|
|
240
|
+
1. **Session affinity**: Should subscriptions be tied to connection or transferable?
|
|
241
|
+
2. **Subscription limits**: Per-connection or per-client (across reconnects)?
|
|
242
|
+
3. **Capability versioning**: How to handle capability changes across protocol versions?
|
|
243
|
+
4. **Auth refresh**: How to handle token expiration during long-lived connections?
|
|
244
|
+
5. **Partial visibility**: Can a client request "all agents I can see" without knowing IDs upfront?
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# MAP Visibility & Permission Model
|
|
2
|
+
|
|
3
|
+
This spec details how MAP controls visibility and permissions at multiple levels: system, client, scope, and agent.
|
|
4
|
+
|
|
5
|
+
## Design Principles
|
|
6
|
+
|
|
7
|
+
1. **Layered control**: Permissions are checked at multiple levels, most restrictive wins
|
|
8
|
+
2. **Explicit over implicit**: Default to restricted, explicitly grant access
|
|
9
|
+
3. **Separation of concerns**: Client permissions vs agent permissions are distinct
|
|
10
|
+
4. **Flexibility**: System implementations can choose how strict to be
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Visibility Layers
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
18
|
+
│ Visibility Stack │
|
|
19
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
20
|
+
│ │
|
|
21
|
+
│ ┌─────────────────────────────────────────────────────────┐ │
|
|
22
|
+
│ │ LAYER 4: Agent Permissions │ │
|
|
23
|
+
│ │ What can this agent see/do within its allowed scope? │ │
|
|
24
|
+
│ └────────────────────────────┬────────────────────────────┘ │
|
|
25
|
+
│ │ │
|
|
26
|
+
│ ┌────────────────────────────▼────────────────────────────┐ │
|
|
27
|
+
│ │ LAYER 3: Scope Permissions │ │
|
|
28
|
+
│ │ What's visible within this scope? Who can see it? │ │
|
|
29
|
+
│ └────────────────────────────┬────────────────────────────┘ │
|
|
30
|
+
│ │ │
|
|
31
|
+
│ ┌────────────────────────────▼────────────────────────────┐ │
|
|
32
|
+
│ │ LAYER 2: Client Permissions │ │
|
|
33
|
+
│ │ What can this client see/do in the system? │ │
|
|
34
|
+
│ └────────────────────────────┬────────────────────────────┘ │
|
|
35
|
+
│ │ │
|
|
36
|
+
│ ┌────────────────────────────▼────────────────────────────┐ │
|
|
37
|
+
│ │ LAYER 1: System Configuration │ │
|
|
38
|
+
│ │ What does the system expose at all? │ │
|
|
39
|
+
│ └─────────────────────────────────────────────────────────┘ │
|
|
40
|
+
│ │
|
|
41
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
42
|
+
|
|
43
|
+
Evaluation: Check Layer 1 → Layer 2 → Layer 3 → Layer 4
|
|
44
|
+
Result: Most restrictive wins (all layers must allow)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Layer 1: System Configuration
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
interface MAPSystemConfig {
|
|
53
|
+
exposure: {
|
|
54
|
+
agents: {
|
|
55
|
+
publicByDefault: boolean;
|
|
56
|
+
publicAgents: string[];
|
|
57
|
+
hiddenAgents: string[];
|
|
58
|
+
};
|
|
59
|
+
events: {
|
|
60
|
+
exposedTypes: string[];
|
|
61
|
+
hiddenTypes: string[];
|
|
62
|
+
};
|
|
63
|
+
scopes: {
|
|
64
|
+
publicByDefault: boolean;
|
|
65
|
+
publicScopes: string[];
|
|
66
|
+
hiddenScopes: string[];
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
limits: {
|
|
70
|
+
maxConnections: number;
|
|
71
|
+
maxConnectionsPerClient: number;
|
|
72
|
+
maxSubscriptionsPerConnection: number;
|
|
73
|
+
};
|
|
74
|
+
anonymousPermissions: MAPClientPermissions;
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Layer 2: Client Permissions
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
interface MAPClientPermissions {
|
|
84
|
+
visibility: {
|
|
85
|
+
agents: "all" | "none" | { include: string[] } | { roles: string[] };
|
|
86
|
+
scopes: "all" | "none" | { include: string[] };
|
|
87
|
+
events: "all" | "none" | { include: string[] };
|
|
88
|
+
structure: boolean;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
actions: {
|
|
92
|
+
sendMessages: boolean | { to: MAPAddress[]; priorities: string[] };
|
|
93
|
+
registerAgents: boolean | { roles: string[]; maxAgents: number };
|
|
94
|
+
unregisterAgents: boolean | { own: boolean; any: boolean };
|
|
95
|
+
createScopes: boolean;
|
|
96
|
+
deleteScopes: boolean | { own: boolean };
|
|
97
|
+
modifyScopes: boolean | { own: boolean; member: boolean };
|
|
98
|
+
steerAgents: boolean | { agents: string[]; methods: string[] };
|
|
99
|
+
federationConnect: boolean;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
limits: {
|
|
103
|
+
subscriptions: number;
|
|
104
|
+
messagesPerMinute: number;
|
|
105
|
+
agentsRegistered: number;
|
|
106
|
+
scopesCreated: number;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Layer 3: Scope Permissions
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
interface MAPScopePermissions {
|
|
117
|
+
discoverability: "public" | "members" | "owners";
|
|
118
|
+
messageVisibility: "public" | "members" | "participants";
|
|
119
|
+
joinPolicy: "open" | "invite" | "owner-invite" | "closed";
|
|
120
|
+
sendPolicy: "anyone" | "members" | "owners";
|
|
121
|
+
inheritFrom?: string;
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Layer 4: Agent Permissions
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
interface MAPAgentPermissions {
|
|
131
|
+
canSee: {
|
|
132
|
+
agents: "all" | "hierarchy" | "scoped" | "direct" | { include: string[] };
|
|
133
|
+
scopes: "all" | "member" | { include: string[] };
|
|
134
|
+
structure: "full" | "local" | "none";
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
canMessage: {
|
|
138
|
+
agents: "all" | "hierarchy" | "scoped" | { include: string[] };
|
|
139
|
+
scopes: "all" | "member" | { include: string[] };
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
acceptsFrom: {
|
|
143
|
+
agents: "all" | "hierarchy" | "scoped" | { include: string[] };
|
|
144
|
+
clients: "all" | "none" | { include: string[] };
|
|
145
|
+
systems: "all" | "none" | { include: string[] };
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
capabilities: {
|
|
149
|
+
registerAgents: boolean;
|
|
150
|
+
createScopes: boolean;
|
|
151
|
+
steerAgents: boolean;
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Permission Resolution
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
function canPerformAction(
|
|
162
|
+
client: MAPClient,
|
|
163
|
+
agent: MAPAgent | null,
|
|
164
|
+
action: MAPAction
|
|
165
|
+
): boolean {
|
|
166
|
+
// Layer 1: System allows?
|
|
167
|
+
if (!systemAllows(action)) return false;
|
|
168
|
+
|
|
169
|
+
// Layer 2: Client permissions allow?
|
|
170
|
+
if (!clientAllows(client, action)) return false;
|
|
171
|
+
|
|
172
|
+
// Layer 3: Scope permissions allow?
|
|
173
|
+
if (action.scope && !scopeAllows(action.scope, client, agent, action)) {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Layer 4: Agent permissions allow?
|
|
178
|
+
if (agent && !agentAllows(agent, action)) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Dynamic Permissions
|
|
189
|
+
|
|
190
|
+
Permissions can change during runtime:
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
// System can update client permissions
|
|
194
|
+
{
|
|
195
|
+
"method": "map/permissions/update",
|
|
196
|
+
"params": {
|
|
197
|
+
"clientId": "client_001",
|
|
198
|
+
"permissions": {
|
|
199
|
+
"actions": {
|
|
200
|
+
"steerAgents": true
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Permission Events
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
type MAPPermissionEvent =
|
|
213
|
+
| { type: "permissions.client.updated"; clientId: string; changes: ... }
|
|
214
|
+
| { type: "permissions.agent.updated"; agentId: string; changes: ... }
|
|
215
|
+
| { type: "permissions.scope.updated"; scopeId: string; changes: ... }
|
|
216
|
+
| { type: "permissions.denied"; action: string; reason: string };
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Security Considerations
|
|
222
|
+
|
|
223
|
+
### Principle of Least Privilege
|
|
224
|
+
|
|
225
|
+
- Default to restricted permissions
|
|
226
|
+
- Grant only what's needed
|
|
227
|
+
- Regularly audit permission grants
|
|
228
|
+
|
|
229
|
+
### Permission Escalation Prevention
|
|
230
|
+
|
|
231
|
+
- Agents cannot grant permissions they don't have
|
|
232
|
+
- Clients cannot modify their own permissions
|
|
233
|
+
- System enforces capability ceilings
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Open Questions
|
|
238
|
+
|
|
239
|
+
1. **Inheritance**: Should agent permissions inherit from parent by default?
|
|
240
|
+
2. **Temporary grants**: Time-limited permission grants?
|
|
241
|
+
3. **Delegation**: Can agents delegate their permissions to others?
|
|
242
|
+
4. **Groups**: Should there be permission groups/roles for clients?
|
|
243
|
+
5. **Revocation**: Immediate revocation or graceful wind-down?
|