@agentlayer.tech/wallet 0.1.100 → 0.1.102

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.
Files changed (85) hide show
  1. package/.openclaw/extensions/agent-wallet/dist/index.js +46 -1
  2. package/.openclaw/extensions/agent-wallet/index.ts +46 -1
  3. package/.openclaw/extensions/agent-wallet/openclaw.plugin.json +1 -1
  4. package/.openclaw/extensions/agent-wallet/package.json +1 -1
  5. package/README.md +18 -0
  6. package/VERSION +1 -1
  7. package/agent-wallet/agent_wallet/__init__.py +1 -1
  8. package/agent-wallet/agent_wallet/connector_cli.py +198 -0
  9. package/agent-wallet/agent_wallet/connectors/__init__.py +28 -0
  10. package/agent-wallet/agent_wallet/connectors/catalog.py +68 -0
  11. package/agent-wallet/agent_wallet/connectors/client.py +308 -0
  12. package/agent-wallet/agent_wallet/connectors/intent_policy.py +243 -0
  13. package/agent-wallet/agent_wallet/connectors/manifest.py +192 -0
  14. package/agent-wallet/agent_wallet/connectors/registry.py +341 -0
  15. package/agent-wallet/agent_wallet/openclaw_adapter.py +56 -5
  16. package/agent-wallet/agent_wallet/providers/solana_rpc.py +1 -1
  17. package/agent-wallet/agent_wallet/providers/wdk_btc_local.py +7 -4
  18. package/agent-wallet/agent_wallet/providers/wdk_evm_local.py +7 -2
  19. package/agent-wallet/agent_wallet/wallet_layer/solana.py +1 -1
  20. package/agent-wallet/openclaw.plugin.json +1 -1
  21. package/agent-wallet/pyproject.toml +4 -2
  22. package/agent-wallet/scripts/build_release_bundle.py +1 -0
  23. package/agent-wallet/scripts/install_agent_wallet.py +1 -1
  24. package/bin/openclaw-agent-wallet.mjs +38 -0
  25. package/claude-code/plugins/agent-wallet/.claude-plugin/plugin.json +1 -1
  26. package/codex/plugins/agent-wallet/.codex-plugin/plugin.json +1 -1
  27. package/codex/plugins/agent-wallet/server.py +17 -5
  28. package/connectors/AGENTS.md +37 -0
  29. package/connectors/DEVELOPER_GUIDE.md +131 -0
  30. package/connectors/README.md +139 -0
  31. package/connectors/READ_ONLY_BETA.md +54 -0
  32. package/connectors/RELEASING.md +48 -0
  33. package/connectors/conformance/README.md +31 -0
  34. package/connectors/conformance/package.json +54 -0
  35. package/connectors/conformance/scripts/sync-license.mjs +3 -0
  36. package/connectors/conformance/scripts/sync-spec.mjs +16 -0
  37. package/connectors/conformance/src/cli.ts +43 -0
  38. package/connectors/conformance/src/index.ts +7 -0
  39. package/connectors/conformance/src/runner.ts +314 -0
  40. package/connectors/conformance/src/types.ts +27 -0
  41. package/connectors/conformance/test/fixtures/invalid-response-identity.json +14 -0
  42. package/connectors/conformance/test/fixtures/missing-tool-fixture.json +4 -0
  43. package/connectors/conformance/test/runner.test.mjs +151 -0
  44. package/connectors/conformance/tsconfig.json +17 -0
  45. package/connectors/examples/reference-crypto-data/Dockerfile +21 -0
  46. package/connectors/examples/reference-crypto-data/README.md +51 -0
  47. package/connectors/examples/reference-crypto-data/conformance.json +11 -0
  48. package/connectors/examples/reference-crypto-data/connector.json +95 -0
  49. package/connectors/examples/reference-crypto-data/package.json +21 -0
  50. package/connectors/examples/reference-crypto-data/railway.toml +9 -0
  51. package/connectors/examples/reference-crypto-data/src/connector.ts +137 -0
  52. package/connectors/examples/reference-crypto-data/src/server.ts +13 -0
  53. package/connectors/examples/reference-crypto-data/test/connector.test.mjs +97 -0
  54. package/connectors/examples/reference-crypto-data/tsconfig.json +17 -0
  55. package/connectors/package-lock.json +561 -0
  56. package/connectors/package.json +19 -0
  57. package/connectors/scripts/smoke-packed-packages.mjs +121 -0
  58. package/connectors/sdk-typescript/README.md +47 -0
  59. package/connectors/sdk-typescript/package.json +49 -0
  60. package/connectors/sdk-typescript/scripts/sync-license.mjs +3 -0
  61. package/connectors/sdk-typescript/src/connector.ts +204 -0
  62. package/connectors/sdk-typescript/src/errors.ts +11 -0
  63. package/connectors/sdk-typescript/src/http.ts +116 -0
  64. package/connectors/sdk-typescript/src/index.ts +26 -0
  65. package/connectors/sdk-typescript/src/types.ts +101 -0
  66. package/connectors/sdk-typescript/test/sdk.test.mjs +181 -0
  67. package/connectors/sdk-typescript/tsconfig.json +21 -0
  68. package/connectors/spec/connector-manifest.schema.json +340 -0
  69. package/connectors/spec/connector-protocol.md +159 -0
  70. package/connectors/spec/transaction-intent.schema.json +281 -0
  71. package/connectors/templates/read-only/.env.example +1 -0
  72. package/connectors/templates/read-only/Dockerfile +11 -0
  73. package/connectors/templates/read-only/README.md +33 -0
  74. package/connectors/templates/read-only/conformance.json +11 -0
  75. package/connectors/templates/read-only/connector.json +64 -0
  76. package/connectors/templates/read-only/package.json +21 -0
  77. package/connectors/templates/read-only/railway.toml +9 -0
  78. package/connectors/templates/read-only/src/connector.ts +61 -0
  79. package/connectors/templates/read-only/src/server.ts +14 -0
  80. package/connectors/templates/read-only/test/connector.test.mjs +62 -0
  81. package/connectors/templates/read-only/tsconfig.json +17 -0
  82. package/hermes/plugins/agent_wallet/plugin.yaml +1 -1
  83. package/package.json +2 -1
  84. package/wdk-btc-wallet/package.json +1 -1
  85. package/wdk-evm-wallet/package.json +1 -1
@@ -0,0 +1,181 @@
1
+ import assert from "node:assert/strict";
2
+ import { Readable } from "node:stream";
3
+ import test from "node:test";
4
+
5
+ import {
6
+ ConnectorSdkError,
7
+ createConnectorHttpHandler,
8
+ defineReadOnlyConnector,
9
+ } from "../dist/index.js";
10
+
11
+ function manifest(overrides = {}) {
12
+ return {
13
+ schema_version: 1,
14
+ id: "com.example.markets",
15
+ name: "Example Markets",
16
+ version: "1.0.0",
17
+ artifact_digest: `sha256:${"a".repeat(64)}`,
18
+ publisher: { id: "example", name: "Example" },
19
+ agentlayer: { protocol_version: 1, runtime_range: ">=0.1.101" },
20
+ trust: "community_read_only",
21
+ transport: { type: "https", url: "https://connector.example.com/v1" },
22
+ permissions: {
23
+ wallet_address: false,
24
+ transaction_intents: false,
25
+ network_hosts: ["api.example.com"],
26
+ },
27
+ tools: [
28
+ {
29
+ name: "get_markets",
30
+ description: "Get markets.",
31
+ read_only: true,
32
+ risk_level: "low",
33
+ input_schema: {
34
+ type: "object",
35
+ properties: { limit: { type: "integer", minimum: 1, maximum: 10 } },
36
+ required: ["limit"],
37
+ additionalProperties: false,
38
+ },
39
+ output_schema: {
40
+ type: "object",
41
+ properties: { markets: { type: "array", items: { type: "string" } } },
42
+ required: ["markets"],
43
+ additionalProperties: false,
44
+ },
45
+ },
46
+ ],
47
+ ...overrides,
48
+ };
49
+ }
50
+
51
+ function request(overrides = {}) {
52
+ return {
53
+ protocol_version: 1,
54
+ request_id: "request-123",
55
+ connector: {
56
+ id: "com.example.markets",
57
+ version: "1.0.0",
58
+ artifact_digest: `sha256:${"a".repeat(64)}`,
59
+ },
60
+ tool: "get_markets",
61
+ arguments: { limit: 2 },
62
+ context: { chain: "evm", network: "base" },
63
+ ...overrides,
64
+ };
65
+ }
66
+
67
+ test("builds a short-lived identity-bound read result", async () => {
68
+ const connector = defineReadOnlyConnector({
69
+ manifest: manifest(),
70
+ handlers: { get_markets: ({ limit }) => ({ markets: Array(limit).fill("USDC") }) },
71
+ });
72
+ const result = await connector.invoke(request());
73
+ assert.equal(result.kind, "read_result");
74
+ assert.deepEqual(result.result, { markets: ["USDC", "USDC"] });
75
+ assert.equal(result.connector.artifact_digest, `sha256:${"a".repeat(64)}`);
76
+ assert.ok(Date.parse(result.expires_at) > Date.now());
77
+ });
78
+
79
+ test("rejects identity mismatch and invalid arguments", async () => {
80
+ const connector = defineReadOnlyConnector({
81
+ manifest: manifest(),
82
+ handlers: { get_markets: () => ({ markets: [] }) },
83
+ });
84
+ await assert.rejects(
85
+ connector.invoke(request({ connector: { id: "com.attacker", version: "1.0.0" } })),
86
+ (error) => error instanceof ConnectorSdkError && error.code === "identity_mismatch"
87
+ );
88
+ await assert.rejects(
89
+ connector.invoke(request({ arguments: { limit: 100 } })),
90
+ (error) => error instanceof ConnectorSdkError && error.code === "invalid_arguments"
91
+ );
92
+ });
93
+
94
+ test("rejects handler output that violates the public schema", async () => {
95
+ const connector = defineReadOnlyConnector({
96
+ manifest: manifest(),
97
+ handlers: { get_markets: () => ({ markets: "not-an-array" }) },
98
+ });
99
+ await assert.rejects(
100
+ connector.invoke(request()),
101
+ (error) => error instanceof ConnectorSdkError && error.code === "invalid_result"
102
+ );
103
+ });
104
+
105
+ test("rejects write envelopes embedded in read-only output", async () => {
106
+ const permissiveManifest = manifest();
107
+ permissiveManifest.tools[0].output_schema = { type: "object" };
108
+ const connector = defineReadOnlyConnector({
109
+ manifest: permissiveManifest,
110
+ handlers: {
111
+ get_markets: () => ({ data: { transaction_intent: { to: "0xdead" } } }),
112
+ },
113
+ });
114
+ await assert.rejects(
115
+ connector.invoke(request()),
116
+ (error) => error instanceof ConnectorSdkError && error.code === "write_not_supported"
117
+ );
118
+ });
119
+
120
+ test("rejects a response larger than the wallet protocol limit", async () => {
121
+ const permissiveManifest = manifest();
122
+ permissiveManifest.tools[0].output_schema = { type: "object" };
123
+ const connector = defineReadOnlyConnector({
124
+ manifest: permissiveManifest,
125
+ handlers: { get_markets: () => ({ data: "x".repeat(1024 * 1024) }) },
126
+ });
127
+ await assert.rejects(
128
+ connector.invoke(request()),
129
+ (error) => error instanceof ConnectorSdkError && error.code === "response_too_large"
130
+ );
131
+ });
132
+
133
+ test("refuses write-capable manifests and undeclared handlers", () => {
134
+ assert.throws(
135
+ () =>
136
+ defineReadOnlyConnector({
137
+ manifest: manifest({ trust: "verified_write" }),
138
+ handlers: { get_markets: () => ({ markets: [] }) },
139
+ }),
140
+ (error) => error instanceof ConnectorSdkError && error.code === "write_not_supported"
141
+ );
142
+ assert.throws(
143
+ () =>
144
+ defineReadOnlyConnector({
145
+ manifest: manifest(),
146
+ handlers: {
147
+ get_markets: () => ({ markets: [] }),
148
+ hidden_write: () => ({ transaction: "0x" }),
149
+ },
150
+ }),
151
+ (error) => error instanceof ConnectorSdkError && error.code === "unknown_handler"
152
+ );
153
+ });
154
+
155
+ test("serves only health and JSON invoke routes", async () => {
156
+ const connector = defineReadOnlyConnector({
157
+ manifest: manifest(),
158
+ handlers: { get_markets: () => ({ markets: ["USDC"] }) },
159
+ });
160
+ const handler = createConnectorHttpHandler(connector);
161
+ const body = JSON.stringify(request());
162
+ const incoming = Object.assign(Readable.from([body]), {
163
+ method: "POST",
164
+ url: "/invoke",
165
+ headers: { "content-type": "application/json", "content-length": String(Buffer.byteLength(body)) },
166
+ });
167
+ const captured = { statusCode: 0, headers: {}, body: "" };
168
+ const response = {
169
+ writeHead(statusCode, headers) {
170
+ captured.statusCode = statusCode;
171
+ captured.headers = headers;
172
+ },
173
+ end(value) {
174
+ captured.body = String(value ?? "");
175
+ },
176
+ };
177
+ await handler(incoming, response);
178
+ assert.equal(captured.statusCode, 200);
179
+ assert.equal(JSON.parse(captured.body).kind, "read_result");
180
+ assert.equal(captured.headers["cache-control"], "no-store");
181
+ });
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2023",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "rootDir": "src",
7
+ "outDir": "dist",
8
+ "declaration": true,
9
+ "declarationMap": true,
10
+ "sourceMap": true,
11
+ "strict": true,
12
+ "noUncheckedIndexedAccess": true,
13
+ "exactOptionalPropertyTypes": true,
14
+ "esModuleInterop": true,
15
+ "allowSyntheticDefaultImports": true,
16
+ "verbatimModuleSyntax": true,
17
+ "types": ["node"],
18
+ "skipLibCheck": true
19
+ },
20
+ "include": ["src/**/*.ts"]
21
+ }
@@ -0,0 +1,340 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://agent-layer.tech/schemas/connectors/v1/connector-manifest.schema.json",
4
+ "title": "AgentLayer Connector Manifest v1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "schema_version",
9
+ "id",
10
+ "name",
11
+ "version",
12
+ "publisher",
13
+ "agentlayer",
14
+ "trust",
15
+ "transport",
16
+ "permissions",
17
+ "tools"
18
+ ],
19
+ "properties": {
20
+ "schema_version": {
21
+ "const": 1
22
+ },
23
+ "id": {
24
+ "type": "string",
25
+ "pattern": "^[a-z0-9]+(?:[._-][a-z0-9]+)+$",
26
+ "maxLength": 128
27
+ },
28
+ "name": {
29
+ "type": "string",
30
+ "minLength": 1,
31
+ "maxLength": 80
32
+ },
33
+ "description": {
34
+ "type": "string",
35
+ "maxLength": 500
36
+ },
37
+ "version": {
38
+ "type": "string",
39
+ "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$",
40
+ "maxLength": 64
41
+ },
42
+ "artifact_digest": {
43
+ "type": "string",
44
+ "pattern": "^sha256:[0-9a-f]{64}$"
45
+ },
46
+ "publisher": {
47
+ "type": "object",
48
+ "additionalProperties": false,
49
+ "required": ["id", "name"],
50
+ "properties": {
51
+ "id": {
52
+ "type": "string",
53
+ "pattern": "^[a-z0-9][a-z0-9_-]{1,63}$"
54
+ },
55
+ "name": {
56
+ "type": "string",
57
+ "minLength": 1,
58
+ "maxLength": 80
59
+ },
60
+ "url": {
61
+ "type": "string",
62
+ "format": "uri",
63
+ "pattern": "^https://"
64
+ }
65
+ }
66
+ },
67
+ "agentlayer": {
68
+ "type": "object",
69
+ "additionalProperties": false,
70
+ "required": ["protocol_version", "runtime_range"],
71
+ "properties": {
72
+ "protocol_version": {
73
+ "const": 1
74
+ },
75
+ "runtime_range": {
76
+ "type": "string",
77
+ "minLength": 1,
78
+ "maxLength": 100
79
+ }
80
+ }
81
+ },
82
+ "trust": {
83
+ "type": "string",
84
+ "enum": [
85
+ "community_read_only",
86
+ "verified_read_only",
87
+ "verified_write",
88
+ "local_development"
89
+ ]
90
+ },
91
+ "transport": {
92
+ "type": "object",
93
+ "additionalProperties": false,
94
+ "required": ["type", "url"],
95
+ "properties": {
96
+ "type": {
97
+ "const": "https"
98
+ },
99
+ "url": {
100
+ "type": "string",
101
+ "format": "uri",
102
+ "pattern": "^https://",
103
+ "maxLength": 2048
104
+ },
105
+ "timeout_ms": {
106
+ "type": "integer",
107
+ "minimum": 100,
108
+ "maximum": 30000,
109
+ "default": 10000
110
+ }
111
+ }
112
+ },
113
+ "permissions": {
114
+ "type": "object",
115
+ "additionalProperties": false,
116
+ "required": ["wallet_address", "transaction_intents", "network_hosts"],
117
+ "properties": {
118
+ "wallet_address": {
119
+ "type": "boolean"
120
+ },
121
+ "balance_read": {
122
+ "type": "boolean",
123
+ "default": false
124
+ },
125
+ "transaction_intents": {
126
+ "type": "boolean"
127
+ },
128
+ "x402_discovery": {
129
+ "type": "boolean",
130
+ "default": false
131
+ },
132
+ "network_hosts": {
133
+ "type": "array",
134
+ "maxItems": 32,
135
+ "uniqueItems": true,
136
+ "items": {
137
+ "type": "string",
138
+ "pattern": "^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z]{2,63}$"
139
+ }
140
+ }
141
+ }
142
+ },
143
+ "chains": {
144
+ "type": "array",
145
+ "maxItems": 32,
146
+ "items": {
147
+ "$ref": "#/$defs/chainPolicy"
148
+ }
149
+ },
150
+ "tools": {
151
+ "type": "array",
152
+ "minItems": 1,
153
+ "maxItems": 64,
154
+ "items": {
155
+ "$ref": "#/$defs/tool"
156
+ }
157
+ }
158
+ },
159
+ "$defs": {
160
+ "jsonSchema": {
161
+ "type": "object"
162
+ },
163
+ "tool": {
164
+ "type": "object",
165
+ "additionalProperties": false,
166
+ "required": ["name", "description", "read_only", "risk_level", "input_schema", "output_schema"],
167
+ "properties": {
168
+ "name": {
169
+ "type": "string",
170
+ "pattern": "^[a-z][a-z0-9_]{1,63}$"
171
+ },
172
+ "description": {
173
+ "type": "string",
174
+ "minLength": 1,
175
+ "maxLength": 500
176
+ },
177
+ "read_only": {
178
+ "type": "boolean"
179
+ },
180
+ "risk_level": {
181
+ "type": "string",
182
+ "enum": ["low", "medium", "high"]
183
+ },
184
+ "input_schema": {
185
+ "$ref": "#/$defs/jsonSchema"
186
+ },
187
+ "output_schema": {
188
+ "$ref": "#/$defs/jsonSchema"
189
+ }
190
+ }
191
+ },
192
+ "chainPolicy": {
193
+ "oneOf": [
194
+ {
195
+ "$ref": "#/$defs/evmPolicy"
196
+ },
197
+ {
198
+ "$ref": "#/$defs/solanaPolicy"
199
+ }
200
+ ]
201
+ },
202
+ "evmPolicy": {
203
+ "type": "object",
204
+ "additionalProperties": false,
205
+ "required": ["chain", "chain_ids", "contracts"],
206
+ "properties": {
207
+ "chain": {
208
+ "const": "evm"
209
+ },
210
+ "chain_ids": {
211
+ "type": "array",
212
+ "minItems": 1,
213
+ "uniqueItems": true,
214
+ "items": {
215
+ "type": "integer",
216
+ "minimum": 1
217
+ }
218
+ },
219
+ "contracts": {
220
+ "type": "array",
221
+ "minItems": 1,
222
+ "maxItems": 128,
223
+ "items": {
224
+ "type": "object",
225
+ "additionalProperties": false,
226
+ "required": ["chain_id", "address", "selectors"],
227
+ "properties": {
228
+ "chain_id": {
229
+ "type": "integer",
230
+ "minimum": 1
231
+ },
232
+ "address": {
233
+ "type": "string",
234
+ "pattern": "^0x[0-9a-fA-F]{40}$"
235
+ },
236
+ "selectors": {
237
+ "type": "array",
238
+ "minItems": 1,
239
+ "uniqueItems": true,
240
+ "items": {
241
+ "type": "string",
242
+ "pattern": "^0x[0-9a-fA-F]{8}$"
243
+ }
244
+ }
245
+ }
246
+ }
247
+ }
248
+ }
249
+ },
250
+ "solanaPolicy": {
251
+ "type": "object",
252
+ "additionalProperties": false,
253
+ "required": ["chain", "networks", "program_ids"],
254
+ "properties": {
255
+ "chain": {
256
+ "const": "solana"
257
+ },
258
+ "networks": {
259
+ "type": "array",
260
+ "minItems": 1,
261
+ "uniqueItems": true,
262
+ "items": {
263
+ "type": "string",
264
+ "enum": ["mainnet", "devnet", "testnet"]
265
+ }
266
+ },
267
+ "program_ids": {
268
+ "type": "array",
269
+ "minItems": 1,
270
+ "maxItems": 64,
271
+ "uniqueItems": true,
272
+ "items": {
273
+ "type": "string",
274
+ "pattern": "^[1-9A-HJ-NP-Za-km-z]{32,44}$"
275
+ }
276
+ }
277
+ }
278
+ }
279
+ },
280
+ "allOf": [
281
+ {
282
+ "if": {
283
+ "properties": {
284
+ "trust": {
285
+ "enum": ["community_read_only", "verified_read_only"]
286
+ }
287
+ },
288
+ "required": ["trust"]
289
+ },
290
+ "then": {
291
+ "properties": {
292
+ "permissions": {
293
+ "type": "object",
294
+ "properties": {
295
+ "transaction_intents": {
296
+ "const": false
297
+ }
298
+ }
299
+ },
300
+ "tools": {
301
+ "type": "array",
302
+ "items": {
303
+ "type": "object",
304
+ "properties": {
305
+ "read_only": {
306
+ "const": true
307
+ }
308
+ }
309
+ }
310
+ }
311
+ }
312
+ }
313
+ },
314
+ {
315
+ "if": {
316
+ "properties": {
317
+ "trust": {
318
+ "const": "verified_write"
319
+ }
320
+ },
321
+ "required": ["trust"]
322
+ },
323
+ "then": {
324
+ "required": ["artifact_digest", "chains"],
325
+ "properties": {
326
+ "artifact_digest": true,
327
+ "chains": true,
328
+ "permissions": {
329
+ "type": "object",
330
+ "properties": {
331
+ "transaction_intents": {
332
+ "const": true
333
+ }
334
+ }
335
+ }
336
+ }
337
+ }
338
+ }
339
+ ]
340
+ }
@@ -0,0 +1,159 @@
1
+ # AgentLayer Connector Protocol v1
2
+
3
+ ## Status
4
+
5
+ Protocol v1 is frozen for the read-only public beta. Additive optional fields
6
+ may be introduced in v1, but existing required fields, response binding, trust
7
+ semantics, and tool namespaces cannot change without a new protocol version.
8
+
9
+ The read-only beta supports direct HTTPS invocation of publisher-hosted
10
+ `community_read_only` and `verified_read_only` connectors. Gateway-attested
11
+ requests are an additive deployment mode. Write-capable execution remains
12
+ experimental and is not part of the read-only beta release.
13
+
14
+ ## Components
15
+
16
+ - **Local registry** pins manifests selected by the user.
17
+ - **Gateway** may authenticate invocations and route them to an exact connector
18
+ version; direct read-only HTTPS invocation does not require it.
19
+ - **Connector runtime** returns structured read results or unsigned intents.
20
+ - **Local wallet** validates schemas, policy, simulation, approval, signing,
21
+ broadcast, and final confirmation.
22
+
23
+ ## Identity and immutability
24
+
25
+ A connector is identified by `(id, version, artifact_digest)`. Published
26
+ versions are immutable. A changed artifact requires a new version. The local
27
+ registry pins all three values and refuses a response that names a different
28
+ identity.
29
+
30
+ ## Tool namespaces
31
+
32
+ Tool names in a manifest are connector-local. Hosts expose them as:
33
+
34
+ ```text
35
+ connector__<normalized_connector_id>__<tool_name>
36
+ ```
37
+
38
+ Normalized names contain lowercase ASCII letters, digits, and underscores.
39
+
40
+ ## Invocation request
41
+
42
+ The wallet sends a JSON request containing:
43
+
44
+ ```json
45
+ {
46
+ "protocol_version": 1,
47
+ "request_id": "uuid",
48
+ "connector": {
49
+ "id": "com.example.protocol",
50
+ "version": "1.0.0",
51
+ "artifact_digest": "sha256:..."
52
+ },
53
+ "tool": "get_markets",
54
+ "arguments": {},
55
+ "context": {
56
+ "chain": "evm",
57
+ "network": "base",
58
+ "chain_id": 8453,
59
+ "wallet_address": "0x..."
60
+ },
61
+ "issued_at": "2026-08-25T12:00:00Z",
62
+ "expires_at": "2026-08-25T12:00:30Z",
63
+ "nonce": "opaque-single-use-value"
64
+ }
65
+ ```
66
+
67
+ `wallet_address` is omitted unless the installed manifest grants that
68
+ permission. `issued_at`, `expires_at`, and `nonce` are optional for direct
69
+ read-only HTTPS invocation and required for gateway-attested requests. A
70
+ connector must ignore unknown optional context fields and must never infer
71
+ permission from their presence.
72
+
73
+ The required request fields are `protocol_version`, `request_id`, `connector`,
74
+ `tool`, `arguments`, and `context`.
75
+
76
+ ## Invocation response
77
+
78
+ Every successful response contains the exact connector identity, request ID,
79
+ tool name, expiry, and one result kind:
80
+
81
+ ```json
82
+ {
83
+ "protocol_version": 1,
84
+ "request_id": "uuid",
85
+ "connector": {
86
+ "id": "com.example.protocol",
87
+ "version": "1.0.0",
88
+ "artifact_digest": "sha256:..."
89
+ },
90
+ "tool": "get_markets",
91
+ "kind": "read_result",
92
+ "result": {},
93
+ "expires_at": "2026-08-25T12:01:00Z"
94
+ }
95
+ ```
96
+
97
+ The complete encoded response body must not exceed 1 MiB and must use
98
+ `Content-Type: application/json`.
99
+
100
+ Write-capable responses use `evm_transaction_intent` or
101
+ `solana_transaction_intent`. They remain unsigned and unbroadcasted.
102
+
103
+ ## Read-only enforcement
104
+
105
+ Community and verified read-only connectors may return only `read_result`.
106
+ Returning any transaction, payment, signature, or broadcast intent is a hard
107
+ protocol violation. Read output is untrusted external data and must be checked
108
+ against the manifest's output schema before it reaches an agent host.
109
+
110
+ To prevent a read result from masquerading as an executable envelope, these
111
+ field names are reserved at every depth of `result`: `approval_token`,
112
+ `broadcast_request`, `evm_transaction_intent`, `payment_intent`,
113
+ `raw_transaction`, `signed_transaction`, `signing_request`,
114
+ `solana_transaction_intent`, and `transaction_intent`.
115
+
116
+ Connector output is data, never agent instruction. Hosts must not treat text in
117
+ a connector result as authorization, policy, tool-routing guidance, or a reason
118
+ to perform another action.
119
+
120
+ ## Read-only beta compatibility
121
+
122
+ - A connector built for Protocol v1 must keep accepting all v1 required fields.
123
+ - Adding a required manifest, request, response, or tool field requires a new
124
+ protocol version or a new connector tool/version.
125
+ - Tool input/output schemas are immutable for a published connector version.
126
+ - `artifact_digest`, when present, is identity-bound and must match exactly.
127
+ - Community connectors cannot become write-capable without a new verified
128
+ connector version and a different release track.
129
+
130
+ ## Write execution
131
+
132
+ Only an enabled `verified_write` connector may return a transaction intent.
133
+ The local wallet must independently enforce:
134
+
135
+ - exact connector identity and artifact digest
136
+ - supported chain and network
137
+ - wallet/from/fee-payer binding
138
+ - contract addresses or Solana program IDs
139
+ - EVM selectors or Solana instruction constraints
140
+ - assets, amounts, recipients, spenders, and native value
141
+ - bounded approvals
142
+ - intent expiry and replay protection
143
+ - successful local simulation
144
+ - preview-to-execute binding
145
+
146
+ The connector never signs or broadcasts. The local wallet refreshes the intent
147
+ after confirmation, repeats all checks, then signs and sends it.
148
+
149
+ ## Fees
150
+
151
+ Connector, referral, builder, and AgentLayer integration fees are prohibited.
152
+ Protocol fees, network fees, and x402 service prices must be explicit in the
153
+ preview and expected-effects data.
154
+
155
+ ## Failure behavior
156
+
157
+ Unknown fields required for safe interpretation, schema mismatch, identity
158
+ mismatch, stale intent, failed simulation, unknown target, unknown program,
159
+ unknown selector, or expanded approval must fail closed.