@visa/cli 5.0.0-rc.408 → 5.0.0-rc.411

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.
@@ -1,116 +0,0 @@
1
- # Running Visa agent setup in OpenClaw and Hermes
2
-
3
- `@visa/visa-cli-openclaw` is packaged for OpenClaw, but the skill is runtime-agnostic.
4
- OpenClaw, Hermes, and any runtime that can execute the `visa` CLI or mount its MCP server
5
- all drive the same setup operation: identity plus every requested rail, behind one owner
6
- approval.
7
-
8
- ## Plugins are runtime-specific
9
-
10
- | Axis | OpenClaw | Hermes |
11
- | --------------- | --------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
12
- | Language | JavaScript/TypeScript | Python |
13
- | Plugin manifest | `openclaw.plugin.json` + `definePluginEntry` (`index.ts`) | `~/.hermes/plugins/<name>/plugin.yaml` + `__init__.py`, `ctx.register_tool(...)` |
14
- | Config file | `~/.openclaw/openclaw.json` | `~/.hermes/config.yaml` |
15
- | Skills | Markdown `SKILL.md` | Markdown under `~/.hermes/skills/<name>/` |
16
- | MCP | `mcp.servers.*` | `mcp_servers.*` |
17
- | Migration | — | `hermes claw migrate` imports skills, allowlists, compatible MCP servers, memory, and `SOUL.md` |
18
-
19
- The OpenClaw JavaScript tools do not load as a Hermes plugin. Portability comes from the
20
- Markdown skill, CLI, and MCP protocol instead.
21
-
22
- ## One ceremony, two surfaces
23
-
24
- Both supported surfaces run the same protected enrollment and share the same local
25
- pending record:
26
-
27
- 1. Visa MCP server: `agent_enroll`, then `agent_enroll` with `wait: true` once the
28
- owner has the page open.
29
- 2. Terminal: `visa connect` (add `--format json` for machine output).
30
-
31
- Each returns one link and a short code for the human. The browser receives only that
32
- link. The agent's keys are generated on this device and never leave it, and the
33
- approval page certifies only the keys this device named in the link. Calling it again
34
- resumes the same pending enrollment after an interruption.
35
-
36
- Use `agentId` as the stable identity. `identityKeyJkt` identifies the currently bound
37
- Ed25519 public key and can change after key rotation.
38
-
39
- The older plugin pairing tools and MCP enrollment tools are gone: they drove CLI
40
- commands that no longer exist. `agent_enroll` (MCP) and `visa connect` are the one door.
41
-
42
- ## Install and mount
43
-
44
- Install the prerelease CLI, which provides both command names and the MCP server:
45
-
46
- ```sh
47
- npm install -g @visa/cli@rc
48
- ```
49
-
50
- There is no `visa mcp` subcommand. Run `visa-cli connect <runtime>` when supported, or
51
- configure `@visa/cli/dist/mcp-server/index.js` directly. Replace `<npm root -g>` below
52
- with the output of `npm root -g`.
53
-
54
- OpenClaw (`~/.openclaw/openclaw.json`):
55
-
56
- ```json
57
- {
58
- "mcp": {
59
- "servers": {
60
- "visa-cli": {
61
- "command": "node",
62
- "args": ["<npm root -g>/@visa/cli/dist/mcp-server/index.js"]
63
- }
64
- }
65
- }
66
- }
67
- ```
68
-
69
- Hermes (`~/.hermes/config.yaml`). Hermes passes a filtered platform-safe baseline
70
- (`PATH`, `HOME`, platform variables, and `XDG_*`) plus this server's `env:` map.
71
- Arbitrary gateway variables are excluded, so map `VISA_RC_CODE` explicitly. The
72
- placeholder keeps its value in `~/.hermes/.env` instead of `config.yaml`:
73
-
74
- ```yaml
75
- mcp_servers:
76
- visa-cli:
77
- command: node
78
- args: ['<npm root -g>/@visa/cli/dist/mcp-server/index.js']
79
- env:
80
- VISA_RC_CODE: ${VISA_RC_CODE}
81
- # Optional overrides for a different state directory or toolchain:
82
- # HOME: /home/<user>
83
- # PATH: /usr/local/bin:/usr/bin:/bin
84
- ```
85
-
86
- ### Keep one local-state namespace
87
-
88
- The gateway shell and the Visa MCP subprocess must resolve the same `HOME` and
89
- `VISA_CLI_HOME`. Set that boundary before pairing and keep it stable. Changing
90
- `VISA_CLI_HOME` later also changes where paired identity and grant records are
91
- read; it is not a safe way to make an old contact file visible.
92
-
93
- For example, with `HOME=/opt/data/home` and no `VISA_CLI_HOME`, identity lives
94
- under `/opt/data/home/.visa-cli` and checkout contact under
95
- `/opt/data/home/.visa-mcp`. A profile at `/opt/data/.visa-mcp` belongs to a
96
- different state namespace. Do not scan, copy, or auto-adopt it: contact files
97
- contain owner PII. The host passes checkout details to `purchase_create` itself;
98
- no Visa tool writes the profile.
99
-
100
- ## Runtime setup map
101
-
102
- | Runtime | Setup surface |
103
- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
104
- | OpenClaw | Install `@visa/cli@rc` (`npm install -g @visa/cli@rc`) and run `visa connect openclaw`. It plants the skill under `~/.openclaw/skills/` and mounts the Visa MCP server into `~/.openclaw/openclaw.json`. (The `@visa/visa-cli-openclaw` plugin package is prerelease). |
105
- | Hermes | Run `visa connect hermes`. It resolves the per-profile skills directory and refuses to guess when several profiles exist — set `HERMES_PROFILE` to choose one. `hermes claw migrate` can import an existing OpenClaw setup. |
106
- | Codex | Run `visa connect codex`. It plants the skill under `~/.codex/skills/` and mounts the Visa MCP server into `~/.codex/config.toml` in the same step. |
107
- | Other runtime | Put `visa` on `PATH` and mount the same MCP server by hand; `get_status` shows what is connected. |
108
-
109
- The skill is planted by `visa connect <client>`, into that client's own skills
110
- directory. Reload the runtime afterwards.
111
-
112
- ## Optional Hermes wrapper
113
-
114
- A Hermes Python plugin may wrap the canonical raw CLI commands and register tools with
115
- `ctx.register_tool(...)`. It is optional: the MCP server and skill already expose the
116
- same operation and persisted local state without a second implementation.
@@ -1,464 +0,0 @@
1
- ---
2
- name: pair-visa-agent
3
- description: Set up a Visa CLI v4 agent through the single protected enrollment implementation (MCP `agent_enroll` or `visa connect`), and report its live capabilities honestly. The owner always approves in their browser. Use when the user says "pair my agent", "connect Visa", "enroll my Visa CLI", "set up my agent", or "let this agent pay".
4
- compatibility: Needs the `visa` CLI (`npm i -g @visa/cli@rc`) — run `node scripts/setup.mjs` to install it if missing — plus network access to the Visa authorization service. Works in OpenClaw, Hermes, Claude Code, Codex, or any Agent Skills runtime.
5
- allowed-tools: Bash(visa:*) Bash(visa-cli:*) Bash(node:*) Bash(npm:*) Bash(npx:*)
6
- metadata:
7
- author: visa
8
- homepage: https://visacli.sh/agents
9
- version: '0.9.0'
10
- # OpenClaw-namespaced extension (agentskills.io keeps `metadata` free-form, so
11
- # non-standard runtime config lives here — `user-invocable` is not a standard
12
- # top-level field). OpenClaw auto-installs `install[]` when `requires.bins` are
13
- # missing; other runtimes (Hermes, Claude Code, …) self-provision via the
14
- # bundled `scripts/setup.mjs` (see compatibility + Getting set up). @rc pinned
15
- # until 4.1.0 is promoted to latest.
16
- openclaw:
17
- user-invocable: true
18
- emoji: '🔐'
19
- requires:
20
- bins:
21
- - visa
22
- install:
23
- - kind: node
24
- package: '@visa/cli@rc'
25
- bins:
26
- - visa
27
- - visa-cli
28
- ---
29
-
30
- # Set up a Visa agent
31
-
32
- One protected enrollment carries everything: this runtime's identity, the binding to
33
- **this device**, and the spending limits — behind a **single** owner approval in their
34
- browser.
35
-
36
- It has two entrances to the exact same protected enrollment implementation: the same
37
- native signer, Authority routes, owner browser approval, and limits. Never invent or mix
38
- in a second ceremony.
39
-
40
- - **You have the Visa MCP server mounted:** call `agent_enroll` and hand the owner the one
41
- link and short code it returns. Call it again with `wait: true` once they have the page
42
- open; it finishes activation only after they approve.
43
- - **The owner is at a terminal:** they run the command below.
44
-
45
- ```
46
- # the human runs this:
47
- visa connect
48
-
49
- → it prints a URL and a short code
50
- → the human opens the URL and enters the code at /agent/enroll/protected-agent
51
- → the human approves the device and its spending limits (one approval)
52
- → the command finishes; `get_status` now reports pairing.paired: true
53
- ```
54
-
55
- The installed CLI selects its own service origins from its release channel. Never ask
56
- for, guess, or construct a Visa URL.
57
-
58
- Running the same command again resumes an interrupted enrolment; `--restart` replaces an
59
- unclaimed request with a fresh code. `--ceiling <usd>` and `--per-transaction <usd>`
60
- propose limits the owner confirms on the approval page.
61
-
62
- ## The tools the Visa MCP server serves
63
-
64
- The Visa MCP server serves exactly these tools: `get_status`, `agent_enroll`,
65
- `discover`, `pay` and `history`, plus the card preview's
66
- `purchase_create`, `purchase_retrieve` and `purchase_cancel` where the build lists
67
- them. Call no other Visa tool name, whatever an older guide, a memory or another
68
- agent says: every earlier setup, login, pairing, capability and wallet tool is gone.
69
- Read the live tool list if in doubt.
70
-
71
- ## The older ceremonies were deleted — do not call them
72
-
73
- The whole `visa setup` and `visa agent` command groups are gone too — including the
74
- retired `agent pair`, `agent create`, `agent verify`, `agent enroll-claim`,
75
- `agent claim`, `agent pairing-resume`, `agent connect`, `agent handoff-claim` and
76
- every `agent grant-*` verb.
77
-
78
- **`visa connect` is the LIVE door and is not on that list.** It is the
79
- top-level command, not the retired `visa agent connect` subcommand: one is the
80
- one door, the other is a ceremony that no longer exists.
81
-
82
- A retired command, or an older build still answering a retired tool name, returns
83
- one refusal:
84
-
85
- ```json
86
- {
87
- "code": "legacy_door_removed",
88
- "kind": "caller",
89
- "fix": "visa connect (shell) or agent_enroll (MCP)"
90
- }
91
- ```
92
-
93
- That code means the door no longer exists. **Relay the replacement and stop.** Do not
94
- retry it, do not try a variant spelling, and do not report it to the human as an outage:
95
- nothing was signed, paired, or paid.
96
-
97
- ## What "set up" means here
98
-
99
- Each completed protected enrollment mints a **new** agent: a new server-assigned agent,
100
- a new device-held Ed25519 identity key, and the wallet limits the owner approved.
101
-
102
- - The runtime keeps the private Ed25519 key and sends only the public JWK.
103
- - The limits are the ones the owner actually approved on the page. Nothing you asked for
104
- is granted until they approve it.
105
- - An email address, a `.visa` mesh name, and TAP bindings remain separate, later
106
- configuration. Do not infer them from a finished enrolment.
107
-
108
- **Where the `agentId` comes from — read this before you quote one.** Do not invent it and
109
- do not read it out of the command's terminal output, which you often cannot see. Read it
110
- from `get_status` once the enrolment finishes. Never substitute a
111
- correlation id, a confirmation code, or an origin for an `agentId`.
112
-
113
- **Re-running the command does not repair an agent that already exists** — it creates a
114
- second one. To fix a capability an existing agent is missing, see "Already set up — do NOT
115
- enrol again" near the end.
116
-
117
- ## Getting this skill
118
-
119
- The skill ships inside the public `@visa/cli` npm package. No clone of the private
120
- monorepo is required:
121
-
122
- ```sh
123
- npm install -g @visa/cli@rc
124
- visa connect
125
- ```
126
-
127
- `visa connect` auto-detects the runtime it is running in. It plants this skill into that
128
- runtime's own skills directory (OpenClaw, Hermes, Claude Code and Codex each read their
129
- own), mounts the Visa MCP server, signs the owner in, enrols this machine's agent and
130
- renews its device lease — skipping whatever is already done. Pass a client explicitly
131
- (`visa connect codex`) when auto-detection is not what you want, and `--restart` to
132
- replace an edited skill. Reload or restart the agent runtime afterwards so it registers
133
- the skill.
134
-
135
- Access remains enforced by the Visa service. Installing the public package or skill does
136
- not authorize an account to pair.
137
-
138
- OpenClaw users receive the skill via `visa connect openclaw` (or through the `@visa/visa-cli-openclaw` plugin when running from source).
139
-
140
- ## Getting set up
141
-
142
- 1. **Install the prerelease CLI.** Run `npm install -g @visa/cli@rc`, or run the bundled
143
- idempotent provisioner `node scripts/setup.mjs`. The `@latest` tag may not yet expose
144
- the v4 setup tools. Installation puts `visa` and `visa-cli` on `PATH` and includes
145
- `@visa/cli/dist/mcp-server/index.js`.
146
- 2. **Run `visa connect <client>`.** One command: it plants the skill, writes the MCP
147
- entry, signs the owner in, enrols this machine's agent and renews its device lease.
148
- - **OpenClaw:** `visa connect openclaw` writes `mcp.servers["visa-cli"]` in
149
- `~/.openclaw/openclaw.json`. (Installing `@visa/visa-cli-openclaw` from
150
- source/tarball also auto-mounts the server).
151
- - **Hermes:** `visa connect hermes` writes the entry under `mcp_servers` in
152
- `~/.hermes/config.yaml`.
153
- - **No MCP integration:** everything below still works — connecting is a shell
154
- command, and `--format json` is available on every command.
155
- 3. **Check what is owed.** `get_status` reports the owner, the agent, its limits, which
156
- clients are mounted, and one `next:` line when something is blocking.
157
-
158
- ## MCP mounting examples
159
-
160
- Both runtimes use the same server entrypoint. Replace `<npm root -g>` with the output of
161
- `npm root -g`.
162
-
163
- OpenClaw (`~/.openclaw/openclaw.json`):
164
-
165
- ```json
166
- {
167
- "mcp": {
168
- "servers": {
169
- "visa-cli": {
170
- "command": "node",
171
- "args": ["<npm root -g>/@visa/cli/dist/mcp-server/index.js"]
172
- }
173
- }
174
- }
175
- }
176
- ```
177
-
178
- Hermes (`~/.hermes/config.yaml`). **Hermes passes ONLY this `env:` map to the MCP
179
- subprocess — it does NOT inherit the gateway environment.** Omitting a required variable
180
- (an RC access code, the right `HOME`, `PATH`) makes the server exit on every start, so no
181
- Visa tool registers at all, while the terminal — which reads on-disk state with the
182
- gateway's own environment — can still look healthy. Always set the map explicitly:
183
-
184
- ```yaml
185
- mcp_servers:
186
- visa-cli:
187
- command: node
188
- args: ['<npm root -g>/@visa/cli/dist/mcp-server/index.js']
189
- # Hermes does NOT inherit the gateway env. This map is the entire
190
- # subprocess environment; omit VISA_RC_CODE and the server exits on boot.
191
- env:
192
- HOME: /home/<user> # the home that holds this runtime's .visa-cli state
193
- VISA_RC_CODE: <access code>
194
- PATH: /usr/local/bin:/usr/bin:/bin
195
- ```
196
-
197
- Hermes also loads skills **per profile** from `~/.hermes/profiles/<profile>/skills/`, not
198
- from `~/.hermes/skills/`. `visa connect hermes` resolves this automatically: it targets
199
- the single profile when exactly one exists (or the one named by `HERMES_PROFILE`), and
200
- **fails loudly** on a multi-profile box instead of planting into the flat dir nothing
201
- reads — set `HERMES_PROFILE` to choose.
202
-
203
- **Hermes sanitizes MCP server names when registering tools.** A server declared
204
- `visa-cli` in `mcp_servers:` registers its tools as `mcp__visa_cli__<tool>` — with an
205
- UNDERSCORE, not the declared hyphen. Anything that hardcodes `mcp__visa-cli__<tool>` gets
206
- `unknown tool` on every call while looking correct in review. Read tool names off the
207
- live registry; never derive them from the config key.
208
-
209
- In Hermes, `hermes claw migrate` can also import this skill and MCP configuration from an
210
- existing OpenClaw installation. See `RUNTIMES.md` for the complete runtime map.
211
-
212
- ## Sign in first — the wallet is owner-bound
213
-
214
- The USDC wallet is delegated out of the owner's own wallet, so this runtime needs a live
215
- owner session. The one door takes care of the order: `agent_enroll` (and `visa connect`)
216
- signs the owner in first whenever the session is missing or has lapsed, and only then
217
- starts the enrolment.
218
-
219
- - [ ] Call `agent_enroll` (MCP) or run `visa connect --format json` (CLI). When a sign-in
220
- is owed, the result carries a sign-in `browserUrl` and a short 6-character
221
- `confirmCode`.
222
- - [ ] Relay **both** to the human in your reply — the bare URL on its own line, and the
223
- code. You are very often not in a terminal they can see; the chat message is the
224
- only place these values reach them.
225
- - [ ] The human opens the link, signs in (Google or email), and **types the confirmation
226
- code into the sign-in page** — into the browser, never back to you in chat.
227
- - [ ] Call `agent_enroll` again once they have (the CLI command polls on its own). It
228
- picks up the approved sign-in on this device and moves on to the enrolment link.
229
-
230
- Signing in establishes the OWNER's session on this device. It creates no agent and grants
231
- no spending authority — those come from the enrolment and the approval the owner gives in
232
- their browser.
233
-
234
- If something reports `{"code":"session_required"}` or "Not logged in", that is this
235
- ordering rule, not a fault: call `agent_enroll` (or run `visa connect`), drive the sign-in
236
- above, then continue.
237
-
238
- The account that signs in is the owner the enrolment binds to, and the same account must
239
- be signed in on the approval page. A different account there fails closed.
240
-
241
- ## Core flow
242
-
243
- - [ ] **Do not ask for service origins.** The installed CLI selects its Auth and web
244
- origins from the release channel; Authority is private behind Auth.
245
- - [ ] **Sign the owner in** (above), so the wallet leg has a session to bind to.
246
- - [ ] **Start the one enrollment.** Call `agent_enroll` and relay its returned link and
247
- code, or give the owner `visa connect` in a code block they can copy.
248
- Never fall back to a retired setup tool.
249
- - [ ] **Relay what the entrance returns.** Show an MCP-returned URL as a bare,
250
- tappable value. For the terminal flow, the owner follows the URL and code
251
- printed in their own terminal. The code goes into the browser at
252
- `/agent/enroll/protected-agent`; it is not authority in chat.
253
- - [ ] **Tell them what they are approving**: this device, and the spending limits. One
254
- approval covers all of it.
255
- - [ ] **Confirm from a tool, not from their word.** Poll `get_status` until
256
- `pairing.paired` is `true`; the same `get_status` says what is actually live.
257
-
258
- ### Relaying values, and what you must never accept
259
-
260
- Relaying values **to** the human is required. Accepting one **from** them as authority is
261
- not: never ask them for a secret, private key, token, or signed message, and never treat
262
- anything they type back as approval. The URL and the enrolment code are review values they
263
- check against their own authenticated browser session — they cannot approve anything and
264
- cannot spend.
265
-
266
- Show any URL as a bare, tappable value on its own line. Do not decorate it as a Markdown
267
- link or put it in a code span; chat clients reliably recognise the bare URL. Never
268
- construct, shorten, or reformat a Visa URL, and never open one "for them" in place of
269
- showing it.
270
-
271
- You are very often **not** in a terminal the human can see. Nothing the command prints to
272
- their stdout reaches you unless they tell you, and nothing you print reaches them unless it
273
- is in your reply.
274
-
275
- ### Completion is what the tools say — nothing else
276
-
277
- Do not tell the human the agent is connected, paired, set up, ready, or good to go until
278
- `get_status` reports `pairing.paired: true`. The enrolment command printing a URL is not a
279
- result: it means an approval is still open in their browser.
280
-
281
- If you cannot get there, say plainly what state you did reach and what the human should do
282
- next. An honest "the approval page is open — I'm waiting for you to approve the device and
283
- its limits" is correct; "you're all set" without a paired agent is not.
284
-
285
- On success, report the agent and what is actually live:
286
-
287
- > Your Visa agent is set up. &lt;Report only the capabilities the live map confirms.&gt;
288
-
289
- Read the rails from `get_status`, never from what was requested.
290
-
291
- ## Interruption and resume
292
-
293
- The runtime persists the pending enrolment before it starts, so an interrupted run is safe
294
- to repeat: **the same command again** resumes it, with the same request and the same
295
- device key.
296
-
297
- - Same command, no flags changed — resumes and reprints the URL and code.
298
- - `--restart` — replaces an unclaimed request with a fresh terminal code. Use it only when
299
- the previous code is genuinely unusable; it is not a retry button.
300
- - `--wait` — keeps the command polling until the owner has approved, instead of returning
301
- after printing the link.
302
-
303
- Do not tell the human to run a second, different enrolment because the first went quiet.
304
- Two enrolments mean two agents, two identities, and a confused owner. Do not delete or edit
305
- local pending files to fix a transient failure, and never copy pending state between
306
- runtimes.
307
-
308
- ## Management commands (an agent that already exists)
309
-
310
- ```
311
- get_status {} # owner, agent, limits, mounts, every readiness gate
312
- history {} # this agent's payments
313
- # Caps are the owner's, in the Visa Console: /agent/enroll/limits?agent=<agent-id>
314
- # Spend across every rail is the Console's Activity feed.
315
- visa disconnect --revoke # drop this machine's spending authority
316
- ```
317
-
318
- `get_status` is the one call that answers "can it spend, and what is missing" — it
319
- carries the readiness gates the old `spendability` and `preflight` commands each answered
320
- a fragment of. Pausing, resuming, renaming and revoking an agent are owner actions in the
321
- Visa Console, not terminal commands.
322
-
323
- None of these creates an identity. Prefer structured output and parse it; never scrape
324
- prose.
325
-
326
- ## Already set up — do NOT enrol again
327
-
328
- If this device already holds an agent, a fresh enrolment is not needed and creates a
329
- _second, separate_ agent. Do this instead:
330
-
331
- 1. **Tell the user plainly:** "This device is already set up as `<name>`." Read the name
332
- from `get_status`. Start another enrolment only if they
333
- explicitly want a second agent.
334
- 2. **Report status honestly — "set up" is several separate things.** Never imply the agent
335
- can spend just because it exists. Read it live from `get_status` rather than guessing
336
- from prose: it reports pairing, account and version, and answers "can it spend, and
337
- what is missing".
338
- - **Identity** — bound to _this user's_ account, on _this device_.
339
- - **Spending** — the limits the owner approved in the browser. You **cannot** self-grant
340
- either rail or self-mint a wallet: the wallet arrives only by the owner's delegation.
341
- - **Trusted (TAP)** — follows spend/provisioning; don't promise it before then.
342
- 3. **Scope everything to the user.** The identity is bound to the account they signed in
343
- with; the wallet and limits are theirs. Speak in terms of "your agent / your account /
344
- the limits you approved", never a shared identity.
345
-
346
- ## An existing agent is missing a capability
347
-
348
- There is no rail-add ceremony any more: `visa agent grant-card` / `grant-wallet` /
349
- `grant-activate` / `grant-claim` were deleted, and calling one returns
350
- `legacy_door_removed`.
351
-
352
- What to do instead:
353
-
354
- - [ ] **Diagnose first.** `get_status` says
355
- exactly what is missing. Do not start anything before you know which of identity,
356
- wallet delegation, card authority or funding is absent.
357
- - [ ] **If the device's identity custody is broken**, `visa connect` repairs it in place
358
- without minting a new agent — it renews the device lease and skips every step that
359
- is already done.
360
- - [ ] **If the OWNER never approved that authority**, only they can add it. Say so, name
361
- what is missing, and stop. Enrolling again mints a NEW agent — it does not upgrade
362
- this one, and doing it silently leaves the owner with two agents and one funded
363
- wallet.
364
-
365
- A policy refusal or timeout means **nothing was signed**: report it and stop; do not retry
366
- with a different command or a reconstructed URL. Never raise a human-approved limit
367
- yourself.
368
-
369
- ## Spending, once a rail is live
370
-
371
- Wallet: `discover` finds what to buy (a query, or a listing id to read one without
372
- paying), `pay` pays it with a mandatory `max` ceiling, and `history` reads this agent's
373
- payments. The limits are the ones the owner approved; the owner changes them in the Visa
374
- Console, never you. Funding is the owner's, in the Console.
375
-
376
- Card: Visa-operated browser checkout is retired; another enrollment will not repair it.
377
- The retired browser-checkout tools refuse with `card_browser_checkout_removed`.
378
- On local builds that list `purchase_create`,
379
- `purchase_retrieve` and `purchase_cancel`, the protected card preview uses the
380
- host's checkout tools and the existing eligible card and agent identity. Follow
381
- `next`: relay the single owner setup or limits URL, let the owner act, then repeat
382
- the same purchase call. Never ask for funding-card secrets in chat. Explicit
383
- `include:"card"` may put the issued purchase credential in model/chat history,
384
- under the owner's disclosure consent. A saved card or tester flag alone does
385
- not establish eligibility or merchant credential compatibility. UCP discovery
386
- and preparation remain separate from payment execution; a `not_ready` handoff
387
- is not permission to pay or to revive the retired browser flow.
388
-
389
- On a hosted runtime, **every payment requires the owner's browser
390
- approval** until the protected no-tap executor lands. Enrollment, a session, or a spending
391
- grant does not approve a later hosted payment. Relay the hosted approval URL and wait for
392
- the owner's decision before reporting success or retrying.
393
-
394
- ## Retired mesh integration
395
-
396
- Subway messaging and `visa register` are retired. Pairing grants no directory or
397
- messaging authority. Do not attempt mesh registration or improvise another transport.
398
-
399
- ## Optional agent mailbox (separate from setup)
400
-
401
- Connecting an agent does not provision an email address or inbox, and no Visa tool
402
- connects or reads one. There is no terminal command for this either. Do not claim setup
403
- set up mail, and do not improvise a mailbox. A mailbox would grant an email address and
404
- nothing more: it never authorizes a payment.
405
-
406
- ## Optional checkout profile (separate from setup)
407
-
408
- Do not collect a checkout profile to revive Visa browser checkout: it
409
- is retired. On local builds that list `purchase_create`, `purchase_retrieve` and
410
- `purchase_cancel`, the protected card preview reuses this identity and verified
411
- card. The host supplies checkout and billing details, owns browser submission,
412
- and follows the returned `next` action. Fixed protocol fields and `requestKey`
413
- may be omitted; retain the same checkout reference and terms on retry. Explicit
414
- `include:"card"` returns issued purchase credentials under owner consent and may
415
- put them in model/chat history. Never request original funding-card details in
416
- chat, bypass eligibility, or retry an uncertain merchant submission. Existing
417
- `~/.visa-mcp/contact.json` files use the format below; preserve them with mode `0600`.
418
- Never infer or invent identity or address data.
419
-
420
- No Visa tool writes this profile; the host passes checkout and billing details to
421
- `purchase_create` itself. Any shell that reads an existing profile must have the exact
422
- same `HOME` and `VISA_CLI_HOME` as the MCP subprocess. A profile found under another root
423
- is owner PII, not a migration candidate: never scan, copy, or auto-adopt it. If the roots
424
- drifted, keep the root holding the paired identity.
425
-
426
- ```jsonc
427
- {
428
- "fullName": "Ada Lovelace",
429
- "email": "ada@example.com",
430
- "addressLine1": "1 Analytical Way",
431
- "addressLine2": "",
432
- "city": "San Francisco",
433
- "state": "CA",
434
- "postalCode": "94105",
435
- "country": "US",
436
- }
437
- ```
438
-
439
- `fullName` must be non-blank; `firstName` plus `lastName` is also accepted. The engine reads
440
- the exact keys `fullName`, `firstName`, `lastName`, `email`, `addressLine1`, `addressLine2`,
441
- `city`, `state`, `postalCode`, and `country`. The profile supplies checkout/cardholder and
442
- billing data only. Its `email` value is not the account's verified owner email, an agent
443
- mailbox, key proof, recovery factor, or permission to spend.
444
-
445
- ## Security rules
446
-
447
- - Never read, print, log, paste, or transmit the private Ed25519 JWK or any local claim
448
- token.
449
- - Never read or echo local pending files. Present only the URL returned by the tool.
450
- - Never treat `identityKeyJkt` as the stable identity. Use `agentId` for references and
451
- persistence.
452
- - Never fetch or submit the review URL on the human's behalf. They review and approve it
453
- in their own browser.
454
- - Never invent a secondary path when a call fails. Preserve the local state, surface the
455
- error, and resume through the same protected entrance: call `agent_enroll` again, or
456
- repeat the same `visa connect` command.
457
- - Never call a retired door to "check whether it still works". `legacy_door_removed` is a
458
- final answer, not a transient failure.
459
-
460
- ## Further docs
461
-
462
- - `RUNTIMES.md` — OpenClaw, Hermes, and raw CLI setup.
463
- - `docs/agents/ARCHITECTURE.md` — where enrolment sits in the v4 request paths.
464
- - `visacli.sh/agents` — product-facing agent documentation.