network-ai 4.0.17 → 4.1.0
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 +110 -30
- package/dist/adapters/a2a-adapter.d.ts +152 -0
- package/dist/adapters/a2a-adapter.d.ts.map +1 -0
- package/dist/adapters/a2a-adapter.js +235 -0
- package/dist/adapters/a2a-adapter.js.map +1 -0
- package/dist/adapters/custom-streaming-adapter.d.ts +68 -0
- package/dist/adapters/custom-streaming-adapter.d.ts.map +1 -0
- package/dist/adapters/custom-streaming-adapter.js +181 -0
- package/dist/adapters/custom-streaming-adapter.js.map +1 -0
- package/dist/adapters/index.d.ts +7 -0
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +12 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/langchain-streaming-adapter.d.ts +48 -0
- package/dist/adapters/langchain-streaming-adapter.d.ts.map +1 -0
- package/dist/adapters/langchain-streaming-adapter.js +161 -0
- package/dist/adapters/langchain-streaming-adapter.js.map +1 -0
- package/dist/adapters/streaming-base-adapter.d.ts +42 -0
- package/dist/adapters/streaming-base-adapter.d.ts.map +1 -0
- package/dist/adapters/streaming-base-adapter.js +68 -0
- package/dist/adapters/streaming-base-adapter.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/run.js +1 -0
- package/dist/run.js.map +1 -1
- package/package.json +6 -4
- package/types/streaming-adapter.d.ts +63 -0
package/README.md
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
[](https://github.com/jovanSAPFIONEER/Network-AI/actions/workflows/ci.yml)
|
|
6
6
|
[](https://github.com/jovanSAPFIONEER/Network-AI/actions/workflows/codeql.yml)
|
|
7
|
-
[](https://github.com/jovanSAPFIONEER/Network-AI/releases)
|
|
8
8
|
[](https://www.npmjs.com/package/network-ai)
|
|
9
|
-
[](#testing)
|
|
10
|
+
[](#adapter-system)
|
|
11
11
|
[](LICENSE)
|
|
12
12
|
[](https://socket.dev/npm/package/network-ai/overview)
|
|
13
13
|
[](https://nodejs.org)
|
|
@@ -19,7 +19,13 @@ Network-AI is a TypeScript/Node.js multi-agent orchestrator that adds coordinati
|
|
|
19
19
|
|
|
20
20
|
- **Shared blackboard with locking** — atomic `propose → validate → commit` prevents race conditions and split-brain failures across parallel agents
|
|
21
21
|
- **Guardrails and budgets** — FSM governance, per-agent token ceilings, HMAC audit trails, and permission gating
|
|
22
|
-
- **
|
|
22
|
+
- **13 adapters** — LangChain (+ streaming), AutoGen, CrewAI, OpenAI Assistants, LlamaIndex, Semantic Kernel, Haystack, DSPy, Agno, MCP, Custom (+ streaming), OpenClaw, and A2A — no glue code, no lock-in
|
|
23
|
+
|
|
24
|
+
> **The silent failure mode in multi-agent systems:** parallel agents writing to the same key
|
|
25
|
+
> use last-write-wins by default — one agent's result silently overwrites another's mid-flight.
|
|
26
|
+
> The outcome is split-brain state: double-spends, contradictory decisions, corrupted context,
|
|
27
|
+
> no error thrown. Network-AI's `propose → validate → commit` mutex prevents this at the
|
|
28
|
+
> coordination layer, before any write reaches shared state.
|
|
23
29
|
|
|
24
30
|
**Use Network-AI as:**
|
|
25
31
|
- A **TypeScript/Node.js library** — `import { createSwarmOrchestrator } from 'network-ai'`
|
|
@@ -28,6 +34,15 @@ Network-AI is a TypeScript/Node.js multi-agent orchestrator that adds coordinati
|
|
|
28
34
|
|
|
29
35
|
[**5-minute quickstart →**](QUICKSTART.md) | [**Architecture →**](ARCHITECTURE.md) | [**All adapters →**](#adapter-system) | [**Benchmarks →**](BENCHMARKS.md)
|
|
30
36
|
|
|
37
|
+
> **Try the control-plane stress test — no API key, ~3 seconds:**
|
|
38
|
+
> ```bash
|
|
39
|
+
> npx ts-node examples/08-control-plane-stress-demo.ts
|
|
40
|
+
> ```
|
|
41
|
+
> Runs priority preemption, AuthGuardian permission gating, FSM governance, and compliance
|
|
42
|
+
> monitoring against a live swarm. No external services required.
|
|
43
|
+
>
|
|
44
|
+
> If it saves you from a race condition, a ⭐ helps others find it.
|
|
45
|
+
|
|
31
46
|
---
|
|
32
47
|
|
|
33
48
|
## Why teams use Network-AI
|
|
@@ -37,7 +52,7 @@ Network-AI is a TypeScript/Node.js multi-agent orchestrator that adds coordinati
|
|
|
37
52
|
| Race conditions in parallel agents | Atomic blackboard: `propose → validate → commit` with file-system mutex |
|
|
38
53
|
| Agent overspend / runaway costs | `FederatedBudget` — hard per-agent token ceilings with live spend tracking |
|
|
39
54
|
| No visibility into what agents did | HMAC-signed audit log on every write, permission grant, and FSM transition |
|
|
40
|
-
| Locked into one AI framework |
|
|
55
|
+
| Locked into one AI framework | 13 adapters — mix LangChain + AutoGen + CrewAI + A2A + custom in one swarm |
|
|
41
56
|
| Agents escalating beyond their scope | `AuthGuardian` — scoped permission tokens required before sensitive operations |
|
|
42
57
|
|
|
43
58
|
---
|
|
@@ -90,6 +105,64 @@ No native dependencies, no build step. Adapters are dependency-free (BYOC — br
|
|
|
90
105
|
|
|
91
106
|
---
|
|
92
107
|
|
|
108
|
+
## Use as MCP Server
|
|
109
|
+
|
|
110
|
+
Start the server (no config required, zero dependencies):
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npx network-ai-server --port 3001
|
|
114
|
+
# or from source:
|
|
115
|
+
npx ts-node bin/mcp-server.ts --port 3001
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Then wire any MCP-compatible client to it.
|
|
119
|
+
|
|
120
|
+
**Claude Desktop** — add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"mcpServers": {
|
|
125
|
+
"network-ai": {
|
|
126
|
+
"url": "http://localhost:3001/sse"
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Cursor / Cline / any SSE-based MCP client** — point to the same URL:
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{
|
|
136
|
+
"mcpServers": {
|
|
137
|
+
"network-ai": {
|
|
138
|
+
"url": "http://localhost:3001/sse"
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Verify it's running:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
curl http://localhost:3001/health # { "status": "ok", "tools": <n>, "uptime": <ms> }
|
|
148
|
+
curl http://localhost:3001/tools # full tool list
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Tools exposed over MCP:**
|
|
152
|
+
- `blackboard_read` / `blackboard_write` / `blackboard_list` / `blackboard_delete` / `blackboard_exists`
|
|
153
|
+
- `budget_status` / `budget_spend` / `budget_reset` — federated token tracking
|
|
154
|
+
- `token_create` / `token_validate` / `token_revoke` — HMAC-signed permission tokens
|
|
155
|
+
- `audit_query` — query the append-only audit log
|
|
156
|
+
- `config_get` / `config_set` — live orchestrator configuration
|
|
157
|
+
- `agent_list` / `agent_spawn` / `agent_stop` — agent lifecycle
|
|
158
|
+
- `fsm_transition` — write FSM state transitions to the blackboard
|
|
159
|
+
|
|
160
|
+
Each tool takes an `agent_id` parameter — all writes are identity-verified and namespace-scoped, exactly as they are in the TypeScript API.
|
|
161
|
+
|
|
162
|
+
Options: `--no-budget`, `--no-token`, `--no-control`, `--ceiling <n>`, `--board <name>`, `--audit-log <path>`.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
93
166
|
## Two agents, one shared state — without race conditions
|
|
94
167
|
|
|
95
168
|
The real differentiator is coordination. Here is what no single-framework solution handles: two agents writing to the same resource concurrently, atomically, without corrupting each other.
|
|
@@ -157,12 +230,12 @@ npm run demo -- --07
|
|
|
157
230
|
|
|
158
231
|
## Adapter System
|
|
159
232
|
|
|
160
|
-
|
|
233
|
+
13 adapters, zero adapter dependencies. You bring your own SDK objects.
|
|
161
234
|
|
|
162
|
-
| Adapter | Framework | Register method |
|
|
235
|
+
| Adapter | Framework / Protocol | Register method |
|
|
163
236
|
|---|---|---|
|
|
164
237
|
| `CustomAdapter` | Any function or HTTP endpoint | `registerHandler(name, fn)` |
|
|
165
|
-
| `LangChainAdapter` | LangChain | `
|
|
238
|
+
| `LangChainAdapter` | LangChain | `registerAgent(name, runnable)` |
|
|
166
239
|
| `AutoGenAdapter` | AutoGen / AG2 | `registerAgent(name, agent)` |
|
|
167
240
|
| `CrewAIAdapter` | CrewAI | `registerAgent` or `registerCrew` |
|
|
168
241
|
| `MCPAdapter` | Model Context Protocol | `registerTool(name, handler)` |
|
|
@@ -173,8 +246,16 @@ npm run demo -- --07
|
|
|
173
246
|
| `DSPyAdapter` | Stanford DSPy | `registerModule()`, `registerProgram()` |
|
|
174
247
|
| `AgnoAdapter` | Agno (formerly Phidata) | `registerAgent()`, `registerTeam()` |
|
|
175
248
|
| `OpenClawAdapter` | OpenClaw | `registerSkill(name, skillRef)` |
|
|
249
|
+
| `A2AAdapter` | Google A2A Protocol | `registerRemoteAgent(name, url)` |
|
|
250
|
+
|
|
251
|
+
**Streaming variants** (drop-in replacements with `.stream()` support):
|
|
176
252
|
|
|
177
|
-
|
|
253
|
+
| Adapter | Extends | Streaming source |
|
|
254
|
+
|---|---|---|
|
|
255
|
+
| `LangChainStreamingAdapter` | `LangChainAdapter` | Calls `.stream()` on the Runnable if available; falls back to `.invoke()` |
|
|
256
|
+
| `CustomStreamingAdapter` | `CustomAdapter` | Pipes `AsyncIterable<string>` handlers; falls back to single-chunk for plain Promises |
|
|
257
|
+
|
|
258
|
+
Extend `BaseAdapter` (or `StreamingBaseAdapter` for streaming) to add your own in minutes. See [references/adapter-system.md](references/adapter-system.md).
|
|
178
259
|
|
|
179
260
|
---
|
|
180
261
|
|
|
@@ -184,7 +265,7 @@ Extend `BaseAdapter` to add your own in minutes. See [references/adapter-system.
|
|
|
184
265
|
|
|
185
266
|
| Capability | Network-AI | LangGraph | CrewAI | AutoGen |
|
|
186
267
|
|---|---|---|---|---|
|
|
187
|
-
| Cross-framework agents in one swarm | ✅
|
|
268
|
+
| Cross-framework agents in one swarm | ✅ 13 built-in adapters | ⚠️ Nodes can call any code; no adapter abstraction | ⚠️ Extensible via tools; CrewAI-native agents only | ⚠️ Extensible via plugins; AutoGen-native agents only |
|
|
188
269
|
| Atomic shared state (conflict-safe) | ✅ `propose → validate → commit` mutex | ⚠️ State passed between nodes; last-write-wins | ⚠️ Shared memory available; no conflict resolution | ⚠️ Shared context available; no conflict resolution |
|
|
189
270
|
| Hard token ceiling per agent | ✅ `FederatedBudget` (first-class API) | ⚠️ Via callbacks / custom middleware | ⚠️ Via callbacks / custom middleware | ⚠️ Built-in token tracking in v0.4+; no swarm-level ceiling |
|
|
190
271
|
| Permission gating before sensitive ops | ✅ `AuthGuardian` (built-in) | ⚠️ Possible via custom node logic | ⚠️ Possible via custom tools | ⚠️ Possible via custom middleware |
|
|
@@ -200,29 +281,31 @@ Extend `BaseAdapter` to add your own in minutes. See [references/adapter-system.
|
|
|
200
281
|
npm run test:all # All suites in sequence
|
|
201
282
|
npm test # Core orchestrator
|
|
202
283
|
npm run test:security # Security module
|
|
203
|
-
npm run test:adapters # All
|
|
284
|
+
npm run test:adapters # All 13 adapters
|
|
285
|
+
npm run test:streaming # Streaming adapters
|
|
286
|
+
npm run test:a2a # A2A protocol adapter
|
|
204
287
|
npm run test:priority # Priority & preemption
|
|
205
288
|
```
|
|
206
289
|
|
|
207
|
-
**1,
|
|
290
|
+
**1,283 passing assertions across 15 test suites** (`npm run test:all`):
|
|
208
291
|
|
|
209
292
|
| Suite | Assertions | Covers |
|
|
210
293
|
|---|---|---|
|
|
211
|
-
| `test-
|
|
212
|
-
| `test-
|
|
213
|
-
| `test-
|
|
214
|
-
| `test-
|
|
215
|
-
| `test-
|
|
216
|
-
| `test-
|
|
217
|
-
| `test-
|
|
218
|
-
| `test-
|
|
219
|
-
| `test-
|
|
220
|
-
| `test-
|
|
221
|
-
| `test-
|
|
222
|
-
| `test-
|
|
223
|
-
| `test-
|
|
224
|
-
| `test.ts` |
|
|
225
|
-
| `test-
|
|
294
|
+
| `test-phase4.ts` | 147 | FSM governance, compliance monitor, adapter integration |
|
|
295
|
+
| `test-phase5f.ts` | 127 | SSE transport, `McpCombinedBridge`, extended MCP tools |
|
|
296
|
+
| `test-phase5g.ts` | 121 | CRDT backend, vector clocks, bidirectional sync |
|
|
297
|
+
| `test-phase6.ts` | 121 | MCP server, control-plane tools, audit tools |
|
|
298
|
+
| `test-phase5d.ts` | 117 | Pluggable backend (Redis, CRDT, Memory) |
|
|
299
|
+
| `test-adapters.ts` | 139 | All 13 adapters, registry routing, integration, edge cases |
|
|
300
|
+
| `test-standalone.ts` | 88 | Blackboard, auth, integration, persistence, parallelisation, quality gate |
|
|
301
|
+
| `test-phase5e.ts` | 87 | Federated budget tracking |
|
|
302
|
+
| `test-phase5c.ts` | 73 | Named multi-blackboard, isolation, backend options |
|
|
303
|
+
| `test-priority.ts` | 64 | Priority preemption, conflict resolution, backward compat |
|
|
304
|
+
| `test-a2a.ts` | 34 | A2A protocol: register, execute, mock fetch, error paths |
|
|
305
|
+
| `test-streaming.ts` | 31 | Streaming adapters, chunk shapes, fallback, collectStream |
|
|
306
|
+
| `test-phase5b.ts` | 55 | Pluggable backend part 2, consistency levels |
|
|
307
|
+
| `test-phase5.ts` | 42 | Named multi-blackboard base |
|
|
308
|
+
| `test-security.ts` | 34 | Tokens, sanitization, rate limiting, encryption, audit |
|
|
226
309
|
|
|
227
310
|
---
|
|
228
311
|
|
|
@@ -248,9 +331,6 @@ npm run test:priority # Priority & preemption
|
|
|
248
331
|
|
|
249
332
|
1. Fork → feature branch → `npm run test:all` → pull request
|
|
250
333
|
2. Bugs and feature requests via [Issues](https://github.com/jovanSAPFIONEER/Network-AI/issues)
|
|
251
|
-
3. If Network-AI saves you time, a ⭐ helps others find it
|
|
252
|
-
|
|
253
|
-
[](https://github.com/jovanSAPFIONEER/Network-AI)
|
|
254
334
|
|
|
255
335
|
---
|
|
256
336
|
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A2AAdapter — Agent-to-Agent (A2A) protocol adapter.
|
|
3
|
+
*
|
|
4
|
+
* Implements the Google A2A (Agent-to-Agent) open protocol that lets
|
|
5
|
+
* independently hosted agents discover each other through a standard
|
|
6
|
+
* Agent Card (/.well-known/agent.json) and exchange tasks via a
|
|
7
|
+
* JSON-RPC envelope posted to the agent's task endpoint.
|
|
8
|
+
*
|
|
9
|
+
* References:
|
|
10
|
+
* https://google.github.io/A2A/
|
|
11
|
+
* https://github.com/google/A2A
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
*
|
|
15
|
+
* const adapter = new A2AAdapter();
|
|
16
|
+
* await adapter.initialize({});
|
|
17
|
+
*
|
|
18
|
+
* // Register a remote agent by its Agent Card URL
|
|
19
|
+
* await adapter.registerRemoteAgent('remote-analyst', 'https://agent.example.com');
|
|
20
|
+
*
|
|
21
|
+
* // Or register a local agent that serves an A2A-compliant card
|
|
22
|
+
* adapter.registerLocalA2AAgent('local-writer', {
|
|
23
|
+
* name: 'Writing Agent',
|
|
24
|
+
* description: 'Draft documents given a topic',
|
|
25
|
+
* version: '1.0',
|
|
26
|
+
* capabilities: { streaming: false },
|
|
27
|
+
* taskEndpoint: 'https://writer.internal/tasks',
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* await registry.addAdapter(adapter);
|
|
31
|
+
*
|
|
32
|
+
* // In the orchestrator:
|
|
33
|
+
* delegateTask({ targetAgent: 'a2a:remote-analyst', ... })
|
|
34
|
+
*
|
|
35
|
+
* @module A2AAdapter
|
|
36
|
+
* @version 1.0.0
|
|
37
|
+
*/
|
|
38
|
+
import { BaseAdapter } from './base-adapter';
|
|
39
|
+
import type { AdapterConfig, AdapterCapabilities, AgentPayload, AgentContext, AgentResult } from '../types/agent-adapter';
|
|
40
|
+
/** Agent Card served at /.well-known/agent.json (A2A spec §3.1) */
|
|
41
|
+
export interface A2AAgentCard {
|
|
42
|
+
/** Human-readable agent name */
|
|
43
|
+
name: string;
|
|
44
|
+
/** Purpose / capabilities in plain English */
|
|
45
|
+
description?: string;
|
|
46
|
+
/** SemVer */
|
|
47
|
+
version?: string;
|
|
48
|
+
/** Protocol capabilities declared by the agent */
|
|
49
|
+
capabilities?: {
|
|
50
|
+
streaming?: boolean;
|
|
51
|
+
pushNotifications?: boolean;
|
|
52
|
+
stateTransitionHistory?: boolean;
|
|
53
|
+
};
|
|
54
|
+
/** URL that accepts A2A task envelopes (defaults to <baseUrl>/tasks) */
|
|
55
|
+
taskEndpoint?: string;
|
|
56
|
+
/** Agent homepage or further docs */
|
|
57
|
+
url?: string;
|
|
58
|
+
}
|
|
59
|
+
/** JSON-RPC 2.0 task request envelope sent to the task endpoint (A2A spec §4) */
|
|
60
|
+
export interface A2ATask {
|
|
61
|
+
jsonrpc: '2.0';
|
|
62
|
+
id: string;
|
|
63
|
+
method: 'tasks/send';
|
|
64
|
+
params: {
|
|
65
|
+
id: string;
|
|
66
|
+
message: {
|
|
67
|
+
role: 'user';
|
|
68
|
+
parts: Array<{
|
|
69
|
+
type: 'text';
|
|
70
|
+
text: string;
|
|
71
|
+
}>;
|
|
72
|
+
};
|
|
73
|
+
metadata?: Record<string, unknown>;
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/** State of a running A2A task */
|
|
77
|
+
export type A2ATaskState = 'submitted' | 'working' | 'input-required' | 'completed' | 'canceled' | 'failed' | 'unknown';
|
|
78
|
+
/** Artifact produced by the agent (A2A spec §4.3) */
|
|
79
|
+
export interface A2AArtifact {
|
|
80
|
+
name?: string;
|
|
81
|
+
description?: string;
|
|
82
|
+
parts: Array<{
|
|
83
|
+
type: string;
|
|
84
|
+
text?: string;
|
|
85
|
+
data?: unknown;
|
|
86
|
+
}>;
|
|
87
|
+
}
|
|
88
|
+
/** JSON-RPC 2.0 task response (A2A spec §4) */
|
|
89
|
+
export interface A2ATaskResponse {
|
|
90
|
+
jsonrpc: '2.0';
|
|
91
|
+
id: string;
|
|
92
|
+
result?: {
|
|
93
|
+
id: string;
|
|
94
|
+
status: {
|
|
95
|
+
state: A2ATaskState;
|
|
96
|
+
message?: string;
|
|
97
|
+
};
|
|
98
|
+
artifacts?: A2AArtifact[];
|
|
99
|
+
metadata?: Record<string, unknown>;
|
|
100
|
+
};
|
|
101
|
+
error?: {
|
|
102
|
+
code: number;
|
|
103
|
+
message: string;
|
|
104
|
+
data?: unknown;
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/** Adapter configuration specific to A2A */
|
|
108
|
+
export interface A2AAdapterConfig extends AdapterConfig {
|
|
109
|
+
/** Default bearer token applied to all agents unless overridden at agent level */
|
|
110
|
+
defaultBearerToken?: string;
|
|
111
|
+
/** Default timeout for all agents in ms (default: 30 000) */
|
|
112
|
+
defaultTimeoutMs?: number;
|
|
113
|
+
/** Custom fetch implementation (for testing / node compat) */
|
|
114
|
+
fetchImpl?: typeof fetch;
|
|
115
|
+
}
|
|
116
|
+
export declare class A2AAdapter extends BaseAdapter {
|
|
117
|
+
readonly name = "a2a";
|
|
118
|
+
readonly version = "1.0.0";
|
|
119
|
+
private a2aAgents;
|
|
120
|
+
private defaultBearerToken?;
|
|
121
|
+
private defaultTimeoutMs;
|
|
122
|
+
private fetchImpl;
|
|
123
|
+
get capabilities(): AdapterCapabilities;
|
|
124
|
+
initialize(config: A2AAdapterConfig): Promise<void>;
|
|
125
|
+
/**
|
|
126
|
+
* Fetch the Agent Card from `<baseUrl>/.well-known/agent.json` and register
|
|
127
|
+
* the remote agent for use in the orchestrator.
|
|
128
|
+
*
|
|
129
|
+
* @param agentId - Local identifier (used in `delegate_task` calls)
|
|
130
|
+
* @param baseUrl - Root URL of the remote A2A-compliant agent server
|
|
131
|
+
* @param options - Optional bearer token / timeout override
|
|
132
|
+
*/
|
|
133
|
+
registerRemoteAgent(agentId: string, baseUrl: string, options?: {
|
|
134
|
+
bearerToken?: string;
|
|
135
|
+
timeoutMs?: number;
|
|
136
|
+
}): Promise<void>;
|
|
137
|
+
/**
|
|
138
|
+
* Register a local A2A agent whose card you already have (no network fetch).
|
|
139
|
+
* Useful when the card is embedded in config or returned from another service.
|
|
140
|
+
*/
|
|
141
|
+
registerLocalA2AAgent(agentId: string, card: A2AAgentCard & {
|
|
142
|
+
taskEndpoint: string;
|
|
143
|
+
}, options?: {
|
|
144
|
+
bearerToken?: string;
|
|
145
|
+
timeoutMs?: number;
|
|
146
|
+
}): void;
|
|
147
|
+
executeAgent(agentId: string, payload: AgentPayload, context: AgentContext): Promise<AgentResult>;
|
|
148
|
+
private fetchAgentCard;
|
|
149
|
+
private sendTask;
|
|
150
|
+
private extractOutput;
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=a2a-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"a2a-adapter.d.ts","sourceRoot":"","sources":["../../adapters/a2a-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* A2AAdapter — Agent-to-Agent (A2A) protocol adapter.
|
|
4
|
+
*
|
|
5
|
+
* Implements the Google A2A (Agent-to-Agent) open protocol that lets
|
|
6
|
+
* independently hosted agents discover each other through a standard
|
|
7
|
+
* Agent Card (/.well-known/agent.json) and exchange tasks via a
|
|
8
|
+
* JSON-RPC envelope posted to the agent's task endpoint.
|
|
9
|
+
*
|
|
10
|
+
* References:
|
|
11
|
+
* https://google.github.io/A2A/
|
|
12
|
+
* https://github.com/google/A2A
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
*
|
|
16
|
+
* const adapter = new A2AAdapter();
|
|
17
|
+
* await adapter.initialize({});
|
|
18
|
+
*
|
|
19
|
+
* // Register a remote agent by its Agent Card URL
|
|
20
|
+
* await adapter.registerRemoteAgent('remote-analyst', 'https://agent.example.com');
|
|
21
|
+
*
|
|
22
|
+
* // Or register a local agent that serves an A2A-compliant card
|
|
23
|
+
* adapter.registerLocalA2AAgent('local-writer', {
|
|
24
|
+
* name: 'Writing Agent',
|
|
25
|
+
* description: 'Draft documents given a topic',
|
|
26
|
+
* version: '1.0',
|
|
27
|
+
* capabilities: { streaming: false },
|
|
28
|
+
* taskEndpoint: 'https://writer.internal/tasks',
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* await registry.addAdapter(adapter);
|
|
32
|
+
*
|
|
33
|
+
* // In the orchestrator:
|
|
34
|
+
* delegateTask({ targetAgent: 'a2a:remote-analyst', ... })
|
|
35
|
+
*
|
|
36
|
+
* @module A2AAdapter
|
|
37
|
+
* @version 1.0.0
|
|
38
|
+
*/
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.A2AAdapter = void 0;
|
|
41
|
+
const base_adapter_1 = require("./base-adapter");
|
|
42
|
+
class A2AAdapter extends base_adapter_1.BaseAdapter {
|
|
43
|
+
name = 'a2a';
|
|
44
|
+
version = '1.0.0';
|
|
45
|
+
a2aAgents = new Map();
|
|
46
|
+
defaultBearerToken;
|
|
47
|
+
defaultTimeoutMs = 30_000;
|
|
48
|
+
fetchImpl = globalThis.fetch;
|
|
49
|
+
get capabilities() {
|
|
50
|
+
return {
|
|
51
|
+
streaming: false,
|
|
52
|
+
parallel: true,
|
|
53
|
+
bidirectional: false,
|
|
54
|
+
discovery: true,
|
|
55
|
+
authentication: true,
|
|
56
|
+
statefulSessions: false,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
async initialize(config) {
|
|
60
|
+
await super.initialize(config);
|
|
61
|
+
if (config.defaultBearerToken)
|
|
62
|
+
this.defaultBearerToken = config.defaultBearerToken;
|
|
63
|
+
if (config.defaultTimeoutMs)
|
|
64
|
+
this.defaultTimeoutMs = config.defaultTimeoutMs;
|
|
65
|
+
if (config.fetchImpl)
|
|
66
|
+
this.fetchImpl = config.fetchImpl;
|
|
67
|
+
}
|
|
68
|
+
// ── Registration ────────────────────────────────────────────────────────────
|
|
69
|
+
/**
|
|
70
|
+
* Fetch the Agent Card from `<baseUrl>/.well-known/agent.json` and register
|
|
71
|
+
* the remote agent for use in the orchestrator.
|
|
72
|
+
*
|
|
73
|
+
* @param agentId - Local identifier (used in `delegate_task` calls)
|
|
74
|
+
* @param baseUrl - Root URL of the remote A2A-compliant agent server
|
|
75
|
+
* @param options - Optional bearer token / timeout override
|
|
76
|
+
*/
|
|
77
|
+
async registerRemoteAgent(agentId, baseUrl, options) {
|
|
78
|
+
const url = baseUrl.replace(/\/$/, '');
|
|
79
|
+
const card = await this.fetchAgentCard(url, options?.bearerToken ?? this.defaultBearerToken);
|
|
80
|
+
const taskEndpoint = card.taskEndpoint ??
|
|
81
|
+
(card.url ? `${card.url.replace(/\/$/, '')}/tasks` : `${url}/tasks`);
|
|
82
|
+
this.a2aAgents.set(agentId, {
|
|
83
|
+
baseUrl: url,
|
|
84
|
+
card,
|
|
85
|
+
taskEndpoint,
|
|
86
|
+
bearerToken: options?.bearerToken ?? this.defaultBearerToken,
|
|
87
|
+
timeoutMs: options?.timeoutMs ?? this.defaultTimeoutMs,
|
|
88
|
+
});
|
|
89
|
+
this.registerLocalAgent({
|
|
90
|
+
id: agentId,
|
|
91
|
+
name: card.name,
|
|
92
|
+
description: card.description ?? `Remote A2A agent at ${url}`,
|
|
93
|
+
capabilities: card.capabilities
|
|
94
|
+
? Object.keys(card.capabilities).filter(k => card.capabilities[k] === true)
|
|
95
|
+
: undefined,
|
|
96
|
+
status: 'available',
|
|
97
|
+
metadata: { a2aBaseUrl: url, taskEndpoint },
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Register a local A2A agent whose card you already have (no network fetch).
|
|
102
|
+
* Useful when the card is embedded in config or returned from another service.
|
|
103
|
+
*/
|
|
104
|
+
registerLocalA2AAgent(agentId, card, options) {
|
|
105
|
+
this.a2aAgents.set(agentId, {
|
|
106
|
+
baseUrl: card.url ?? '',
|
|
107
|
+
card,
|
|
108
|
+
taskEndpoint: card.taskEndpoint,
|
|
109
|
+
bearerToken: options?.bearerToken ?? this.defaultBearerToken,
|
|
110
|
+
timeoutMs: options?.timeoutMs ?? this.defaultTimeoutMs,
|
|
111
|
+
});
|
|
112
|
+
this.registerLocalAgent({
|
|
113
|
+
id: agentId,
|
|
114
|
+
name: card.name,
|
|
115
|
+
description: card.description ?? `Local A2A agent: ${agentId}`,
|
|
116
|
+
capabilities: card.capabilities
|
|
117
|
+
? Object.keys(card.capabilities).filter(k => card.capabilities[k] === true)
|
|
118
|
+
: undefined,
|
|
119
|
+
status: 'available',
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
// ── Execution ───────────────────────────────────────────────────────────────
|
|
123
|
+
async executeAgent(agentId, payload, context) {
|
|
124
|
+
this.ensureReady();
|
|
125
|
+
const config = this.a2aAgents.get(agentId);
|
|
126
|
+
if (!config) {
|
|
127
|
+
return this.errorResult('AGENT_NOT_FOUND', `A2A agent "${agentId}" is not registered. Call registerRemoteAgent() or registerLocalA2AAgent() first.`, false);
|
|
128
|
+
}
|
|
129
|
+
const startTime = Date.now();
|
|
130
|
+
// Build the task instruction from the handoff payload
|
|
131
|
+
const instruction = payload.handoff?.instruction ??
|
|
132
|
+
(payload.params ? JSON.stringify(payload.params) : 'No instruction provided');
|
|
133
|
+
const taskId = `${context.taskId ?? 'task'}-${Date.now()}`;
|
|
134
|
+
const taskEnvelope = {
|
|
135
|
+
jsonrpc: '2.0',
|
|
136
|
+
id: taskId,
|
|
137
|
+
method: 'tasks/send',
|
|
138
|
+
params: {
|
|
139
|
+
id: taskId,
|
|
140
|
+
message: {
|
|
141
|
+
role: 'user',
|
|
142
|
+
parts: [{ type: 'text', text: instruction }],
|
|
143
|
+
},
|
|
144
|
+
metadata: {
|
|
145
|
+
sourceAgent: context.agentId,
|
|
146
|
+
sessionId: context.sessionId,
|
|
147
|
+
...(payload.handoff?.context ?? {}),
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
try {
|
|
152
|
+
const response = await this.sendTask(config, taskEnvelope);
|
|
153
|
+
if (response.error) {
|
|
154
|
+
return this.errorResult(`A2A_ERROR_${response.error.code}`, response.error.message, response.error.code >= 500, response.error);
|
|
155
|
+
}
|
|
156
|
+
if (!response.result) {
|
|
157
|
+
return this.errorResult('A2A_EMPTY_RESPONSE', 'A2A response had no result field', true);
|
|
158
|
+
}
|
|
159
|
+
const state = response.result.status.state;
|
|
160
|
+
if (state === 'failed' || state === 'canceled') {
|
|
161
|
+
return this.errorResult(`A2A_TASK_${state.toUpperCase()}`, response.result.status.message ?? `Task ended with state: ${state}`, state === 'failed');
|
|
162
|
+
}
|
|
163
|
+
// Extract text from artifacts
|
|
164
|
+
const output = this.extractOutput(response.result.artifacts);
|
|
165
|
+
return this.successResult({ output, state, artifacts: response.result.artifacts, metadata: response.result.metadata }, Date.now() - startTime);
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
if (err instanceof Error && err.name === 'AbortError') {
|
|
169
|
+
return this.errorResult('A2A_TIMEOUT', `A2A request timed out after ${config.timeoutMs}ms`, true);
|
|
170
|
+
}
|
|
171
|
+
return this.errorResult('A2A_REQUEST_FAILED', err instanceof Error ? err.message : 'A2A request failed', true, err);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// ── Internals ───────────────────────────────────────────────────────────────
|
|
175
|
+
async fetchAgentCard(baseUrl, bearerToken) {
|
|
176
|
+
const cardUrl = `${baseUrl}/.well-known/agent.json`;
|
|
177
|
+
const headers = { Accept: 'application/json' };
|
|
178
|
+
if (bearerToken)
|
|
179
|
+
headers.Authorization = `Bearer ${bearerToken}`;
|
|
180
|
+
const controller = new AbortController();
|
|
181
|
+
const id = setTimeout(() => controller.abort(), this.defaultTimeoutMs);
|
|
182
|
+
let response;
|
|
183
|
+
try {
|
|
184
|
+
response = await this.fetchImpl(cardUrl, { headers, signal: controller.signal });
|
|
185
|
+
}
|
|
186
|
+
finally {
|
|
187
|
+
clearTimeout(id);
|
|
188
|
+
}
|
|
189
|
+
if (!response.ok) {
|
|
190
|
+
throw new Error(`Failed to fetch agent card from ${cardUrl}: HTTP ${response.status}`);
|
|
191
|
+
}
|
|
192
|
+
const card = await response.json();
|
|
193
|
+
if (!card.name) {
|
|
194
|
+
throw new Error(`Agent card at ${cardUrl} is missing required "name" field`);
|
|
195
|
+
}
|
|
196
|
+
return card;
|
|
197
|
+
}
|
|
198
|
+
async sendTask(config, task) {
|
|
199
|
+
const headers = {
|
|
200
|
+
'Content-Type': 'application/json',
|
|
201
|
+
Accept: 'application/json',
|
|
202
|
+
};
|
|
203
|
+
if (config.bearerToken)
|
|
204
|
+
headers.Authorization = `Bearer ${config.bearerToken}`;
|
|
205
|
+
const controller = new AbortController();
|
|
206
|
+
const id = setTimeout(() => controller.abort(), config.timeoutMs);
|
|
207
|
+
let response;
|
|
208
|
+
try {
|
|
209
|
+
response = await this.fetchImpl(config.taskEndpoint, {
|
|
210
|
+
method: 'POST',
|
|
211
|
+
headers,
|
|
212
|
+
body: JSON.stringify(task),
|
|
213
|
+
signal: controller.signal,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
finally {
|
|
217
|
+
clearTimeout(id);
|
|
218
|
+
}
|
|
219
|
+
if (!response.ok) {
|
|
220
|
+
throw new Error(`A2A task endpoint returned HTTP ${response.status}: ${response.statusText}`);
|
|
221
|
+
}
|
|
222
|
+
return response.json();
|
|
223
|
+
}
|
|
224
|
+
extractOutput(artifacts) {
|
|
225
|
+
if (!artifacts?.length)
|
|
226
|
+
return '';
|
|
227
|
+
return artifacts
|
|
228
|
+
.flatMap(a => a.parts)
|
|
229
|
+
.filter(p => p.type === 'text' && typeof p.text === 'string')
|
|
230
|
+
.map(p => p.text)
|
|
231
|
+
.join('\n');
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
exports.A2AAdapter = A2AAdapter;
|
|
235
|
+
//# sourceMappingURL=a2a-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"a2a-adapter.js","sourceRoot":"","sources":["../../adapters/a2a-adapter.ts"],"names":[],"mappings":"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"}
|