@agentlayer.tech/wallet 0.1.101 → 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.
- package/.openclaw/extensions/agent-wallet/dist/index.js +46 -1
- package/.openclaw/extensions/agent-wallet/index.ts +46 -1
- package/.openclaw/extensions/agent-wallet/openclaw.plugin.json +1 -1
- package/.openclaw/extensions/agent-wallet/package.json +1 -1
- package/README.md +18 -0
- package/VERSION +1 -1
- package/agent-wallet/agent_wallet/__init__.py +1 -1
- package/agent-wallet/agent_wallet/connector_cli.py +198 -0
- package/agent-wallet/agent_wallet/connectors/__init__.py +28 -0
- package/agent-wallet/agent_wallet/connectors/catalog.py +68 -0
- package/agent-wallet/agent_wallet/connectors/client.py +308 -0
- package/agent-wallet/agent_wallet/connectors/intent_policy.py +243 -0
- package/agent-wallet/agent_wallet/connectors/manifest.py +192 -0
- package/agent-wallet/agent_wallet/connectors/registry.py +341 -0
- package/agent-wallet/agent_wallet/openclaw_adapter.py +56 -5
- package/agent-wallet/openclaw.plugin.json +1 -1
- package/agent-wallet/pyproject.toml +4 -2
- package/agent-wallet/scripts/build_release_bundle.py +1 -0
- package/agent-wallet/scripts/install_agent_wallet.py +1 -1
- package/bin/openclaw-agent-wallet.mjs +38 -0
- package/claude-code/plugins/agent-wallet/.claude-plugin/plugin.json +1 -1
- package/codex/plugins/agent-wallet/.codex-plugin/plugin.json +1 -1
- package/codex/plugins/agent-wallet/server.py +4 -1
- package/connectors/AGENTS.md +37 -0
- package/connectors/DEVELOPER_GUIDE.md +131 -0
- package/connectors/README.md +139 -0
- package/connectors/READ_ONLY_BETA.md +54 -0
- package/connectors/RELEASING.md +48 -0
- package/connectors/conformance/README.md +31 -0
- package/connectors/conformance/package.json +54 -0
- package/connectors/conformance/scripts/sync-license.mjs +3 -0
- package/connectors/conformance/scripts/sync-spec.mjs +16 -0
- package/connectors/conformance/src/cli.ts +43 -0
- package/connectors/conformance/src/index.ts +7 -0
- package/connectors/conformance/src/runner.ts +314 -0
- package/connectors/conformance/src/types.ts +27 -0
- package/connectors/conformance/test/fixtures/invalid-response-identity.json +14 -0
- package/connectors/conformance/test/fixtures/missing-tool-fixture.json +4 -0
- package/connectors/conformance/test/runner.test.mjs +151 -0
- package/connectors/conformance/tsconfig.json +17 -0
- package/connectors/examples/reference-crypto-data/Dockerfile +21 -0
- package/connectors/examples/reference-crypto-data/README.md +51 -0
- package/connectors/examples/reference-crypto-data/conformance.json +11 -0
- package/connectors/examples/reference-crypto-data/connector.json +95 -0
- package/connectors/examples/reference-crypto-data/package.json +21 -0
- package/connectors/examples/reference-crypto-data/railway.toml +9 -0
- package/connectors/examples/reference-crypto-data/src/connector.ts +137 -0
- package/connectors/examples/reference-crypto-data/src/server.ts +13 -0
- package/connectors/examples/reference-crypto-data/test/connector.test.mjs +97 -0
- package/connectors/examples/reference-crypto-data/tsconfig.json +17 -0
- package/connectors/package-lock.json +561 -0
- package/connectors/package.json +19 -0
- package/connectors/scripts/smoke-packed-packages.mjs +121 -0
- package/connectors/sdk-typescript/README.md +47 -0
- package/connectors/sdk-typescript/package.json +49 -0
- package/connectors/sdk-typescript/scripts/sync-license.mjs +3 -0
- package/connectors/sdk-typescript/src/connector.ts +204 -0
- package/connectors/sdk-typescript/src/errors.ts +11 -0
- package/connectors/sdk-typescript/src/http.ts +116 -0
- package/connectors/sdk-typescript/src/index.ts +26 -0
- package/connectors/sdk-typescript/src/types.ts +101 -0
- package/connectors/sdk-typescript/test/sdk.test.mjs +181 -0
- package/connectors/sdk-typescript/tsconfig.json +21 -0
- package/connectors/spec/connector-manifest.schema.json +340 -0
- package/connectors/spec/connector-protocol.md +159 -0
- package/connectors/spec/transaction-intent.schema.json +281 -0
- package/connectors/templates/read-only/.env.example +1 -0
- package/connectors/templates/read-only/Dockerfile +11 -0
- package/connectors/templates/read-only/README.md +33 -0
- package/connectors/templates/read-only/conformance.json +11 -0
- package/connectors/templates/read-only/connector.json +64 -0
- package/connectors/templates/read-only/package.json +21 -0
- package/connectors/templates/read-only/railway.toml +9 -0
- package/connectors/templates/read-only/src/connector.ts +61 -0
- package/connectors/templates/read-only/src/server.ts +14 -0
- package/connectors/templates/read-only/test/connector.test.mjs +62 -0
- package/connectors/templates/read-only/tsconfig.json +17 -0
- package/hermes/plugins/agent_wallet/plugin.yaml +1 -1
- package/package.json +2 -1
- package/wdk-btc-wallet/package.json +1 -1
- 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.
|