@clawcrony/claw-crony 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +82 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +720 -0
- package/dist/index.js.map +1 -0
- package/dist/src/agent-card.d.ts +4 -0
- package/dist/src/agent-card.d.ts.map +1 -0
- package/dist/src/agent-card.js +61 -0
- package/dist/src/agent-card.js.map +1 -0
- package/dist/src/audit.d.ts +36 -0
- package/dist/src/audit.d.ts.map +1 -0
- package/dist/src/audit.js +88 -0
- package/dist/src/audit.js.map +1 -0
- package/dist/src/client.d.ts +53 -0
- package/dist/src/client.d.ts.map +1 -0
- package/dist/src/client.js +322 -0
- package/dist/src/client.js.map +1 -0
- package/dist/src/executor.d.ts +34 -0
- package/dist/src/executor.d.ts.map +1 -0
- package/dist/src/executor.js +994 -0
- package/dist/src/executor.js.map +1 -0
- package/dist/src/file-security.d.ts +63 -0
- package/dist/src/file-security.d.ts.map +1 -0
- package/dist/src/file-security.js +350 -0
- package/dist/src/file-security.js.map +1 -0
- package/dist/src/hub-match.d.ts +73 -0
- package/dist/src/hub-match.d.ts.map +1 -0
- package/dist/src/hub-match.js +120 -0
- package/dist/src/hub-match.js.map +1 -0
- package/dist/src/hub-registration.d.ts +24 -0
- package/dist/src/hub-registration.d.ts.map +1 -0
- package/dist/src/hub-registration.js +242 -0
- package/dist/src/hub-registration.js.map +1 -0
- package/dist/src/internal/envelope.d.ts +33 -0
- package/dist/src/internal/envelope.d.ts.map +1 -0
- package/dist/src/internal/envelope.js +152 -0
- package/dist/src/internal/envelope.js.map +1 -0
- package/dist/src/internal/idempotency.d.ts +48 -0
- package/dist/src/internal/idempotency.d.ts.map +1 -0
- package/dist/src/internal/idempotency.js +82 -0
- package/dist/src/internal/idempotency.js.map +1 -0
- package/dist/src/internal/metrics.d.ts +38 -0
- package/dist/src/internal/metrics.d.ts.map +1 -0
- package/dist/src/internal/metrics.js +83 -0
- package/dist/src/internal/metrics.js.map +1 -0
- package/dist/src/internal/outbox.d.ts +49 -0
- package/dist/src/internal/outbox.d.ts.map +1 -0
- package/dist/src/internal/outbox.js +149 -0
- package/dist/src/internal/outbox.js.map +1 -0
- package/dist/src/internal/routing.d.ts +28 -0
- package/dist/src/internal/routing.d.ts.map +1 -0
- package/dist/src/internal/routing.js +57 -0
- package/dist/src/internal/routing.js.map +1 -0
- package/dist/src/internal/security.d.ts +53 -0
- package/dist/src/internal/security.d.ts.map +1 -0
- package/dist/src/internal/security.js +122 -0
- package/dist/src/internal/security.js.map +1 -0
- package/dist/src/internal/transport.d.ts +49 -0
- package/dist/src/internal/transport.d.ts.map +1 -0
- package/dist/src/internal/transport.js +207 -0
- package/dist/src/internal/transport.js.map +1 -0
- package/dist/src/internal/types-internal.d.ts +95 -0
- package/dist/src/internal/types-internal.d.ts.map +1 -0
- package/dist/src/internal/types-internal.js +9 -0
- package/dist/src/internal/types-internal.js.map +1 -0
- package/dist/src/peer-health.d.ts +47 -0
- package/dist/src/peer-health.d.ts.map +1 -0
- package/dist/src/peer-health.js +169 -0
- package/dist/src/peer-health.js.map +1 -0
- package/dist/src/peer-retry.d.ts +16 -0
- package/dist/src/peer-retry.d.ts.map +1 -0
- package/dist/src/peer-retry.js +75 -0
- package/dist/src/peer-retry.js.map +1 -0
- package/dist/src/queueing-executor.d.ts +23 -0
- package/dist/src/queueing-executor.d.ts.map +1 -0
- package/dist/src/queueing-executor.js +179 -0
- package/dist/src/queueing-executor.js.map +1 -0
- package/dist/src/routing-rules.d.ts +53 -0
- package/dist/src/routing-rules.d.ts.map +1 -0
- package/dist/src/routing-rules.js +130 -0
- package/dist/src/routing-rules.js.map +1 -0
- package/dist/src/task-cleanup.d.ts +21 -0
- package/dist/src/task-cleanup.d.ts.map +1 -0
- package/dist/src/task-cleanup.js +77 -0
- package/dist/src/task-cleanup.js.map +1 -0
- package/dist/src/task-store.d.ts +16 -0
- package/dist/src/task-store.d.ts.map +1 -0
- package/dist/src/task-store.js +80 -0
- package/dist/src/task-store.js.map +1 -0
- package/dist/src/telemetry.d.ts +88 -0
- package/dist/src/telemetry.d.ts.map +1 -0
- package/dist/src/telemetry.js +235 -0
- package/dist/src/telemetry.js.map +1 -0
- package/dist/src/transport-fallback.d.ts +29 -0
- package/dist/src/transport-fallback.d.ts.map +1 -0
- package/dist/src/transport-fallback.js +81 -0
- package/dist/src/transport-fallback.js.map +1 -0
- package/dist/src/types.d.ts +160 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +7 -0
- package/dist/src/types.js.map +1 -0
- package/openclaw.plugin.json +272 -0
- package/package.json +56 -0
- package/skill/SKILL.md +230 -0
- package/skill/references/tools-md-template.md +57 -0
- package/skill/scripts/a2a-send.mjs +357 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "claw-crony",
|
|
3
|
+
"name": "Claw Crony",
|
|
4
|
+
"description": "OpenClaw A2A v0.3.0 gateway with Agent Card, JSON-RPC, REST, routing rules, transport fallback, and Hub matchmaking",
|
|
5
|
+
"version": "1.0.1",
|
|
6
|
+
"defaultConfig": {
|
|
7
|
+
"agentCard": {
|
|
8
|
+
"name": "OpenClaw A2A Gateway",
|
|
9
|
+
"description": "A2A bridge for OpenClaw agents",
|
|
10
|
+
"skills": [{ "id": "chat", "name": "chat", "description": "Chat bridge" }]
|
|
11
|
+
},
|
|
12
|
+
"hub": {
|
|
13
|
+
"url": "https://www.factormining.cn",
|
|
14
|
+
"enabled": true,
|
|
15
|
+
"registrationEnabled": true
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"configSchema": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"additionalProperties": false,
|
|
21
|
+
"properties": {
|
|
22
|
+
"agentCard": {
|
|
23
|
+
"type": "object",
|
|
24
|
+
"additionalProperties": false,
|
|
25
|
+
"properties": {
|
|
26
|
+
"name": { "type": "string" },
|
|
27
|
+
"description": { "type": "string" },
|
|
28
|
+
"url": { "type": "string" },
|
|
29
|
+
"skills": {
|
|
30
|
+
"type": "array",
|
|
31
|
+
"items": {
|
|
32
|
+
"oneOf": [
|
|
33
|
+
{ "type": "string" },
|
|
34
|
+
{
|
|
35
|
+
"type": "object",
|
|
36
|
+
"properties": {
|
|
37
|
+
"id": { "type": "string" },
|
|
38
|
+
"name": { "type": "string" },
|
|
39
|
+
"description": { "type": "string" }
|
|
40
|
+
},
|
|
41
|
+
"required": ["name"]
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"hub": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"additionalProperties": false,
|
|
51
|
+
"properties": {
|
|
52
|
+
"url": { "type": "string" },
|
|
53
|
+
"enabled": { "type": "boolean", "default": true },
|
|
54
|
+
"registrationEnabled": { "type": "boolean", "default": true }
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"registration": {
|
|
58
|
+
"type": "object",
|
|
59
|
+
"additionalProperties": false,
|
|
60
|
+
"properties": {
|
|
61
|
+
"username": { "type": "string" },
|
|
62
|
+
"email": { "type": "string" }
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"server": {
|
|
66
|
+
"type": "object",
|
|
67
|
+
"additionalProperties": false,
|
|
68
|
+
"properties": {
|
|
69
|
+
"host": { "type": "string", "default": "0.0.0.0" },
|
|
70
|
+
"port": { "type": "number", "default": 18800 }
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"storage": {
|
|
74
|
+
"type": "object",
|
|
75
|
+
"additionalProperties": false,
|
|
76
|
+
"properties": {
|
|
77
|
+
"tasksDir": { "type": "string", "default": "~/.openclaw/a2a-tasks" },
|
|
78
|
+
"taskTtlHours": {
|
|
79
|
+
"type": "number",
|
|
80
|
+
"default": 72,
|
|
81
|
+
"minimum": 1,
|
|
82
|
+
"description": "Hours before completed/failed/canceled tasks are automatically deleted (default 72h)"
|
|
83
|
+
},
|
|
84
|
+
"cleanupIntervalMinutes": {
|
|
85
|
+
"type": "number",
|
|
86
|
+
"default": 60,
|
|
87
|
+
"minimum": 1,
|
|
88
|
+
"description": "Minutes between automatic task cleanup runs (default 60min)"
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"peers": {
|
|
93
|
+
"type": "array",
|
|
94
|
+
"items": {
|
|
95
|
+
"type": "object",
|
|
96
|
+
"additionalProperties": false,
|
|
97
|
+
"properties": {
|
|
98
|
+
"name": { "type": "string" },
|
|
99
|
+
"agentCardUrl": { "type": "string" },
|
|
100
|
+
"auth": {
|
|
101
|
+
"type": "object",
|
|
102
|
+
"additionalProperties": false,
|
|
103
|
+
"properties": {
|
|
104
|
+
"type": {
|
|
105
|
+
"type": "string",
|
|
106
|
+
"enum": ["bearer", "apiKey"]
|
|
107
|
+
},
|
|
108
|
+
"token": { "type": "string" }
|
|
109
|
+
},
|
|
110
|
+
"required": ["type", "token"]
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"required": ["name", "agentCardUrl"]
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
"security": {
|
|
117
|
+
"type": "object",
|
|
118
|
+
"additionalProperties": false,
|
|
119
|
+
"properties": {
|
|
120
|
+
"inboundAuth": {
|
|
121
|
+
"type": "string",
|
|
122
|
+
"enum": ["none", "bearer"],
|
|
123
|
+
"default": "none"
|
|
124
|
+
},
|
|
125
|
+
"token": { "type": "string" },
|
|
126
|
+
"tokens": {
|
|
127
|
+
"type": "array",
|
|
128
|
+
"items": { "type": "string" },
|
|
129
|
+
"description": "Multiple tokens for zero-downtime rotation. Used alongside or instead of 'token'."
|
|
130
|
+
},
|
|
131
|
+
"allowedMimeTypes": {
|
|
132
|
+
"type": "array",
|
|
133
|
+
"items": { "type": "string" },
|
|
134
|
+
"description": "Allowed MIME type patterns for file transfer (e.g. \"image/*\", \"application/pdf\")"
|
|
135
|
+
},
|
|
136
|
+
"maxFileSizeBytes": {
|
|
137
|
+
"type": "number",
|
|
138
|
+
"default": 52428800,
|
|
139
|
+
"minimum": 0,
|
|
140
|
+
"description": "Max file size in bytes for URI-based files (default 50MB)"
|
|
141
|
+
},
|
|
142
|
+
"maxInlineFileSizeBytes": {
|
|
143
|
+
"type": "number",
|
|
144
|
+
"default": 10485760,
|
|
145
|
+
"minimum": 0,
|
|
146
|
+
"description": "Max file size in bytes for inline base64 files (default 10MB)"
|
|
147
|
+
},
|
|
148
|
+
"fileUriAllowlist": {
|
|
149
|
+
"type": "array",
|
|
150
|
+
"items": { "type": "string" },
|
|
151
|
+
"description": "URI hostname allowlist patterns (e.g. \"*.example.com\"). Empty allows all public hosts."
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
"routing": {
|
|
156
|
+
"type": "object",
|
|
157
|
+
"additionalProperties": false,
|
|
158
|
+
"properties": {
|
|
159
|
+
"defaultAgentId": {
|
|
160
|
+
"type": "string",
|
|
161
|
+
"default": "default"
|
|
162
|
+
},
|
|
163
|
+
"rules": {
|
|
164
|
+
"type": "array",
|
|
165
|
+
"description": "Rule-based routing: auto-select peer by message text regex, tags, or required skills"
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
"limits": {
|
|
170
|
+
"type": "object",
|
|
171
|
+
"additionalProperties": false,
|
|
172
|
+
"properties": {
|
|
173
|
+
"maxConcurrentTasks": {
|
|
174
|
+
"type": "number",
|
|
175
|
+
"default": 4,
|
|
176
|
+
"minimum": 1
|
|
177
|
+
},
|
|
178
|
+
"maxQueuedTasks": {
|
|
179
|
+
"type": "number",
|
|
180
|
+
"default": 100,
|
|
181
|
+
"minimum": 0
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
"observability": {
|
|
186
|
+
"type": "object",
|
|
187
|
+
"additionalProperties": false,
|
|
188
|
+
"properties": {
|
|
189
|
+
"structuredLogs": {
|
|
190
|
+
"type": "boolean",
|
|
191
|
+
"default": true
|
|
192
|
+
},
|
|
193
|
+
"exposeMetricsEndpoint": {
|
|
194
|
+
"type": "boolean",
|
|
195
|
+
"default": true
|
|
196
|
+
},
|
|
197
|
+
"metricsPath": {
|
|
198
|
+
"type": "string",
|
|
199
|
+
"default": "/a2a/metrics"
|
|
200
|
+
},
|
|
201
|
+
"metricsAuth": {
|
|
202
|
+
"type": "string",
|
|
203
|
+
"enum": ["none", "bearer"],
|
|
204
|
+
"default": "none",
|
|
205
|
+
"description": "Authentication for the metrics endpoint. When set to 'bearer', reuses security.token/tokens."
|
|
206
|
+
},
|
|
207
|
+
"auditLogPath": {
|
|
208
|
+
"type": "string",
|
|
209
|
+
"default": "~/.openclaw/a2a-audit.jsonl",
|
|
210
|
+
"description": "Path for the JSONL audit log file (separate from structured logs)."
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
"timeouts": {
|
|
215
|
+
"type": "object",
|
|
216
|
+
"additionalProperties": false,
|
|
217
|
+
"properties": {
|
|
218
|
+
"agentResponseTimeoutMs": {
|
|
219
|
+
"type": "number",
|
|
220
|
+
"default": 300000,
|
|
221
|
+
"minimum": 1000
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
"resilience": {
|
|
226
|
+
"type": "object",
|
|
227
|
+
"additionalProperties": false,
|
|
228
|
+
"properties": {
|
|
229
|
+
"healthCheck": {
|
|
230
|
+
"type": "object",
|
|
231
|
+
"additionalProperties": false,
|
|
232
|
+
"properties": {
|
|
233
|
+
"enabled": { "type": "boolean", "default": true },
|
|
234
|
+
"intervalMs": { "type": "number", "default": 30000, "minimum": 1000 },
|
|
235
|
+
"timeoutMs": { "type": "number", "default": 5000, "minimum": 500 }
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
"retry": {
|
|
239
|
+
"type": "object",
|
|
240
|
+
"additionalProperties": false,
|
|
241
|
+
"properties": {
|
|
242
|
+
"maxRetries": { "type": "number", "default": 3, "minimum": 0 },
|
|
243
|
+
"baseDelayMs": { "type": "number", "default": 1000, "minimum": 100 },
|
|
244
|
+
"maxDelayMs": { "type": "number", "default": 10000, "minimum": 100 }
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
"circuitBreaker": {
|
|
248
|
+
"type": "object",
|
|
249
|
+
"additionalProperties": false,
|
|
250
|
+
"properties": {
|
|
251
|
+
"failureThreshold": { "type": "number", "default": 5, "minimum": 1 },
|
|
252
|
+
"resetTimeoutMs": { "type": "number", "default": 30000, "minimum": 1000 }
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
"uiHints": {
|
|
260
|
+
"peers": {
|
|
261
|
+
"items": {
|
|
262
|
+
"auth": {
|
|
263
|
+
"token": { "sensitive": true }
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
"security": {
|
|
268
|
+
"token": { "sensitive": true },
|
|
269
|
+
"tokens": { "items": { "sensitive": true } }
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@clawcrony/claw-crony",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "OpenClaw A2A gateway plugin implementing the A2A v0.3.0 protocol surface",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"openclaw.plugin.json",
|
|
17
|
+
"skill"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc",
|
|
21
|
+
"test": "node --import tsx --test tests/*.test.ts"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"openclaw",
|
|
25
|
+
"a2a",
|
|
26
|
+
"agent-to-agent",
|
|
27
|
+
"gateway",
|
|
28
|
+
"plugin"
|
|
29
|
+
],
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/express": "^5.0.6",
|
|
33
|
+
"@types/node": "^22.0.0",
|
|
34
|
+
"@types/supertest": "^2.0.16",
|
|
35
|
+
"@types/uuid": "^10.0.0",
|
|
36
|
+
"openclaw": "^2026.3.2",
|
|
37
|
+
"supertest": "^7.1.4",
|
|
38
|
+
"tsx": "^4.19.0",
|
|
39
|
+
"typescript": "^5.9.3"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@a2a-js/sdk": "^0.3.0",
|
|
43
|
+
"@bufbuild/protobuf": "^2.11.0",
|
|
44
|
+
"@grpc/grpc-js": "^1.14.3",
|
|
45
|
+
"express": "^4.21.2",
|
|
46
|
+
"uuid": "^9.0.1"
|
|
47
|
+
},
|
|
48
|
+
"openclaw": {
|
|
49
|
+
"extensions": [
|
|
50
|
+
"./index.ts"
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
"engines": {
|
|
54
|
+
"node": ">=22"
|
|
55
|
+
}
|
|
56
|
+
}
|
package/skill/SKILL.md
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: a2a-setup
|
|
3
|
+
description: "Install and configure the OpenClaw A2A Gateway plugin for cross-server agent communication. Use when: (1) setting up A2A between two or more OpenClaw instances, (2) user says 'configure A2A', 'set up A2A gateway', 'connect two OpenClaw servers', 'agent-to-agent communication', (3) adding a new A2A peer to an existing setup. Covers: plugin installation, Agent Card configuration, security tokens, peer registration, network setup (Tailscale/LAN), TOOLS.md template for agent awareness, and end-to-end verification."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# A2A Gateway Setup
|
|
7
|
+
|
|
8
|
+
Configure the OpenClaw A2A Gateway plugin for cross-server agent-to-agent communication using the A2A v0.3.0 protocol.
|
|
9
|
+
|
|
10
|
+
## Prerequisites
|
|
11
|
+
|
|
12
|
+
- OpenClaw ≥ 2026.3.0 installed and running on each server
|
|
13
|
+
- Network connectivity between servers (Tailscale recommended, LAN or public IP also work)
|
|
14
|
+
- Node.js ≥ 22
|
|
15
|
+
|
|
16
|
+
## Step 1: Install the Plugin
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
mkdir -p <WORKSPACE>/plugins
|
|
20
|
+
cd <WORKSPACE>/plugins
|
|
21
|
+
git clone https://github.com/win4r/openclaw-a2a-gateway.git a2a-gateway
|
|
22
|
+
cd a2a-gateway
|
|
23
|
+
npm install --production
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Replace `<WORKSPACE>` with the agent workspace path. Find it with:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
openclaw config get agents.defaults.workspace
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Step 2: Register Plugin in OpenClaw
|
|
33
|
+
|
|
34
|
+
Get current allowed plugins first to avoid overwriting:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
openclaw config get plugins.allow
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Then add `a2a-gateway` to the existing array (do NOT drop existing plugin ids):
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Example only — include your existing plugins too
|
|
44
|
+
openclaw config set plugins.allow '["<existing...>", "a2a-gateway"]'
|
|
45
|
+
openclaw config set plugins.load.paths '["<ABSOLUTE_PATH>/plugins/a2a-gateway"]'
|
|
46
|
+
openclaw config set plugins.entries.a2a-gateway.enabled true
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Critical:** Use the absolute path in `plugins.load.paths`. Relative paths will fail.
|
|
50
|
+
|
|
51
|
+
## Step 3: Configure Agent Card
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
openclaw config set plugins.entries.a2a-gateway.config.agentCard.name '<AGENT_NAME>'
|
|
55
|
+
openclaw config set plugins.entries.a2a-gateway.config.agentCard.description '<DESCRIPTION>'
|
|
56
|
+
openclaw config set plugins.entries.a2a-gateway.config.agentCard.url 'http://<REACHABLE_IP>:18800/a2a/jsonrpc'
|
|
57
|
+
openclaw config set plugins.entries.a2a-gateway.config.agentCard.skills '[{"id":"chat","name":"chat","description":"Bridge chat/messages to OpenClaw agents"}]'
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### URL field rules
|
|
61
|
+
|
|
62
|
+
| Field | Points to | Example |
|
|
63
|
+
|-------|-----------|---------|
|
|
64
|
+
| `agentCard.url` | JSON-RPC endpoint (default) | `http://100.x.x.x:18800/a2a/jsonrpc` |
|
|
65
|
+
| `peers[].agentCardUrl` | Agent Card discovery (preferred) | `http://100.x.x.x:18800/.well-known/agent-card.json` |
|
|
66
|
+
|
|
67
|
+
**Do NOT confuse these two.** `agentCard.url` tells peers where to send messages. `agentCardUrl` tells you where to discover the peer.
|
|
68
|
+
|
|
69
|
+
Note: this plugin also serves the legacy alias `/.well-known/agent.json`, but the official SDK default is `/.well-known/agent-card.json`.
|
|
70
|
+
|
|
71
|
+
## Step 4: Configure Server
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
openclaw config set plugins.entries.a2a-gateway.config.server.host '0.0.0.0'
|
|
75
|
+
openclaw config set plugins.entries.a2a-gateway.config.server.port 18800
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Step 5: Configure Security
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
TOKEN=$(openssl rand -hex 24)
|
|
82
|
+
echo "Save this token: $TOKEN"
|
|
83
|
+
|
|
84
|
+
openclaw config set plugins.entries.a2a-gateway.config.security.inboundAuth 'bearer'
|
|
85
|
+
openclaw config set plugins.entries.a2a-gateway.config.security.token "$TOKEN"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Share this token with peers who need to send you messages.
|
|
89
|
+
|
|
90
|
+
## Step 6: Configure Routing
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
openclaw config set plugins.entries.a2a-gateway.config.routing.defaultAgentId 'main'
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Step 7: Add Peers
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
openclaw config set plugins.entries.a2a-gateway.config.peers '[
|
|
100
|
+
{
|
|
101
|
+
"name": "<PEER_NAME>",
|
|
102
|
+
"agentCardUrl": "http://<PEER_IP>:18800/.well-known/agent-card.json",
|
|
103
|
+
"auth": {
|
|
104
|
+
"type": "bearer",
|
|
105
|
+
"token": "<PEER_INBOUND_TOKEN>"
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
]'
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
For multiple peers, include all in one JSON array.
|
|
112
|
+
|
|
113
|
+
## Step 8: Restart and Verify
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
openclaw gateway restart
|
|
117
|
+
|
|
118
|
+
# Verify Agent Card
|
|
119
|
+
curl -s http://localhost:18800/.well-known/agent-card.json | python3 -m json.tool
|
|
120
|
+
|
|
121
|
+
# Verify peer connectivity
|
|
122
|
+
curl -s http://<PEER_IP>:18800/.well-known/agent-card.json | python3 -m json.tool
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Step 9: Configure TOOLS.md
|
|
126
|
+
|
|
127
|
+
**This step is critical.** Without it, the agent won't know how to use A2A.
|
|
128
|
+
|
|
129
|
+
Read `references/tools-md-template.md` and append the A2A section to the agent's `TOOLS.md`, replacing placeholders with actual peer info.
|
|
130
|
+
|
|
131
|
+
For outbound messaging, use the SDK script (`scripts/a2a-send.mjs`).
|
|
132
|
+
|
|
133
|
+
To use the SDK script, ensure `@a2a-js/sdk` is installed in the plugin directory:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
cd <WORKSPACE>/plugins/a2a-gateway && npm ls @a2a-js/sdk
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Step 10: End-to-End Test
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
node <WORKSPACE>/plugins/a2a-gateway/skill/scripts/a2a-send.mjs \
|
|
143
|
+
--peer-url http://<PEER_IP>:18800 \
|
|
144
|
+
--token <PEER_TOKEN> \
|
|
145
|
+
--message "Hello, what is your name?"
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
The script uses `@a2a-js/sdk` ClientFactory to auto-discover the Agent Card, handle authentication, and print the peer agent's response.
|
|
149
|
+
|
|
150
|
+
### Async task mode (recommended for long-running prompts)
|
|
151
|
+
|
|
152
|
+
For prompts that may take longer than a typical request timeout (e.g., multi-round discussions, long summaries), use non-blocking mode + polling:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
node <WORKSPACE>/plugins/a2a-gateway/skill/scripts/a2a-send.mjs \
|
|
156
|
+
--peer-url http://<PEER_IP>:18800 \
|
|
157
|
+
--token <PEER_TOKEN> \
|
|
158
|
+
--non-blocking \
|
|
159
|
+
--wait \
|
|
160
|
+
--timeout-ms 600000 \
|
|
161
|
+
--poll-ms 1000 \
|
|
162
|
+
--message "Discuss A2A advantages in 3 rounds and provide final conclusion"
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
This sends `configuration.blocking=false` and then polls `tasks/get` until the task reaches a terminal state.
|
|
166
|
+
|
|
167
|
+
### Server-side timeout configuration (OpenClaw dispatch)
|
|
168
|
+
|
|
169
|
+
If you still see `Request accepted (no agent dispatch available)`, the underlying OpenClaw agent run may be timing out. Increase:
|
|
170
|
+
|
|
171
|
+
- `plugins.entries.a2a-gateway.config.timeouts.agentResponseTimeoutMs` (default: 300000)
|
|
172
|
+
|
|
173
|
+
### Optional: Route to a specific OpenClaw agentId (OpenClaw extension)
|
|
174
|
+
|
|
175
|
+
By default, the peer will route inbound A2A messages to `routing.defaultAgentId`.
|
|
176
|
+
|
|
177
|
+
To route a single request to a specific agentId (e.g., `coder`) on the peer, pass `--agent-id`:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
node <WORKSPACE>/plugins/a2a-gateway/skill/scripts/a2a-send.mjs \
|
|
181
|
+
--peer-url http://<PEER_IP>:18800 \
|
|
182
|
+
--token <PEER_TOKEN> \
|
|
183
|
+
--agent-id coder \
|
|
184
|
+
--message "Run tests and summarize failures"
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Note: this uses a non-standard `message.agentId` field understood by the OpenClaw A2A Gateway plugin. It is most reliable over JSON-RPC/REST. gRPC transport may drop unknown Message fields.
|
|
188
|
+
|
|
189
|
+
## Network: Tailscale Setup (if needed)
|
|
190
|
+
|
|
191
|
+
When servers are on different networks, use Tailscale:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
curl -fsSL https://tailscale.com/install.sh | sh
|
|
195
|
+
sudo tailscale up
|
|
196
|
+
# Authenticate via the printed URL (use same account on all servers)
|
|
197
|
+
tailscale ip -4 # Get the 100.x.x.x IP
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Use Tailscale IPs in all A2A configuration. Verify with:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
ping <OTHER_SERVER_TAILSCALE_IP>
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Mutual Peering Checklist
|
|
207
|
+
|
|
208
|
+
For two-way communication, repeat Steps 1-9 on BOTH servers:
|
|
209
|
+
|
|
210
|
+
- [ ] Server A: plugin installed, Agent Card configured, token generated
|
|
211
|
+
- [ ] Server B: plugin installed, Agent Card configured, token generated
|
|
212
|
+
- [ ] Server A: has Server B in peers (with B's token)
|
|
213
|
+
- [ ] Server B: has Server A in peers (with A's token)
|
|
214
|
+
- [ ] Server A: TOOLS.md updated with Server B peer info
|
|
215
|
+
- [ ] Server B: TOOLS.md updated with Server A peer info
|
|
216
|
+
- [ ] Both: `openclaw gateway restart` done
|
|
217
|
+
- [ ] Both: Agent Cards accessible (`curl /.well-known/agent-card.json`)
|
|
218
|
+
- [ ] Test: A → B message/send works
|
|
219
|
+
- [ ] Test: B → A message/send works
|
|
220
|
+
|
|
221
|
+
## Troubleshooting
|
|
222
|
+
|
|
223
|
+
| Symptom | Cause | Fix |
|
|
224
|
+
|---------|-------|-----|
|
|
225
|
+
| "no agent dispatch available" | (1) No AI provider configured, or (2) OpenClaw agent dispatch timed out | Check `openclaw config get auth.profiles`; for long prompts use async mode (`--non-blocking --wait`) or increase `config.timeouts.agentResponseTimeoutMs` |
|
|
226
|
+
| "plugin not found: a2a-gateway" | Load path missing or wrong | Verify `plugins.load.paths` uses absolute path |
|
|
227
|
+
| Agent Card 404 | Plugin not loaded | Check `plugins.allow` includes `a2a-gateway` |
|
|
228
|
+
| Port 18800 connection refused | Gateway not restarted | Run `openclaw gateway restart` |
|
|
229
|
+
| Peer auth fails | Token mismatch | Verify peer config token matches target's `security.token` |
|
|
230
|
+
| Agent doesn't know about A2A | TOOLS.md not configured | Add A2A section from the template (Step 9) |
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# TOOLS.md A2A Section Template
|
|
2
|
+
|
|
3
|
+
Append this section to the agent's `TOOLS.md` file, replacing all `<PLACEHOLDERS>` with actual values.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
```markdown
|
|
8
|
+
## A2A Gateway (Agent-to-Agent Communication)
|
|
9
|
+
|
|
10
|
+
You have an A2A Gateway plugin running on port 18800. You can communicate with peer agents on other servers.
|
|
11
|
+
|
|
12
|
+
### Peers
|
|
13
|
+
|
|
14
|
+
| Peer | IP | Auth Token |
|
|
15
|
+
|------|-----|------------|
|
|
16
|
+
| <PEER_NAME> | <PEER_IP> | <PEER_TOKEN> |
|
|
17
|
+
|
|
18
|
+
### How to send a message to a peer
|
|
19
|
+
|
|
20
|
+
When the user says "通过 A2A 让 <PEER_NAME> 做 xxx" / "Send to <PEER_NAME>: xxx" / "Ask <PEER_NAME> to ..." or similar, use the exec tool to run:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
node <WORKSPACE>/plugins/a2a-gateway/skill/scripts/a2a-send.mjs \
|
|
24
|
+
--peer-url http://<PEER_IP>:18800 \
|
|
25
|
+
--token <PEER_TOKEN> \
|
|
26
|
+
--message "YOUR MESSAGE HERE"
|
|
27
|
+
|
|
28
|
+
# Optional (OpenClaw extension): route to a specific peer OpenClaw agentId
|
|
29
|
+
# --agent-id coder
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The script uses `@a2a-js/sdk` ClientFactory to:
|
|
33
|
+
- Auto-discover the peer's Agent Card
|
|
34
|
+
- Handle bearer token authentication
|
|
35
|
+
- Select the best transport (JSON-RPC by default; REST or GRPC if preferred/available)
|
|
36
|
+
- Print the peer agent's response text directly
|
|
37
|
+
|
|
38
|
+
### Notes
|
|
39
|
+
|
|
40
|
+
- For long-running prompts (multi-round discussions, long summaries), use async task mode:
|
|
41
|
+
- add: `--non-blocking --wait --timeout-ms 600000 --poll-ms 1000`
|
|
42
|
+
- If the peer returns an error, check the token and network connectivity
|
|
43
|
+
- The script handles messageId generation and response parsing automatically
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Placeholder Reference
|
|
49
|
+
|
|
50
|
+
| Placeholder | Description | Example |
|
|
51
|
+
|-------------|-------------|---------|
|
|
52
|
+
| `<PEER_NAME>` | Display name of the peer agent | `Server-A` |
|
|
53
|
+
| `<PEER_IP>` | IP address reachable from this server | `100.76.43.74` |
|
|
54
|
+
| `<PEER_TOKEN>` | The peer's inbound security token | `9489c2c7ce10...` |
|
|
55
|
+
| `<WORKSPACE>` | Agent workspace absolute path | `/home/ubuntu/.openclaw/workspace` |
|
|
56
|
+
|
|
57
|
+
For multiple peers, add one row per peer to the table.
|