@perkos/perkos-a2a 0.3.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/LICENSE +21 -0
- package/README.md +620 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +236 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +36 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +287 -0
- package/dist/server.js.map +1 -0
- package/dist/types.d.ts +78 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/openclaw.plugin.json +65 -0
- package/package.json +53 -0
- package/skills/a2a/SKILL.md +33 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PerkOS
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,620 @@
|
|
|
1
|
+
# @perkos/a2a
|
|
2
|
+
|
|
3
|
+
Agent-to-Agent (A2A) protocol communication plugin for [OpenClaw](https://github.com/openclaw/openclaw).
|
|
4
|
+
|
|
5
|
+
Implements Google's [A2A Protocol](https://github.com/a2aproject/A2A) (v0.3.0) to enable OpenClaw agents to discover each other, send tasks, and collaborate autonomously.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Agent Card Discovery** — Each agent publishes identity and skills at `/.well-known/agent-card.json`
|
|
10
|
+
- **JSON-RPC 2.0** — Standard A2A protocol methods: `message/send`, `tasks/get`, `tasks/list`, `tasks/cancel`
|
|
11
|
+
- **OpenClaw Tools** — `a2a_discover`, `a2a_send_task`, `a2a_task_status` available to the LLM
|
|
12
|
+
- **CLI Commands** — `openclaw a2a status`, `openclaw a2a discover`, `openclaw a2a send`
|
|
13
|
+
- **Peer Discovery** — Automatic discovery of online agents in the network
|
|
14
|
+
- **Background Service** — A2A HTTP server runs alongside the OpenClaw gateway
|
|
15
|
+
|
|
16
|
+
## Architecture
|
|
17
|
+
|
|
18
|
+
### System Overview
|
|
19
|
+
|
|
20
|
+
```mermaid
|
|
21
|
+
graph TB
|
|
22
|
+
subgraph Internet
|
|
23
|
+
TG[Telegram]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
subgraph Docker Network - council
|
|
27
|
+
subgraph Mimir Container
|
|
28
|
+
M_OC[OpenClaw Gateway :3000]
|
|
29
|
+
M_A2A["@perkos/a2a Plugin :5000"]
|
|
30
|
+
M_OC --- M_A2A
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
subgraph Tyr Container
|
|
34
|
+
T_OC[OpenClaw Gateway :3000]
|
|
35
|
+
T_A2A["@perkos/a2a Plugin :5000"]
|
|
36
|
+
T_OC --- T_A2A
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
subgraph Bragi Container
|
|
40
|
+
B_OC[OpenClaw Gateway :3000]
|
|
41
|
+
B_A2A["@perkos/a2a Plugin :5000"]
|
|
42
|
+
B_OC --- B_A2A
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
subgraph Idunn Container
|
|
46
|
+
I_OC[OpenClaw Gateway :3000]
|
|
47
|
+
I_A2A["@perkos/a2a Plugin :5000"]
|
|
48
|
+
I_OC --- I_A2A
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
TG <--> M_OC
|
|
53
|
+
TG <--> T_OC
|
|
54
|
+
TG <--> B_OC
|
|
55
|
+
TG <--> I_OC
|
|
56
|
+
|
|
57
|
+
M_A2A <-->|A2A JSON-RPC| T_A2A
|
|
58
|
+
M_A2A <-->|A2A JSON-RPC| B_A2A
|
|
59
|
+
M_A2A <-->|A2A JSON-RPC| I_A2A
|
|
60
|
+
T_A2A <-->|A2A JSON-RPC| B_A2A
|
|
61
|
+
T_A2A <-->|A2A JSON-RPC| I_A2A
|
|
62
|
+
B_A2A <-->|A2A JSON-RPC| I_A2A
|
|
63
|
+
|
|
64
|
+
style M_OC fill:#eb1b69,color:#fff
|
|
65
|
+
style T_OC fill:#eb1b69,color:#fff
|
|
66
|
+
style B_OC fill:#eb1b69,color:#fff
|
|
67
|
+
style I_OC fill:#eb1b69,color:#fff
|
|
68
|
+
style M_A2A fill:#8e2051,color:#fff
|
|
69
|
+
style T_A2A fill:#8e2051,color:#fff
|
|
70
|
+
style B_A2A fill:#8e2051,color:#fff
|
|
71
|
+
style I_A2A fill:#8e2051,color:#fff
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Plugin Architecture
|
|
75
|
+
|
|
76
|
+
```mermaid
|
|
77
|
+
graph LR
|
|
78
|
+
subgraph OpenClaw Gateway
|
|
79
|
+
LLM[LLM Agent]
|
|
80
|
+
Tools[Tool Registry]
|
|
81
|
+
Session[Session Manager]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
subgraph "@perkos/a2a Plugin"
|
|
85
|
+
Service[Background Service]
|
|
86
|
+
Express[Express HTTP Server]
|
|
87
|
+
AgentCard[Agent Card Provider]
|
|
88
|
+
TaskStore[In-Memory Task Store]
|
|
89
|
+
Client[A2A Client]
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
subgraph Endpoints
|
|
93
|
+
WK["/.well-known/agent-card.json"]
|
|
94
|
+
RPC["/a2a/jsonrpc"]
|
|
95
|
+
Health["/health"]
|
|
96
|
+
Peers["/a2a/peers"]
|
|
97
|
+
Send["/a2a/send"]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
LLM --> Tools
|
|
101
|
+
Tools -->|a2a_discover| Client
|
|
102
|
+
Tools -->|a2a_send_task| Client
|
|
103
|
+
Tools -->|a2a_task_status| Client
|
|
104
|
+
|
|
105
|
+
Service --> Express
|
|
106
|
+
Express --> WK
|
|
107
|
+
Express --> RPC
|
|
108
|
+
Express --> Health
|
|
109
|
+
Express --> Peers
|
|
110
|
+
Express --> Send
|
|
111
|
+
|
|
112
|
+
RPC --> TaskStore
|
|
113
|
+
WK --> AgentCard
|
|
114
|
+
Client -->|HTTP POST| RPC
|
|
115
|
+
|
|
116
|
+
style LLM fill:#eb1b69,color:#fff
|
|
117
|
+
style Service fill:#8e2051,color:#fff
|
|
118
|
+
style Express fill:#76437b,color:#fff
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Protocol Specification
|
|
122
|
+
|
|
123
|
+
### A2A Protocol Layers
|
|
124
|
+
|
|
125
|
+
This plugin implements the three layers of the A2A Protocol Specification:
|
|
126
|
+
|
|
127
|
+
```mermaid
|
|
128
|
+
graph TB
|
|
129
|
+
subgraph "Layer 1: Data Model"
|
|
130
|
+
Task[Task]
|
|
131
|
+
Message[Message]
|
|
132
|
+
AgentCard[AgentCard]
|
|
133
|
+
Part[Part]
|
|
134
|
+
Artifact[Artifact]
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
subgraph "Layer 2: Operations"
|
|
138
|
+
SendMsg["message/send"]
|
|
139
|
+
GetTask["tasks/get"]
|
|
140
|
+
ListTasks["tasks/list"]
|
|
141
|
+
CancelTask["tasks/cancel"]
|
|
142
|
+
GetCard["agent/card"]
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
subgraph "Layer 3: Protocol Binding"
|
|
146
|
+
JSONRPC["JSON-RPC 2.0 over HTTP"]
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
Task --> SendMsg
|
|
150
|
+
Message --> SendMsg
|
|
151
|
+
AgentCard --> GetCard
|
|
152
|
+
Part --> Message
|
|
153
|
+
Artifact --> Task
|
|
154
|
+
|
|
155
|
+
SendMsg --> JSONRPC
|
|
156
|
+
GetTask --> JSONRPC
|
|
157
|
+
ListTasks --> JSONRPC
|
|
158
|
+
CancelTask --> JSONRPC
|
|
159
|
+
GetCard --> JSONRPC
|
|
160
|
+
|
|
161
|
+
style Task fill:#e1f5fe,color:#000
|
|
162
|
+
style Message fill:#e1f5fe,color:#000
|
|
163
|
+
style AgentCard fill:#e1f5fe,color:#000
|
|
164
|
+
style Part fill:#e1f5fe,color:#000
|
|
165
|
+
style Artifact fill:#e1f5fe,color:#000
|
|
166
|
+
style SendMsg fill:#f3e5f5,color:#000
|
|
167
|
+
style GetTask fill:#f3e5f5,color:#000
|
|
168
|
+
style ListTasks fill:#f3e5f5,color:#000
|
|
169
|
+
style CancelTask fill:#f3e5f5,color:#000
|
|
170
|
+
style GetCard fill:#f3e5f5,color:#000
|
|
171
|
+
style JSONRPC fill:#e8f5e8,color:#000
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Task Lifecycle
|
|
175
|
+
|
|
176
|
+
```mermaid
|
|
177
|
+
stateDiagram-v2
|
|
178
|
+
[*] --> submitted: message/send received
|
|
179
|
+
submitted --> working: Processing begins
|
|
180
|
+
working --> completed: Task finished successfully
|
|
181
|
+
working --> failed: Error during processing
|
|
182
|
+
working --> canceled: tasks/cancel received
|
|
183
|
+
completed --> [*]
|
|
184
|
+
failed --> [*]
|
|
185
|
+
canceled --> [*]
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Agent Discovery Sequence
|
|
189
|
+
|
|
190
|
+
```mermaid
|
|
191
|
+
sequenceDiagram
|
|
192
|
+
participant User
|
|
193
|
+
participant Mimir as Mimir (Orchestrator)
|
|
194
|
+
participant TyrCard as Tyr /.well-known/agent-card.json
|
|
195
|
+
participant BragiCard as Bragi /.well-known/agent-card.json
|
|
196
|
+
participant IdunnCard as Idunn /.well-known/agent-card.json
|
|
197
|
+
|
|
198
|
+
User->>Mimir: "Discover all agents"
|
|
199
|
+
activate Mimir
|
|
200
|
+
Mimir->>Mimir: a2a_discover tool invoked
|
|
201
|
+
|
|
202
|
+
par Parallel Discovery
|
|
203
|
+
Mimir->>TyrCard: GET /.well-known/agent-card.json
|
|
204
|
+
TyrCard-->>Mimir: AgentCard {name, skills, url}
|
|
205
|
+
and
|
|
206
|
+
Mimir->>BragiCard: GET /.well-known/agent-card.json
|
|
207
|
+
BragiCard-->>Mimir: AgentCard {name, skills, url}
|
|
208
|
+
and
|
|
209
|
+
Mimir->>IdunnCard: GET /.well-known/agent-card.json
|
|
210
|
+
IdunnCard-->>Mimir: AgentCard {name, skills, url}
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
Mimir-->>User: "3 agents online: Tyr (engineering), Bragi (comms), Idunn (product)"
|
|
214
|
+
deactivate Mimir
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Task Delegation Sequence
|
|
218
|
+
|
|
219
|
+
```mermaid
|
|
220
|
+
sequenceDiagram
|
|
221
|
+
participant User
|
|
222
|
+
participant Mimir as Mimir (Orchestrator)
|
|
223
|
+
participant TyrA2A as Tyr A2A Server
|
|
224
|
+
participant TyrOC as Tyr OpenClaw Agent
|
|
225
|
+
participant TyrFS as Tyr Workspace
|
|
226
|
+
|
|
227
|
+
User->>Mimir: "Ask Tyr to implement rate limiting"
|
|
228
|
+
activate Mimir
|
|
229
|
+
Mimir->>Mimir: a2a_send_task(target="tyr", message="...")
|
|
230
|
+
|
|
231
|
+
Mimir->>TyrA2A: POST /a2a/jsonrpc {method: "message/send"}
|
|
232
|
+
activate TyrA2A
|
|
233
|
+
|
|
234
|
+
TyrA2A->>TyrA2A: Create Task (state: submitted)
|
|
235
|
+
TyrA2A-->>Mimir: Task {id, status: "submitted"}
|
|
236
|
+
Mimir-->>User: "Task sent to Tyr. ID: abc-123"
|
|
237
|
+
deactivate Mimir
|
|
238
|
+
|
|
239
|
+
TyrA2A->>TyrA2A: Process Task (state: working)
|
|
240
|
+
TyrA2A->>TyrFS: Write task to memory/a2a-task-{id}.md
|
|
241
|
+
TyrA2A->>TyrA2A: Complete Task (state: completed)
|
|
242
|
+
deactivate TyrA2A
|
|
243
|
+
|
|
244
|
+
Note over TyrOC: Agent picks up task<br/>from workspace on<br/>next heartbeat/session
|
|
245
|
+
|
|
246
|
+
User->>Mimir: "Check status of task abc-123 on Tyr"
|
|
247
|
+
activate Mimir
|
|
248
|
+
Mimir->>TyrA2A: POST /a2a/jsonrpc {method: "tasks/get", id: "abc-123"}
|
|
249
|
+
TyrA2A-->>Mimir: Task {status: "completed", artifacts: [...]}
|
|
250
|
+
Mimir-->>User: "Task completed"
|
|
251
|
+
deactivate Mimir
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Multi-Agent Collaboration Sequence
|
|
255
|
+
|
|
256
|
+
```mermaid
|
|
257
|
+
sequenceDiagram
|
|
258
|
+
participant J as Julio (Founder)
|
|
259
|
+
participant M as Mimir (Strategy)
|
|
260
|
+
participant T as Tyr (Engineering)
|
|
261
|
+
participant B as Bragi (Comms)
|
|
262
|
+
participant I as Idunn (Product)
|
|
263
|
+
|
|
264
|
+
J->>M: "Build a landing page for PerkOS"
|
|
265
|
+
activate M
|
|
266
|
+
|
|
267
|
+
M->>M: Strategic analysis
|
|
268
|
+
Note over M: Break into subtasks:<br/>1. UX spec (Idunn)<br/>2. Implementation (Tyr)<br/>3. Copy (Bragi)
|
|
269
|
+
|
|
270
|
+
M->>I: a2a_send_task("Design the landing page UX")
|
|
271
|
+
activate I
|
|
272
|
+
I-->>M: Task accepted (UX spec)
|
|
273
|
+
I->>I: Creates wireframes + spec
|
|
274
|
+
deactivate I
|
|
275
|
+
|
|
276
|
+
M->>T: a2a_send_task("Implement landing page per Idunn's spec")
|
|
277
|
+
activate T
|
|
278
|
+
T-->>M: Task accepted (implementation)
|
|
279
|
+
T->>T: Writes Next.js + Tailwind code
|
|
280
|
+
deactivate T
|
|
281
|
+
|
|
282
|
+
M->>B: a2a_send_task("Write landing page copy for PerkOS")
|
|
283
|
+
activate B
|
|
284
|
+
B-->>M: Task accepted (copywriting)
|
|
285
|
+
B->>B: Writes headlines, CTAs, descriptions
|
|
286
|
+
deactivate B
|
|
287
|
+
|
|
288
|
+
M-->>J: "Landing page tasks delegated to Idunn (UX), Tyr (code), Bragi (copy)"
|
|
289
|
+
deactivate M
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Data Model
|
|
293
|
+
|
|
294
|
+
### Agent Card
|
|
295
|
+
|
|
296
|
+
Each agent publishes an Agent Card describing its identity and capabilities:
|
|
297
|
+
|
|
298
|
+
```json
|
|
299
|
+
{
|
|
300
|
+
"name": "Tyr",
|
|
301
|
+
"description": "Engineering and execution agent",
|
|
302
|
+
"protocolVersion": "0.3.0",
|
|
303
|
+
"version": "1.0.0",
|
|
304
|
+
"url": "http://perkos-tyr:5000/a2a/jsonrpc",
|
|
305
|
+
"skills": [
|
|
306
|
+
{
|
|
307
|
+
"id": "code",
|
|
308
|
+
"name": "Code Implementation",
|
|
309
|
+
"description": "Write production-quality TypeScript, Solidity, Next.js code",
|
|
310
|
+
"tags": ["coding", "typescript", "solidity"]
|
|
311
|
+
}
|
|
312
|
+
],
|
|
313
|
+
"capabilities": { "pushNotifications": false },
|
|
314
|
+
"defaultInputModes": ["text"],
|
|
315
|
+
"defaultOutputModes": ["text"]
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Task
|
|
320
|
+
|
|
321
|
+
Tasks track the lifecycle of delegated work:
|
|
322
|
+
|
|
323
|
+
```json
|
|
324
|
+
{
|
|
325
|
+
"kind": "task",
|
|
326
|
+
"id": "f49f9755-86b9-4399-9463-fa6b9a11b51a",
|
|
327
|
+
"contextId": "cc57cc50-762c-41d4-b9a1-59b1ee691a69",
|
|
328
|
+
"status": {
|
|
329
|
+
"state": "completed",
|
|
330
|
+
"timestamp": "2026-03-12T16:24:45.709Z"
|
|
331
|
+
},
|
|
332
|
+
"messages": [
|
|
333
|
+
{
|
|
334
|
+
"kind": "message",
|
|
335
|
+
"messageId": "a008eb3e-2fb0-4947-b1e4-15a6d3a8cba5",
|
|
336
|
+
"role": "user",
|
|
337
|
+
"parts": [{ "kind": "text", "text": "Implement rate limiting on the API" }],
|
|
338
|
+
"metadata": { "fromAgent": "mimir" }
|
|
339
|
+
}
|
|
340
|
+
],
|
|
341
|
+
"artifacts": [
|
|
342
|
+
{
|
|
343
|
+
"kind": "artifact",
|
|
344
|
+
"artifactId": "b2c3d4e5-...",
|
|
345
|
+
"parts": [{ "kind": "text", "text": "Task queued for processing" }]
|
|
346
|
+
}
|
|
347
|
+
]
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Message
|
|
352
|
+
|
|
353
|
+
Messages are communication turns between agents:
|
|
354
|
+
|
|
355
|
+
```json
|
|
356
|
+
{
|
|
357
|
+
"kind": "message",
|
|
358
|
+
"messageId": "unique-id",
|
|
359
|
+
"role": "user",
|
|
360
|
+
"parts": [
|
|
361
|
+
{ "kind": "text", "text": "Your task description here" }
|
|
362
|
+
],
|
|
363
|
+
"metadata": {
|
|
364
|
+
"fromAgent": "mimir"
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
## JSON-RPC 2.0 Methods
|
|
370
|
+
|
|
371
|
+
| Method | Description | Request Params | Response |
|
|
372
|
+
|--------|------------|----------------|----------|
|
|
373
|
+
| `message/send` | Send a task to the agent | `{message: Message}` | `Task` |
|
|
374
|
+
| `tasks/get` | Get task by ID | `{id: string}` | `Task` |
|
|
375
|
+
| `tasks/list` | List all tasks | `{}` | `{tasks: Task[]}` |
|
|
376
|
+
| `tasks/cancel` | Cancel a running task | `{id: string}` | `Task` |
|
|
377
|
+
| `agent/card` | Get the agent's card | `{}` | `AgentCard` |
|
|
378
|
+
|
|
379
|
+
### Example JSON-RPC Request
|
|
380
|
+
|
|
381
|
+
```json
|
|
382
|
+
{
|
|
383
|
+
"jsonrpc": "2.0",
|
|
384
|
+
"method": "message/send",
|
|
385
|
+
"id": "req-1",
|
|
386
|
+
"params": {
|
|
387
|
+
"message": {
|
|
388
|
+
"kind": "message",
|
|
389
|
+
"messageId": "msg-1",
|
|
390
|
+
"role": "user",
|
|
391
|
+
"parts": [{"kind": "text", "text": "Review the API security"}],
|
|
392
|
+
"metadata": {"fromAgent": "mimir"}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### Example JSON-RPC Response
|
|
399
|
+
|
|
400
|
+
```json
|
|
401
|
+
{
|
|
402
|
+
"jsonrpc": "2.0",
|
|
403
|
+
"id": "req-1",
|
|
404
|
+
"result": {
|
|
405
|
+
"kind": "task",
|
|
406
|
+
"id": "task-uuid",
|
|
407
|
+
"contextId": "ctx-uuid",
|
|
408
|
+
"status": {"state": "submitted", "timestamp": "2026-03-12T16:00:00Z"},
|
|
409
|
+
"messages": [...],
|
|
410
|
+
"artifacts": []
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
## HTTP Endpoints
|
|
416
|
+
|
|
417
|
+
| Endpoint | Method | Description |
|
|
418
|
+
|----------|--------|-------------|
|
|
419
|
+
| `/.well-known/agent-card.json` | GET | A2A Agent Card (discovery) |
|
|
420
|
+
| `/a2a/jsonrpc` | POST | JSON-RPC 2.0 endpoint |
|
|
421
|
+
| `/a2a/peers` | GET | Discover all peer agents |
|
|
422
|
+
| `/a2a/send` | POST | REST convenience for sending tasks |
|
|
423
|
+
| `/health` | GET | Health check with agent info |
|
|
424
|
+
|
|
425
|
+
## OpenClaw Integration
|
|
426
|
+
|
|
427
|
+
### Registered Tools
|
|
428
|
+
|
|
429
|
+
| Tool | Description | Parameters |
|
|
430
|
+
|------|-------------|------------|
|
|
431
|
+
| `a2a_discover` | Discover peer agents and capabilities | none |
|
|
432
|
+
| `a2a_send_task` | Send a task to a peer agent | `target`, `message` |
|
|
433
|
+
| `a2a_task_status` | Check status of a sent task | `target`, `taskId` |
|
|
434
|
+
|
|
435
|
+
### CLI Commands
|
|
436
|
+
|
|
437
|
+
```bash
|
|
438
|
+
openclaw a2a status # Show A2A agent configuration
|
|
439
|
+
openclaw a2a discover # Discover and list peer agents
|
|
440
|
+
openclaw a2a send <agent> <message> # Send a task to a peer
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### Gateway RPC
|
|
444
|
+
|
|
445
|
+
```bash
|
|
446
|
+
openclaw gateway call a2a.status # Get A2A status via RPC
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
## ⚠️ macOS Note
|
|
450
|
+
|
|
451
|
+
On macOS, **port 5000 is used by AirPlay Receiver** (ControlCenter). The default port is `5050` to avoid conflicts. If the configured port is in use, the plugin automatically tries the next port (up to 3 attempts). Docker/Linux agents can still use port 5000 via explicit config.
|
|
452
|
+
|
|
453
|
+
## Installation
|
|
454
|
+
|
|
455
|
+
### From npm
|
|
456
|
+
|
|
457
|
+
```bash
|
|
458
|
+
openclaw plugins install @perkos/a2a
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### Manual Installation
|
|
462
|
+
|
|
463
|
+
```bash
|
|
464
|
+
git clone https://github.com/PerkOS-xyz/PerkOS-A2A.git
|
|
465
|
+
cd PerkOS-A2A
|
|
466
|
+
npm install
|
|
467
|
+
npm run build
|
|
468
|
+
openclaw plugins install -l .
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
## Configuration
|
|
472
|
+
|
|
473
|
+
Add to your `openclaw.json`:
|
|
474
|
+
|
|
475
|
+
```json5
|
|
476
|
+
{
|
|
477
|
+
plugins: {
|
|
478
|
+
entries: {
|
|
479
|
+
"perkos-a2a": {
|
|
480
|
+
enabled: true,
|
|
481
|
+
config: {
|
|
482
|
+
// This agent's name in the network
|
|
483
|
+
agentName: "mimir",
|
|
484
|
+
// Port for the A2A HTTP server (default 5050; use 5000 on Linux/Docker)
|
|
485
|
+
port: 5050,
|
|
486
|
+
// Skills this agent exposes
|
|
487
|
+
skills: [
|
|
488
|
+
{
|
|
489
|
+
id: "strategy",
|
|
490
|
+
name: "Strategic Planning",
|
|
491
|
+
description: "Break down goals into actionable tasks",
|
|
492
|
+
tags: ["planning", "strategy"]
|
|
493
|
+
}
|
|
494
|
+
],
|
|
495
|
+
// Peer agents (name -> A2A URL)
|
|
496
|
+
peers: {
|
|
497
|
+
tyr: "http://perkos-tyr:5000",
|
|
498
|
+
bragi: "http://perkos-bragi:5000",
|
|
499
|
+
idunn: "http://perkos-idunn:5000"
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
### Configuration Options
|
|
509
|
+
|
|
510
|
+
| Option | Type | Default | Description |
|
|
511
|
+
|--------|------|---------|-------------|
|
|
512
|
+
| `agentName` | string | `"agent"` | This agent's name in the network |
|
|
513
|
+
| `port` | number | `5050` | Port for the A2A HTTP server (macOS avoids 5000/AirPlay) |
|
|
514
|
+
| `skills` | array | `[]` | Skills to advertise in the Agent Card |
|
|
515
|
+
| `peers` | object | `{}` | Map of peer agent names to A2A URLs |
|
|
516
|
+
|
|
517
|
+
## Docker Deployment
|
|
518
|
+
|
|
519
|
+
For multi-agent setups, use Docker Compose with a shared network:
|
|
520
|
+
|
|
521
|
+
```yaml
|
|
522
|
+
services:
|
|
523
|
+
mimir:
|
|
524
|
+
build: .
|
|
525
|
+
container_name: perkos-mimir
|
|
526
|
+
ports:
|
|
527
|
+
- "3001:3000" # OpenClaw
|
|
528
|
+
- "5001:5000" # A2A
|
|
529
|
+
environment:
|
|
530
|
+
- AGENT_NAME=mimir
|
|
531
|
+
networks:
|
|
532
|
+
- council
|
|
533
|
+
|
|
534
|
+
tyr:
|
|
535
|
+
build: .
|
|
536
|
+
container_name: perkos-tyr
|
|
537
|
+
ports:
|
|
538
|
+
- "3002:3000"
|
|
539
|
+
- "5002:5000"
|
|
540
|
+
environment:
|
|
541
|
+
- AGENT_NAME=tyr
|
|
542
|
+
networks:
|
|
543
|
+
- council
|
|
544
|
+
|
|
545
|
+
networks:
|
|
546
|
+
council:
|
|
547
|
+
driver: bridge
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
Agents can discover each other via Docker DNS: `http://perkos-tyr:5000`.
|
|
551
|
+
|
|
552
|
+
## A2A Protocol Compliance
|
|
553
|
+
|
|
554
|
+
This plugin implements the [A2A Protocol Specification RC v1.0](https://a2a-protocol.org/latest/specification/):
|
|
555
|
+
|
|
556
|
+
| Feature | Status |
|
|
557
|
+
|---------|--------|
|
|
558
|
+
| Agent Card at `/.well-known/agent-card.json` | ✅ |
|
|
559
|
+
| JSON-RPC 2.0 binding | ✅ |
|
|
560
|
+
| `message/send` | ✅ |
|
|
561
|
+
| `tasks/get` | ✅ |
|
|
562
|
+
| `tasks/list` | ✅ |
|
|
563
|
+
| `tasks/cancel` | ✅ |
|
|
564
|
+
| Task lifecycle states | ✅ |
|
|
565
|
+
| Text parts | ✅ |
|
|
566
|
+
| Artifact generation | ✅ |
|
|
567
|
+
| Streaming (SSE) | 🔜 Planned |
|
|
568
|
+
| Push notifications | 🔜 Planned |
|
|
569
|
+
| File parts | 🔜 Planned |
|
|
570
|
+
| gRPC binding | 🔜 Planned |
|
|
571
|
+
|
|
572
|
+
## TypeScript Types
|
|
573
|
+
|
|
574
|
+
The plugin exports full TypeScript types for the A2A protocol:
|
|
575
|
+
|
|
576
|
+
```typescript
|
|
577
|
+
import type {
|
|
578
|
+
AgentCard,
|
|
579
|
+
AgentSkill,
|
|
580
|
+
Task,
|
|
581
|
+
TaskStatus,
|
|
582
|
+
Message,
|
|
583
|
+
Part,
|
|
584
|
+
Artifact,
|
|
585
|
+
JsonRpcRequest,
|
|
586
|
+
JsonRpcResponse,
|
|
587
|
+
A2APluginConfig,
|
|
588
|
+
} from "@perkos/a2a";
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
## Standalone Server
|
|
592
|
+
|
|
593
|
+
You can also use the A2A server independently of OpenClaw:
|
|
594
|
+
|
|
595
|
+
```typescript
|
|
596
|
+
import { A2AServer } from "@perkos/a2a";
|
|
597
|
+
|
|
598
|
+
const server = new A2AServer({
|
|
599
|
+
agentName: "my-agent",
|
|
600
|
+
port: 5050,
|
|
601
|
+
skills: [{ id: "chat", name: "Chat", description: "General chat", tags: [] }],
|
|
602
|
+
peers: {
|
|
603
|
+
other: "http://other-agent:5050",
|
|
604
|
+
},
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
server.start();
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
## License
|
|
611
|
+
|
|
612
|
+
MIT
|
|
613
|
+
|
|
614
|
+
## Links
|
|
615
|
+
|
|
616
|
+
- [A2A Protocol Specification](https://a2a-protocol.org/latest/specification/)
|
|
617
|
+
- [A2A GitHub](https://github.com/a2aproject/A2A)
|
|
618
|
+
- [A2A JS SDK](https://github.com/a2aproject/a2a-js)
|
|
619
|
+
- [OpenClaw](https://github.com/openclaw/openclaw)
|
|
620
|
+
- [PerkOS](https://perkos.xyz)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @perkos/a2a — OpenClaw Plugin
|
|
3
|
+
*
|
|
4
|
+
* Agent-to-Agent (A2A) protocol communication plugin.
|
|
5
|
+
* Adds tools for agents to discover peers, send tasks, and check task status.
|
|
6
|
+
* Runs an A2A-compliant HTTP server alongside the OpenClaw gateway.
|
|
7
|
+
*/
|
|
8
|
+
export { A2AServer } from "./server.js";
|
|
9
|
+
export * from "./types.js";
|
|
10
|
+
export default function register(api: any): void;
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,cAAc,YAAY,CAAC;AAE3B,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAG,EAAE,GAAG,QAsPxC"}
|