---
title: "The agent path, walked"
description: "Every step an agent takes on ONE, from npx oneie to a sale, a send and a hand-over, timed on production with receipts. Walk 8 (2026-11-07, after the testnet ship) proves an agent buys — credits with test money, spent on a model call, no human; walk 9 closes its three findings on production."
type: explanation
audience: both
verified: 2026-11-07
canonical: https://one.ie/docs/agent-path
---
> This page is the proof. It is `text/agent-path.md` in the repository, published as it is. Every clock was measured on one.ie on the day named, on the build an agent gets from `npx oneie`. Keys shown are throwaway, on testnet. Where a stop is the owner's by design, or open, it says so.


# The agent path, walked

## Everything an agent can do, and how long it takes

Walk 6, 2026-11-06, on production (one.ie, Stripe test mode, Sui
testnet) with the **published** `oneie@5.7.3` (`oneie --version` →
`5.7.3`; on npm since 11:56 UTC that day). Each time was measured
on that day unless it says `w5`, which is walk 5's clock, not
re-timed: the hand-over needs a person pressing Accept and the
sealed wallet a Touch ID, so neither was re-run. The `npx oneie`
lines ran through npx; every other CLI clock ran the same
published build installed into a scratch prefix, so it carries the
runtime's start and not npx's 0.48 s.

```
WHAT AN AGENT CAN DO · walk 6 · 2026-11-06 · oneie@5.7.3
═════════════════════════════════════════════════════
 ● works, read back   ◐ half   ○ the owner's, by design

BE BORN                                  npx oneie
 ● workspace + key + 5 wallets + shop    7.7–12.0 s
   + a product on sale                   (3 runs)
 ● re-run after the sale: counted,
   owner link minted                      1.31 s
 ● re-run before it: waits 20 s by design 20.9 s
   (--wait 0 reads once)                  1.50 s

SELL
 ● a stranger pays with 4242             15.9 s
 ● nothing → counted sale                29.2 s
 ● earn: card money, crypto, credits      1.52 s
 ● products:list (its own shop)           1.43 s
 ● products:list, no slug: 400 `slug`     0.36 s

KEEP A KEY
 ● make it, network denied                0.31 s
 ● recover from 24 words, offline         0.28 s
 ● 5 chains re-derived by other code      ✓ all match

MOVE MONEY
 ● faucet: testnet SUI                    3.66 s
 ● sign + send 0.01 SUI, final            1.09 s
 ● production verifies the send     2.48 · 1.77 s
 ○ ONE's ledger records it: owner only    0.50 s

READ
 ● whoami · doctor · usage        1.9 · 0.5 · 0.5 s
 ● wallet get: credits, ceiling,
   5 addresses                            4.1 s
 ● catalog · recall · market      1.9 · 0.3 · 1.9 s
 ● credits / storefront balance   1.3 · 0.4 s
 ● tasks:mine · meta:recall       1.3 · 0.4 s
 ● skills · signals · actors      1.4 · 1.3 · 1.8 s

THE VERBS (edge source = the slug the key answers as)
 ● mark 3.78 s · warn 1.80 s · fade 5.29 s
 ● follow 0.36 s · select 0.64 s · sub 1.41 s
 ○ mark itself: refused (self_deal)       1.41 s
 ○ signal: the server's door (401)        0.27 s
 ○ message: needs credits (0 → refused)   2.27 s

HAND OVER                              not re-timed
 ● the person presses Accept (POST) w5 4.27–5.05 s
 ● two owners read back, one "Owner"  w5  4.68 s
 ● sealed journey wallet opens, 4 chains w5 12.6 s
 ● create a vault it owns, on chain   w5  1.34 s
 ◐ vault move through ONE                 see below
─────────────────────────────────────────────────────
```

The same times as a ladder, one block for every half second
(walk 6 only; the hand-over's `w5` clocks are not drawn):

```
LONGEST TO SHORTEST · seconds, one █ = 0.5 s
═════════════════════════════════════════════════════
 born (provision)   ████████████████████████  12.0
 fade               ███████████               5.29
 wallet get         ████████                  4.10
 mark               ████████                  3.78
 faucet             ███████                   3.66
 verify the send    █████                     2.48
 groups:members     █████                     2.48
 catalog            ████                      1.94
 whoami             ████                      1.89
 market             ████                      1.86
 warn               ████                      1.80
 earn               ███                       1.52
 products:list      ███                       1.43
 sub                ███                       1.41
 re-run, counted    ███                       1.31
 send, final        ██                        1.09
 select             █                         0.64
 doctor             █                         0.53
 usage              █                         0.48
 follow             █                         0.36
 recall             █                         0.33
 key, offline       █                         0.31
─────────────────────────────────────────────────────
```

Born is the median of three (12.00, 12.03, 7.66 s). Against walk 5
the first command is slower (10.0–11.1 s then), `fade` and `wallet
get` a little slower, and everything else the same or faster:
`follow` 0.91 → 0.36 s, `select` 1.13 → 0.64 s, `doctor` 1.04 →
0.53 s, verify 3.07 → 2.48 s.

### What is closed, what is the owner's, what is open

| | State | Why |
|---|---|---|
| Key, wallets, sign-in, make, sell, practise, send | **works** | read back on production, digests below |
| `whoami`, `wallet get` | **published, 5.7.3** | from the journey's folder, no flag: `whoami` 1.89 s names the workspace and says the key is live; `wallet get` 4.10 s returns 0 credits, a 1000-credit ceiling and five addresses |
| `earn` | **published, 5.7.3** | 1.52 s; it reads `storefront:balance` and `credits:balance` (walk 5 found it calling `pay:weight`, which *pays* a task) |
| `catalog` | **published, 5.7.3** | 1.94 s, the receivers printed (it used to read `items`; the door answers `result`) |
| `mark` `warn` `follow` `select` `sub` `fade` `things` | **published, 5.7.3** | the gateway's short paths answer: mark 3.78 s, warn 1.80 s, fade 5.29 s, follow 0.36 s, select 0.64 s, sub 1.41 s, things 0.59 s (walk 5: `/api/mark/…` → 404) |
| `trade` and `wallet` commands | **published, 5.7.3** | the key is read from the journey's folder: `wallet send` is refused as *agent*, by role, in 0.50 s — never as *anonymous* |
| `products:list` with no slug | **published, 5.7.3** | 400 `validation`, field `slug`, in 0.36 s — no 500 |
| `mark` / `warn`, which source is "own" | **a finding, walk 6** | the slug the key answers as (`credits:balance` and `sub` print it: `01a1b0bb…`), not the workspace uuid — the uuid as source is refused `self_deal: cannot move an edge whose source you do not own` (1.48 s) |
| The Accept press | **4.27–5.05 s** (w5) | was projected at 2.2 s; four presses in a row, the same four phases (below); not re-pressed in walk 6 |
| Record the send in ONE's books | the owner's | an agent key cannot write the owner's ledger (`requires the owner role`), answered in 0.50 s |
| `signal` | the server's | `/api/signal` is behind the server secret (401 in 0.27 s); an agent fires the same receivers through `ask` |
| `message` | needs credits | the router's reply costs credits; a fresh agent has 0 (`insufficient_credits`, 2.27 s) |
| `actors` `groups` `paths` `events` as REST | half open | `actors` still answers a Bearer key as *anonymous* (403, 0.31 s); `groups` answers `[]` (1.51 s); `GET /api/events` is not a route; the receivers (`actors:find` 1.83 s, `groups:members` 2.48 s, `signals:list` 1.33 s) answer |
| Vault move, ONE's half | **door made, run waits for a testnet worker** | below |
| The journey wallet's own recovery | **closed** | opened with Touch ID, 12.6 s, 4 of 4 addresses match |

**The press, four times.** 4.59, 4.37, 4.27 and 5.05 s POST on four
fresh journeys. The 302's `Server-Timing` names where it goes, and the
same four phases lead every time: `redeem-grant` 0.97–1.06 s,
`redeem-tail` 0.90–0.98 s, `hook-suspicious` 0.65–0.83 s,
`redeem-user` 0.42–0.52 s. `redeem-tail` is mostly two KV evictions
that a person born in the press cannot need (nothing was cached for a
slug minted in that request); that change is on dev with a test
(`invite-redeem-speed.test.ts`), not yet live. Deferring
`hook-suspicious` (the sign-in anomaly check) was tried and reverted:
it made the landing hang in a test I could not explain, so it stays
awaited until it is understood.

**The vault move, as far as it goes.** The Move half runs on testnet
with keys the agent holds: `create_vault` then `transfer_owner`
([`2n8DvU1e…`](https://suiscan.xyz/testnet/tx/2n8DvU1e1XEGHpafGvAY4hiM1ythGUBXXFh4zNgwGPNS),
[`Wab4XUHs…`](https://suiscan.xyz/testnet/tx/Wab4XUHsgVHJsJusNd81p7qJfECpCR3y59cWwXWK4Vb),
owner read back before and after over gRPC). Then the sealed journey
wallet, opened with Touch ID, created a vault it owns:
[`Hn9UzKKT…`](https://suiscan.xyz/testnet/tx/Hn9UzKKTcPgxsjKB6PFWfu5VbRgsEE2aPgZuT5ZUv5or)
(1.34 s, vault `0x28842c7d…4583`), which is the address the offer
re-reads from the agent's `wallets` row. ONE's half had one door
missing: nothing made an agent its own owner (the only `actor_owners`
writers named a person), so `agent:handover-offer` answered `unclaimed`.
**The ruling, Tony's "you know the answer":** an agent that
`npx oneie` made and nobody adopted claims itself at the moment it
offers its own handover link, by `INSERT OR IGNORE` on `actor_owners`,
only on its own key, only when the offer is `invite`. An existing
owner always wins, and no person or other agent can trigger it.
Committed as `95dbbb838` (143 / 143 in `handover-invite.test.ts`, red
without the change; 214 neighbouring files green).

What still stops the full chain on production is configuration, not
code: `wrangler.toml` sets `NETWORK = "mainnet"`, the vault absorb cron
reads that network's package, and the offer reads a vault on the
network of its `vaults` row or else the worker's. A testnet vault never
gets a row there. So the run that remains is the whole chain on a
testnet-configured worker: offer, the person's Accept, their kept key
signing the Own press, the agent signing `transfer_owner` (the press is
two-phase by design, `agent_signs`), the person pressing again.

## The final score at a glance

The exact steps, in the order they ran on 2026-11-03, and
what each one took. `npx` lines run in an empty `git init`ed
folder (the walk folder); `node .claude/scripts/…` lines run
from the repo root with that folder's paths. `<ws>`, `<ppid>`,
`<inviteUrl>` and the journey's Sui address come from
`.one/journey.json`; `<d>` is the send's digest.

```
WALK 4 · 2026-11-03 · oneie@5.7.2 · one.ie · testnet
═════════════════════════════════════════════════════

 #  STEP · exact command                         TIME
─────────────────────────────────────────────────────
 0  FETCH the package (apart from the run)
    npx -y --prefer-online oneie@latest \
      --version                                2.82 s

 1  KEY · WALLETS · SIGN IN · MAKE
    npx -y oneie@latest --json \
      --name "Agent Path Walk 4"              12.06 s
    → workspace, 5 sealed wallets, shop, product

 2  SELL · a stranger pays with 4242
    node .claude/scripts/agent-path/buy.mjs \
      "https://one.ie/u/<ws>/shop/checkout\
?ppid=<ppid>"                                 14.39 s
    → Stripe receipt cs_test_a1sVbaxS…

 3  COUNT · the same command again
    npx -y oneie@latest --json                 1.28 s
    → sale done on the first read, no wait
    → the owner link is printed

    ══ nothing → counted sale ═════════════ 27.73 s

 4  KEY · offline, network denied
    ONEIE=~/.npm/_npx/<hash>/node_modules/\
oneie/dist/src/index.js    # the 5.7.2 copy
    sandbox-exec \
      -f .claude/scripts/agent-path/nonet.sb \
      node "$ONEIE" key new --out key.json \
      --json --yes-i-accept-plaintext-file   151 ms
    → 0 requests · 24 words in key.json
    (npx itself needs the network, so the
     cached build runs directly)

 5  KEEP · WALLETS · recover + re-derive
    python3 -c "import json;print(json.load(\
open('key.json'))['mnemonic'])" > words.txt
    sandbox-exec \
      -f .claude/scripts/agent-path/nonet.sb \
      node "$ONEIE" key recover --json \
      < words.txt
    node .claude/scripts/agent-path/\
derive-sui-evm.mjs words.txt
    node .claude/scripts/agent-path/\
derive-sol-btc-asi.mjs words.txt
    → all five chains match

 6  FUND · testnet faucet
    npx -y oneie@latest --json wallet faucet \
      <key sui> --chain sui --network testnet  4.92 s

 7  SEND · sign + settle 0.01 SUI
    node .claude/scripts/agent-path/send.mjs \
      words.txt <journey sui> 10000000  final 1.20 s
    → fee 0.001988099 SUI

 8  PRACTISE · read back on production
    curl -s -X POST \
      https://one.ie/api/ask/wallet:rehearse \
      -H "Authorization: Bearer \
$(cat .one/agent.key)" \
      -H 'content-type: application/json' \
      -d '{"data":{"chain":"sui",
        "network":"testnet","digest":"<d>",
        "address":"<key sui>"}}'               1.34 s
    → verified: true

 9  RECORD · the agent key asks to log it
    npx -y oneie@latest --json wallet send \
      <journey sui> --chain SUI --amount 0.01 \
      --unit token --payment-tx <d> \
      --user-address <key sui> \
      --workspace <ws> \
      --key "$(cat .one/agent.key)"            3.35 s
    → refused: requires the owner role

10  HAND OVER · a fresh person presses Accept
    node .claude/scripts/agent-path/accept.mjs \
      "<inviteUrl>"
    → lands on /onboarding/<ws> · 2 owners
    or, no browser, the server's own clock:
    curl -s -D - -o /dev/null -X POST \
      "<inviteUrl>" -H 'Origin: https://one.ie' \
      -H 'Sec-Fetch-Site: same-origin' \
      -H 'content-type: application/x-www-form-\
urlencoded'          # read Server-Timing
─────────────────────────────────────────────────────
```

The hand-over is the slowest moment a person sees. Its final
score on production, and what the open cut brings:

```
ACCEPT → LANDED · production, final
═════════════════════════════════════════════════════

 live now · main 3705eadbc               7.11 s
 ███████████████████████████████████
 POST /join → 302  6.37 s  ·  page 0.61 s
 "Name your workspace" ready             7.91 s

 press cut live · 2026-11-05            4.59 s POST
 ███████████████████████
 one curl press, Server-Timing data 4431 ms
 was projected ≈ 2.2 s POST · wrong, see below
─────────────────────────────────────────────────────
 target: under 3 s · not met
```

### Second by second: what each person gets, and can do

Clocked on production on 2026-11-03. The agent's first
command was timed by watching the files it writes into `.one/`
(run 4h, 9.76 s; the same command took 12–14 s on other runs).

```
THE AGENT · one command, from nothing
═════════════════════════════════════════════════════
  0.0 s  types `npx -y oneie@latest`
  0.5 s  npx has started oneie
         … the screen stays blank until 9.8 s …
         POST /api/provision/agent: 6.1–8.9 s on
         the server, the longest wait on the path
  7.2 s  GETS  an API key (.one/agent.key, 0600)
               a workspace of its own
               the owner link, minted now or never
               a .gitignore so the key never commits
         CAN   call ONE's receivers as an agent
  7.7 s  GETS  a wallet sealed in Apple Keychain:
               Sui · EVM · Solana · Bitcoin · ASI
  8.4 s  GETS  the wallet registered by proof
               (it signed a server challenge)
  8.7 s  GETS  a shop, on, in test money
  9.3 s  GETS  a product on sale, 1.00 USD, a link
         CAN   send anyone that link to pay
  9.8 s  the command answers, all lines at once

THE BUYER · opens the product link
═════════════════════════════════════════════════════
         sees the checkout, presses Continue
         CAN   type the card (4242 4242 4242 4242)
         presses Pay
+14.4 s  GETS  "Payment received" + a receipt
         (the whole visit, a headless browser's
          cold start included)

THE AGENT · runs the same command again
═════════════════════════════════════════════════════
 +1.3 s  GETS  the sale, counted from the webhook
               the owner link, printed to hand on
         CAN   hand the business to a person
  27.7 s from nothing to a counted sale

THE AGENT · its own key, on chain (testnet)
═════════════════════════════════════════════════════
  0.15 s GETS  a key made with the network off,
               24 words to keep on paper
  4.9 s  GETS  0.05 test SUI from the faucet
  1.2 s  CAN   send 0.01 SUI: final on chain
  1.3 s  GETS  ONE's read-back: verified: true
  3.4 s  is told why it cannot record the send
         on the owner's books: the owner role

THE PERSON · opens the owner link
═════════════════════════════════════════════════════
  0.4 s  sees "You have been invited. Press Accept
         to join. Nothing happens until you do."
         (a link scanner's GET spends nothing)
         presses Accept
  7.1 s  GETS  an account, signed in, no password
               the owner seat beside the agent
               named "Owner", not an invite id
         lands on "Name your workspace", the
         agent's name already filled in
  7.9 s  the page is ready to type into
         4.6 s POST after the press cut (2026-11-05)
         CAN   name it, and own everything above
─────────────────────────────────────────────────────
```

Two of those waits are blank screens: the agent's first 9.8 s
(the CLI prints only at the end) and the person's 7.1 s after
Accept. The second is cut in PR #524; the first is the next
walk's (§ The next walk).

---

---

## The path

An agent with nothing opens a terminal and types one command. Within
ten to fourteen seconds it has a key, five wallets, a shop and a
product on sale. A test card pays, and **27.7 seconds after the first
keystroke the sale is counted**. The agent hands the business to a
person with one link, and sends money on Sui with a key nobody else
ever saw: final in 1.2 seconds.

That is the claim on the home page. This file is the receipt. Every
number below is the final score: walk 4, run on 2026-11-03 against
production (`one.ie`, `oneie@5.7.2` from npm, Sui testnet) and read
back from the chain or the server, never from our own notes. The
walks before it, and what each one fixed, are one line each in
§ History.

The keys printed here are **throwaway testnet keys**, made for this
walk and holding test SUI. They exist so you can check every
derivation yourself. Never put a real key in a document.

```
              nothing
                 │
   $ npx oneie   ▼
          ┌─────────────┐
          │ 1  KEY      │  151 ms · 0 requests
          └──────┬──────┘
                 ▼
          ┌─────────────┐
          │ 2  KEEP     │  24 words · sealed
          └──────┬──────┘
                 ▼
          ┌─────────────┐
          │ 3  WALLETS  │  five chains, one key
          └──────┬──────┘
                 ▼
          ┌─────────────┐
          │ 4  SIGN IN  │  a key, no password
          └──────┬──────┘
                 ▼
          ┌─────────────┐
          │ 5  MAKE     │  on sale at 9.3 s
          └──────┬──────┘
                 ▼
          ┌─────────────┐
          │ 6  SELL     │  counted at 27.7 s
          └──────┬──────┘
                 ▼
          ┌─────────────┐
          │ 7  PRACTISE │  verified · 1.34 s
          └──────┬──────┘
                 ▼
          ┌─────────────┐
          │ 8  SEND     │  0.01 SUI · 1.20 s
          └──────┬──────┘
                 ▼
          ┌─────────────┐
          │ 9  HAND     │  one link · 2 owners
          │    OVER     │  7.11 s
          └──────┬──────┘
                 ▼
       a person with a business
```

---

## The scoreboard

| Stop | Final score | Proven by |
|---|---|---|
| 1 Key | **● 312 ms**, 0 requests (walk 6; 105 ms inside the CLI's own receipt) | network-denied sandbox, the published 5.7.3 |
| 2 Keep | **● walk 6**: the words recover the key offline in 284 ms | the sealed journey wallet opened with Touch ID (12.6 s, walk 5) and gave back the registered Sui, EVM, Solana and Bitcoin addresses |
| 3 Wallets | **● all five** (walk 6, again) | re-derived with code ONE did not write |
| 4 Sign in | **● key at 7.2 s** (walk 4) | `POST /api/provision/agent`; the whole first command 7.66–12.03 s in walk 6 |
| 5 Make | **● on sale at 9.3 s** (walk 4) | `products:create` → pid; `products:list` reads it back in 1.43 s (walk 6) |
| 6 Sell | **● counted on the first re-run, 1.31 s (walk 6; 1.28 s walk 4)** | Stripe `cs_test_a1hOcyRy…` + `storefront:stats`, purchases 1 |
| 7 Practise | **● verified, 2.48 s and 1.77 s (walk 6; 3.07 s walk 5)** | `wallet:rehearse` over Sui GraphQL |
| 8 Send | **◐ final 1.09 s (walk 6); the record is the owner's, refused in 0.50 s** | digest on Suiscan; the owner records it |
| 9 Hand over | **● press 4.27–5.05 s (walk 5, four presses), "Owner" read back** | `/join` → 302, `groups:members`; the vault move is ◐ |

● works and was read back · ◐ half: one leg proven, one leg named.

---

## The keys (throwaway, testnet only)

**The agent key**, made under a macOS sandbox that denies every
network call:

```
melody health leaf door either dad radar hat
recall inherit verb various assume pelican ugly
airport wasp gesture leg depart riot public
skill patrol
```

| Chain | Address (derivation v2, standard paths) | Re-derived by |
|---|---|---|
| Sui | `0xfc587eb21ed077bdc62d137a7825532831043e17b8c2f8b8f11c6f98923b9a50` | `@mysten/sui` ✓ |
| EVM | `0xdFab4fE6080a68f88B36f77cf6eaec54797e606E` | BIP-32 + keccak ✓ |
| Solana | `31mEjGZcjcNF6QAnMrPNHs6umAEMxBcbezr6UafE4wRo` | SLIP-0010 (Mysten) + ed25519 ✓ |
| Bitcoin | `bc1q24vh2julut7yz6rkphdhrx2s5t2ms6568hrkdm` | BIP-84 + hash160 + bech32 ✓ |
| ASI | `fetch17ccey9cs02gjlfsqzmqyctfhuu0277hljpf9je` | BIP-44 coin 118 + bech32 ✓ |
| Identity | `rSNqnDzdRZ6ioxT1kz6qt8Ui0U-N0gyafx_7Kp6yHSc` | |

**Walk 6's agent key**, made the same way on 2026-11-06 with the
published `oneie@5.7.3` (312 ms, 0 requests), recovered from these
words offline in 284 ms, and re-derived to the same five addresses
by the two scripts above. It holds 0.038 test SUI after the send.

```
riot impulse holiday equip alien fringe about
begin anchor behind rate much cancel burst
front animal fine select appear very shy hire
include lawsuit
```

| Chain | Address (derivation v2) | Re-derived |
|---|---|---|
| Sui | `0xb619d1be78c61850343d63d2e916da23eaeb574e69481a0e3c27f161eba6c0b6` | ✓ |
| EVM | `0xd421575DBfFb0dfF77E551d109eC1C5f31BE6264` | ✓ |
| Solana | `2CPZi2STbmNKjYwLW5smBTwSA4UWqsRdJBFgrM94Ax7b` | ✓ |
| Bitcoin | `bc1qkzqxgzjfd5mfdkchn8u2yrsvjp49s358nfjv3h` | ✓ |
| ASI | `fetch1amc6fh78ufh24n89cgqgusww4587pduc97ldnj` | ✓ |
| Identity | `H4gWmD_8YebkImrrU9SKWVViuoN5iVG7RrQVCLI_feA` | |

Its journey (workspace `1f61b647-01bc-4102-b9cb-aca90f9497d2`)
sealed a wallet whose Sui address is
`0x5654eed91fb00ca984f48a16590cd451f5c822d90a324f87df886200ec2664d1`;
that is where the 0.01 SUI went.

**The journey wallet** that `npx oneie` sealed is a different kind of
key: its 24 words were never printed, because the journey never holds
them where they could print (`packages/cli/src/lib/journey.ts`, "THE
WORDS NEVER REACH THIS PROCESS'S STDOUT"). Only its addresses are
public. Workspace `7b902c6f-0e4e-49c7-85a1-55e4f60f6add`:

| Chain | Address |
|---|---|
| Sui | `0xb26cd6dd9e9a02763edb66a84b686be37a5f0ed9c77cd3e587c19d69c1221b10` |
| EVM | `0x230e10Df55202Ea7B3Ee035A227eFf4f01fEcad4` |
| Solana | `2NjU8T4CmrnNgHb3PHuwqnp1As1sCZHLmySxPPYPyjd5` |
| Bitcoin | `bc1qeav5tzuqc8zy0v0lzc2hkfyutwh4dyzh0anywe` |
| ASI | `fetch15gxhueg6l0uf73m7c92h0j7qvjmuzhnhf5mfuy` |

The API key the journey minted is a live production credential, so
only its shape is printed: `one-…`, in `.one/agent.key` at 0600 behind
a `.gitignore` the CLI wrote first.

---

## Stop by stop

### 0 · One command

```
$ npx -y oneie@latest --json --name "Agent Path Walk 4"
{"ok":true,
 "workspace":"7b902c6f-0e4e-49c7-85a1-55e4f60f6add",
 "steps":[{"step":"key","status":"done",…},
          {"step":"products","status":"done",…},
          {"step":"sale","status":"pending",…},
          {"step":"handover","status":"waiting",…}],
 "next":"pay with the test card at the link above,
   then run `npx oneie` again — it waits for the
   sale to land (or `npx oneie --wait 30` …)"}
                                               12.06 s
```

Fetching the package from npm took 2.82 s on its own
(`--prefer-online --version`); once cached, npx starts `oneie` in
0.5 s. The journey's run time moves by a second or two between
runs: 12.06 s here, 9.76 s, 13.79 s and 13.81 s on others that day.

Watching the files it writes into `.one/` shows where the time goes
(the 9.76 s run): the key and the owner link land at 7.2 s, the
sealed wallet at 7.7 s, its registration at 8.4 s, the shop at 8.7 s,
the product at 9.3 s. Most of that is one server call:
`POST /api/provision/agent` answered in 6.10 s and 8.93 s of worker
time on two curl probes. And the CLI prints every line only when it
finishes, so for those seconds the agent sees nothing.

Bare `npx oneie` talks to the network: it has to, to open a shop.
The "0 requests" claim belongs to stop 1's own command, and nowhere
else.

### 1 · Key: made where nobody can see it

```
$ sandbox-exec -f nonet.sb \
    node "$ONEIE" key new --out key.json --json \
    --yes-i-accept-plaintext-file

"receipt": { "lane": "agent", "tookMs": 151,
  "requests": 0, "counted": { "connections": 0,
  "dnsLookups": 0, "datagrams": 0 },
  "computer": { "chip": "Apple M5", "cores": 10 } }
```

The sandbox profile is three lines, `(version 1) (allow default)
(deny network*)`. Inside it the key took **151 ms**, opened **no
socket, made no DNS lookup and sent no datagram**. The words went to
`key.json` at 0600 and never to stdout. `$ONEIE` is the npx cache's
`oneie@5.7.2/dist/src/index.js`: npx itself needs the network, so the
cached build runs directly.

### 2 · Keep: the words bring it back

```
$ sandbox-exec -f nonet.sb \
    node "$ONEIE" key recover --json < words.txt
"v2": { "addresses": { "sui": "0xfc58…9a50",
  "evm": "0xdFab…606E", … } }
```

Recovery ran with the network denied and returned the same five
addresses. The words came in on stdin; the CLI refuses them on argv,
where `ps` would show them. The journey's own wallet is sealed with
the Keychain instead: `.one/wallet.json` holds an argon2id-wrapped
ciphertext, and the wrapping secret sits in the Keychain with no app
pre-trusted, so every read asks for Touch ID. That wallet was sealed
and its addresses registered, but it was not opened, so its own
recovery is claimed by the code, not proven here. Walk 5 repeated the
key half: `key new` 351 ms with the network denied, `key recover` from
the words gave the same identity, and Mysten / BIP-44 / SLIP-0010 code
re-derived Sui, EVM, Solana and Bitcoin to the same four addresses.
Opening the sealed wallet is one command that only Tony's Touch ID
completes: `npx oneie wallet paper` in the walk folder.

### 3 · Wallets: one key, five chains, checked by someone else

ONE's word that the addresses are right is not proof. So all five
were derived again from the words with code ONE did not write
(`derive-sui-evm.mjs`, `derive-sol-btc-asi.mjs`):

| Chain | Path | Derived by | |
|---|---|---|---|
| Sui | `m/44'/784'/0'/0'/0'` | `@mysten/sui` `deriveKeypair` | ✓ |
| EVM | `m/44'/60'/0'/0/0` | `@scure/bip32` + keccak | ✓ |
| Solana | `m/44'/501'/0'/0'` | Mysten's SLIP-0010 + ed25519 + base58 | ✓ |
| Bitcoin | `m/84'/0'/0'/0/0` | BIP-32 + hash160 + bech32 `bc` | ✓ |
| ASI | `m/44'/118'/0'/0/0` | BIP-32 + hash160 + bech32 `fetch` | ✓ |

The re-derivation is our own short script over the public paths,
using the same audited primitives (`@noble`, `@scure`) but none of
ONE's wallet code. Any BIP-39 wallet that loads the 24 words above
with no passphrase will show the same five addresses.

### 4 · Sign in: a key, never a password

The journey's first network call is `POST /api/provision/agent`. It
answers with a workspace, a workspace key, a uid-bound registration
key and a one-time owner link, and every later call is
`Authorization: Bearer one-…`. No person, no password, no email. The
key is saved to `.one/agent.key`, and the CLI writes the `.gitignore`
line before the key, so a stray `git add` cannot catch it.

### 5 · Make: a product with a price

`storefront:enable` with `testMode: true`, then `products:create`
with `{ name: "Test product", prices: [{ unit_amount: 100 }] }`. The
answer carries a pid and a ppid, and the journey writes both to
`.one/journey.json` before moving on, so a re-run never makes a
second product:

```
pid  prod_whnihecd1f8oegoi
ppid price_6fn6bpgs3c7xomq2
url  https://one.ie/u/7b902c6f-…/shop/
       prod_whnihecd1f8oegoi
```

### 6 · Sell: a stranger pays, the agent counts it

A headless browser played the buyer: open the checkout, press
Continue to payment, fill in the 4242 test card in Stripe's embedded
form, press Pay. **14.39 s** around the whole script, Chromium's cold
start included.

| | |
|---|---|
| Stripe session | `cs_test_a1sVbaxS0IbxIoHFa6hV0u3YUY4AdWLVt9EPWvTPhkNiC6LcctexZy2ETe` |
| Order | `ord_cn35l3jb2yd65kgt` · $1 · test money |

Then the agent ran the same command again, straight after the
receipt:

```
$ npx -y oneie@latest --json
{"step":"sale","status":"done",
 "detail":{"purchases":1,"read":"storefront:stats"}}
{"step":"handover","status":"done",
 "detail":{"link":"https://one.ie/join?token=…",
   "note":"anyone holding this link can claim the
     owner seat … It works once and lasts 7 days"}}
                                                1.28 s
```

A printed checkout link is not a sale. The step turns done only when
`storefront:stats` reads a purchase back, and that count comes from
the Stripe webhook, never from the page's beacon. `oneie@5.7.2` waits
up to 20 s for a pending sale by itself; here the webhook had
already counted it, and the first read saw it.

**Nothing → counted sale: 27.73 s** (12.06 + 14.39 + 1.28), with no
second command waiting. The home page holds itself to "press → paid
under 30 s".

### 7 · Practise: test money in, read back from the chain

The faucet, through ONE:

```
$ npx -y oneie@latest --json wallet faucet \
    0xfc58…9a50 --chain sui --network testnet
"message": "SUI dispensed from ONE treasury (public
            faucet was unavailable).",
"txHash": "6mtz6oPGXMvPqLFTUqU6nPoc21z6Wx3q1pESkApiExz6",
"amount": "0.05 SUI", "source": "treasury_fallback"
                                                4.92 s
```

Mysten's public testnet faucet was down, so ONE's own treasury
(`0x2705…4dec`) paid, settled at checkpoint 402,336,857.

Then `wallet:rehearse`, ONE reading a testnet digest back so the
agent can say what happened on chain. With the journey's agent key as
Bearer (an anonymous call is refused at the edge, `403 direct
substrate access not permitted`):

```
prod  { "verified": true, "credits": 0,
        "amount": "-0.011988099 SUI · testnet",
        "sender": "0xfc58…9a50",
        "explorerUrl": "…/testnet/tx/63mr5SjR…" }
                                                1.34 s
```

It reads Sui GraphQL; every public Sui host has retired JSON-RPC.

### 8 · Send: the key signs, the chain settles

The agent's key signed a plain transfer of 0.01 SUI to its journey
wallet and broadcast it (`send.mjs`, over gRPC). ONE's CLI never
signs. The key stays on the machine that made it.

| | |
|---|---|
| Digest | [`63mr5SjRFxX8hNPyWx47pATMN1d7WPPKDFEjdegKKbJ4`](https://suiscan.xyz/testnet/tx/63mr5SjRFxX8hNPyWx47pATMN1d7WPPKDFEjdegKKbJ4) |
| Checkpoint | 402,336,899 |
| Settled (UTC) | 09:52:47.476 |
| Executed | 726 ms |
| Final | **1,200 ms** |
| Arrived | 0 → 0.01 SUI |
| Network fee | 0.001988099 SUI |
| ONE fee | 0 |
| Read back on prod | ✓ 1.34 s |

The fee line, from the chain: computation 1,000,000 MIST + storage
1,976,000 − rebate 987,901 = **1,988,099 MIST**. ONE takes nothing;
Sui charges its own small fee in SUI, which is why the home page says
"ONE takes no fee" and never "no gas".

**ONE's record of the send is refused, by design.** The agent asked
ONE to log it, with the agent key:

```
$ npx -y oneie@latest --json wallet send \
    0xb26c…1b10 --chain SUI --amount 0.01 \
    --unit token --payment-tx 63mr5SjR… \
    --user-address 0xfc58…9a50 \
    --workspace 7b902c6f-… --key "$(cat .one/agent.key)"
{ "ok": false,
  "error": "wallet:send → failure: forbidden ·
    requires manage_workspace · you are agent —
    Requires the owner role in the target
    workspace." }                               3.35 s
```

The refusal is right: an agent key cannot record a payment on the
owner's books. The money moved; ONE's ledger of it waits for the
owner, and the answer says so.

Walk 5 found that the published CLI did not send the key at all from
the journey's folder, so the server answered *you are anonymous*,
not *you are agent*. With the fix (dev) the same command is refused
by role, which is the honest answer: `you are agent — Requires the
owner role in the target workspace`. The agent's own lane for this
stop is `wallet:rehearse`: production reads the chain and answers
`verified: true` (walk 5, digest
[`PgJHH98J…`](https://suiscan.xyz/testnet/tx/PgJHH98JbKkkWGmyzXVL3jmArbpyxJykiLgMFwrDjaJ),
checked 3.07 s, final 1.20 s, fee 0.001988099 SUI). Whether an owner
should be able to grant an agent the ledger write on testnet is a
ruling, not a bug.

Walk 6 ran both halves on the published `oneie@5.7.3`. The faucet
paid 0.05 SUI from the treasury in 3.66 s
([`8os43aaX…`](https://suiscan.xyz/testnet/tx/8os43aaXW1Cyw31Bh751Si6PLMbhWaKc9wEMoUNkgB4H));
the key signed 0.01 SUI to its journey wallet, executed in 718 ms
and final in **1,087 ms**, fee 0.001988099 SUI again
([`GpR8hRRn…`](https://suiscan.xyz/testnet/tx/GpR8hRRne6yYXkAcsqKJ9vLHk79kZdDfjwrCJhyRErWB));
production read it back `verified: true` in 2.48 s, then 1.77 s on
a second ask (anonymous: 403 in 0.10 s). The record, asked from the
journey's folder with no `--key` and no `--workspace`, was refused
by role in 0.50 s — *you are agent*, the published door now sending
the key it finds beside it.

### 9 · Hand over: one link, used once

The owner link was minted at birth, because an agent key cannot mint
one afterwards. A fresh browser opened it:

```
GET  /join?token=…   "You have been invited. Press Accept
                      to join. Nothing happens until you
                      do."                       0.4 s
POST Accept          (redeemed)
POST Accept again    "Invite already used."
```

The GET spends nothing, so a mail scanner that prefetches the link
cannot claim the seat. The first press spends it; the second is told
so.

Accept landed the browser at `one.ie/onboarding/<ws>`, signed in as a
new person, on "Name your workspace". Read back by the agent's key:

```
groups:members  group:<ws>
  <the agent>   owner
  Owner         owner     the person
```

The final score on production (main `3705eadbc`), split per request
by `accept.mjs`:

```
Accept → landed                 7.11 s
  POST /join → 302 headers      6.37 s   ← the server
  GET  /onboarding/<ws>         0.61 s   ← the page
  "Name your workspace" ready   7.91 s
curl, same press, no browser    worker data 6,551 ms
```

The Layout's client router turns the Accept form into a `fetch` POST
plus a page swap, so the press is not a document load; the script
logs every request after it.

**The 6.4 s is nine TypeDB trips in a row**, about 0.73 s each from
the production worker. The redeem now names its steps on the 302's
`Server-Timing` (`redeem-*`, `hook-*`, `land-group`). On
`localhost:4321`, which runs the tree against the production
substrate at about 0.4 s a trip, the session hook was 3.0 s of a
4.0 s press: it read the actor twice, asked a brand-new person which
org they rank highest in, and built their personal workspace before
the invite seat. PR #524 keeps every write and drops or moves the
rest:

- **A person born in the press is written, never read first.** Their
  slug, which is the actor's `aid`, was minted in this request;
  `aid` is `@key`, so the schema refuses a duplicate.
- **They are not asked their highest org.** With an unproven mailbox
  they can belong to none yet: domain auto-join needs a proven one,
  and the invite seat comes after the hook. The landing write still
  happens.
- **Their personal workspace finishes after the 302**, through
  `waitUntil`. The person lands on the agent's workspace, not their
  own, and the session hook heals a missing personal workspace on
  the next sign-in. Read back afterwards, four of four were there,
  each with its owner seat.

```
the press after PR #524         1.1–2.0 s on localhost
  W actor → R seat → W seat       3 trips in a row
  personal group + seat           after the 302
production, measured 2026-11-05  4.59 s POST (one press)
```

**Measured, and the projection missed.** The press cut is live
(the 302 carries `Server-Timing`). One curl press on a fresh
journey (walk 5, 2026-11-05) took 4.59 s; the projection from
trip counts said ≈ 2.2 s. The 302's own phases add to 4431 ms:

```
redeem-grant      1064 ms     hook-actor      760
redeem-tail        947        hook-suspicious 686
redeem-user        436        land-group      180
hook-user          120        redeem-spend     77
hook-group          75        redeem-verify    49
redeem-claim        37        (others 0)
```

Four phases are 3.5 s of it: `redeem-grant`, `redeem-tail`,
`hook-actor` and `hook-suspicious`. The code makes three TypeDB
trips in a row, but the phases above are not three trips of
0.73 s; read what each one waits on before cutting. One press is one
sample — walk 5 repeats it before this is called a floor.

Red first: ledger tests in `invite-redeem-speed.test.ts` (actor reads
→ 0, the `select $gid, $role` read → 0, and a press that answers
while every personal-workspace trip is held, which times out at
3.6 s with the old `await` put back), and one for `withTiming`, which
used to *erase* a route's own `Server-Timing` entries. The 14 redeem,
hook and perf files: 101 / 101, three runs in a row; `tsc` 0.

PR #524 is merged to main; its release was held at gate 1 by two
unrelated reds (a new `/film` folder unclassified, and the seal
page's input hash after an SDK re-copy), fixed in PR #525. It is
live: a press on 2026-11-05 returned the `redeem-*` phases.

What this stop does **not** prove: the vault move the home page draws
at stop 9 (`transfer_owner` on a Sui vault). The `npx oneie` path
hands over the workspace's owner seat. The on-chain owner move is a
separate door that this walk did not run.

---

## The clocks

| Clock | Final score |
|---|---|
| `npx oneie`, nothing → product, walk 6 (published 5.7.3) | 12.00 / 12.03 / 7.66 s |
| npx start, cached, walk 6 | 0.48 s (manifest re-check with the tarball cached: 0.84 s; no cold fetch timed) |
| re-run after the sale, walk 6 | 1.31 s (before the sale it waits its 20 s by design: 20.86 s; `--wait 0` reads once, 1.50 s) |
| buy page → "Payment received", walk 6 | 15.90 s ¹ |
| **nothing → counted sale, walk 6** | **29.21 s** (12.00 + 15.90 + 1.31) |
| key, network denied, walk 6 | 312 ms wall (105 ms inside) |
| key recover from 24 words, offline, walk 6 | 284 ms |
| faucet, command → coin, walk 6 | 3.66 s |
| send, sign → final, walk 6 | 1.087 s (executed 718 ms) |
| `wallet:rehearse`, walk 6 | 2.48 s, then 1.77 s (anonymous: 403 in 0.10 s) |
| record the send with the agent key, walk 6 | refused by role, 0.50 s |
| fetch `oneie@latest` from npm | 2.82 s |
| npx start, cached | 0.5 s |
| key, network denied | 151 ms |
| `POST /api/provision/agent`, worker time | 6.10–8.93 s (walk 4) |
| `npx oneie`, nothing → product, walk 5 | 10.03 / 10.70 / 11.09 s (15.51 s with a cold npx fetch) |
| re-run, read sale + mint hand-over, walk 5 | 1.62 s |
| key, network denied, walk 5 | 351 ms |
| send, sign → final, walk 5 | 1.20 s (executed 811 ms) |
| `wallet:rehearse`, walk 5 | 3.07 s (anonymous: refused in 0.14 s) |
| `npx oneie`, nothing → product on sale | 9.76–13.81 s (12.06 s on the timed walk) |
| Buy page → "Payment received" | 14.39 s ¹ |
| re-run, read sale + mint hand-over | 1.28 s |
| **nothing → counted sale** | **27.73 s** |
| faucet, command → coin | 4.92 s |
| send, sign → final | 1.20 s |
| `wallet:rehearse` read-back | ✓ 1.34 s |
| record the send with the agent key | refused with the reason, 3.35 s |
| hand-over, Accept → landed | 7.11 s (walk 4); not re-measured |
| hand-over, the POST alone | 4.27–5.05 s ² (6.37 s at walk 4) |

¹ The buyer is a headless browser started for the occasion, so this
clock includes Chromium launching and Stripe's iframe loading cold.
² Four curl presses, 2026-11-05, after the press cut shipped. Projected
at ≈ 2.2 s from 0.73 s a trip; the phases ran longer (see the stop).

---

## What changed to get here

Each fix went in red first: a test that failed on the old code, then
the change, then the test green.

| Fix | Commit |
|---|---|
| `wallet:rehearse` reads Sui GraphQL (every public host retired JSON-RPC); SUI matched in either coin spelling; a mistyped digest says `invalid_digest` | `e783bb594` |
| `npx oneie --json` runs the journey instead of printing help; `next:` names `npx oneie`; a refused send carries its reason | `c6430a015` |
| The Analytics pane and its "What agents did · npx oneie" funnel | `7a85abb30` |
| The journey waits up to 20 s for a pending sale by itself | `b7f81a2cc` (5.7.2) |
| The hand-over's subdomain registration and workflow triggers run after the 302; the person is "Owner" | `d1b8e66a5` (PR #523) |
| The Sui readers on the path (`/w` send, pay's SUI escrow, the activity feed) off JSON-RPC | `199b2ce6f` (PR #523) |
| The press: 3 TypeDB trips in a row; the personal workspace after the 302; each step on `Server-Timing` | `8579eadc6`, `ead35a528` (PR #524) |

---

## Is there a workflow the agent follows?

Yes, and until today nothing counted it. The path is code, not a
workflow row: `runJourney` in `packages/cli/src/lib/journey.ts` walks
key → products → sale → handover, saving what each step proved to
`.one/journey.json` so a re-run resumes rather than repeats. On the
server, the only lifecycle rows it writes are `registered` and
`bootstrapped` on the platform's `agent-onboarding` definition.
`trackLifecycle` still has no caller.

Nothing new had to be emitted to see it, because every step already
leaves a row the server writes when the thing happens:

```
 Got a key        world_keys  label 'provision-reg'
      │
 Sealed a wallet  wallets     actor, kind agent, sui
      │
 Opened a shop    owners      storefront_enabled = 1
      │
 Made a product   products    workspace
      │
 First test sale  storefront_events  'purchase'
      │
 Handed over      invites     owner, accepted_at set
```

---

## The analytics, on the front page

Open `one.ie` as the platform's owner or staff, then open the chat
panel. Next to Chat there is now an **Analytics** tab, the page in view
as a funnel:

- **People and agents along the nine stops** (what they *saw*): distinct
  visitors per stop, by page, film or chat.
- **What agents did · npx oneie** (new): the six steps above, each
  counted from its row.

On `localhost:4321` (a local copy of the data, not production numbers)
it read:

```
 WHAT AGENTS DID · NPX ONEIE        30 days
 Got a key        ████████████████████  9
 Sealed a wallet  ███████               3  ← biggest loss
 Opened a shop    ███████████           5
 Made a product   ███████████           5
 First test sale  █████                 2
 Handed over      █████                 2
```

Three things to read correctly. "Got a key" counts every caller of
`/api/provision/agent`: bare `npx oneie`, `init`, `onboard` and keyless
`setup`, not the journey alone. A step can exceed the one before it,
because older agents opened shops before wallets were sealed by proof;
the funnel shows the rows as they are. And these agents are not the
same group as the visitors in the first funnel: provisioning records
no visitor hash, so the two are drawn apart and never joined.

Only the platform workspace reads this series. Any other workspace's
owner gets their own page's funnel and no `did` block.

---

## The next walk: what is left

In the order a stranger would feel it:

1. **Published — `oneie@5.7.3`, 2026-11-06.** Walk 6 ran every door
   on the published build (table above). What it left: the cold
   `npx` fetch was not timed (the tarball was already cached), the
   first command was 12.0 s on two of three runs, and `mark`/`warn`
   want the key's own slug as source, which nothing prints before
   the first refusal — `whoami` should say it.
2. **Ship the eviction cut and read `redeem-tail` again.** Expected
   to drop by most of its 0.9–1.0 s; then `hook-suspicious`
   (0.65–0.83 s) is the next, and needs its hang understood first.
3. **The agent's first command, 10 s on one server call.** The CLI
   prints every line at the end; print each step as it lands, and
   time `POST /api/provision/agent` per step on `Server-Timing`.
4. **Give an agent the REST reads it is entitled to.** `actors`,
   `groups`, `paths` answer a world key as anonymous. Either the
   CLI uses the receivers (`actors:find`, `groups:members`,
   `signals:list`) or the export routes accept the key.
5. **The vault move through ONE, whole.** The self-claim door is
   made (`95dbbb838`) and the sealed wallet created its vault; what
   remains is one run on a testnet-configured worker (production is
   `NETWORK = "mainnet"`) with a headless person holding a kept key
   for the Own press and the agent signing `transfer_owner`.
6. **Stop 2** is closed: the sealed wallet opened.
7. **Production analytics** still unread by a walk.

---

## What this walk does not claim

- **Mainnet.** Everything here is Stripe test mode and Sui testnet.
  No real money moved, by Tony's ruling of 2026-10-22.
- **A cold npm fetch.** Walk 6's CLI clocks ran the published
  `oneie@5.7.3`, but its tarball was already in npm's cache when the
  walk began (0.84 s to re-check the manifest), so no cold-fetch clock
  was taken that day; walk 4's 2.82 s stands.
- **The hand-over, re-timed.** Nobody pressed Accept in walk 6 (a
  press makes a person on production), so the 4.27–5.05 s presses
  and the "Owner" read-back are walk 5's. The eviction cut on dev was
  therefore not read either way.
- **The vault move through ONE.** The Move calls and the sealed
  wallet's own vault ran; the offer and the person's Own press did
  not, because production is a mainnet worker (above). The self-claim
  that unblocks the offer is tested, and ships with the next release.
- **Production analytics.** The panel is live on one.ie; its numbers
  are read only by the platform's owner, so this file quotes none.

---

## History

Every walk before this one, in a line. The numbers above replace
theirs; the full receipts are in git (`git log -p text/agent-path.md`).

| Date | Walk | What it found and what it moved |
|---|---|---|
| 2026-11-07 | **9** · the follow-ons | **Closed on production** (§ below): a key-holder reads its own balance at the x402 gate (402 → 200), `message` from a born workspace answers (persona installed on use), a run on faucet credits burns as test money (`test_mode 1`). Found: the routed persona never saw the question as the user turn — fixed `5ced5b949`, shipped `0c0dda4b`: `message` then answered in one sentence, 7.27 s. |
| 2026-11-07 | **8** · can an agent buy? (after the testnet ship) | **Buys — credits with test money, and a model call with them; a trade with another agent waits for a human's grant, by design** (§ below). Two agents born (10.91 s, 8.96 s); faucet 3.14 s; the 402 names the verifier's treasury `0x9009…765d` with `test_headroom_credits 1000`; the first payment (`DbZd1S4t…`, final 932 ms) verified and was refused `workspace_not_found` — the key's purse was an actor id with no `owners` row (fixed in #547, shipped 721c1a6b); the second (`GvAn8Evf…`, final 1.27 s) granted **10 credits**, `source=faucet`, `test_mode=1`; replay `new:false`, B refused `409 tx_already_granted`; `agent:run` on a persona A published itself: grok-4.5, 8.79 s, **3 credits, balance 10 → 7**; `market:offer → accept` to ESCROW, `market:escrow` with a contract → `grant_required` naming the owner's `agents:approve` |
| 2026-11-07 | **7** · can an agent buy? | **Does not yet buy — it stops at the first credit** (§ below). Two agents born (17.15 s, 7.14 s); a stranger paid A in 14.57 s and A's credits stayed 0 (test money grants nothing); `credits:request` → `no_funder`; the x402 quote was issued and paid on chain (`EiLtuai8…`, 23,512,866 MIST) and refused `payment_not_verified` — one.ie's quote names `owners.treasury_sui 0xa8e3…`, pay verifies `TREASURY_SUI 0x9009…`, both workers mainnet; `market:escrow` / `checkout:create` are `contract_required` for an agent even with a contract (the edge strips the fields); `wallet:transfer` / `wallet:send` need the owner; `pay:weight` → `quote_failed:404`; 0.01 SUI A→B on chain final 1.34 s (`3hcUuqsG…`), B verified it, ONE's ledger `[]`; `message` / `agent:run` → `insufficient_credits`; `credits:spend` at 0 wrote a row: balance −2 |
| 2026-11-06 | **6** · `oneie@5.7.3` published | The six doors confirmed on the published build. Born 12.00 / 12.03 / 7.66 s (three runs), a stranger paid in 15.90 s, the re-run counted it in 1.31 s: nothing → counted sale 29.21 s (27.73 s at walk 4). Key 312 ms offline, recovered in 284 ms, five chains re-derived. Faucet 3.66 s (`8os43aaX…`), send `GpR8hRRn…` final 1.09 s, verified 2.48 s, the record refused by role in 0.50 s. `mark`/`warn` take the key's own slug as source, not the workspace uuid. The hand-over not re-pressed |
| 2026-11-05 | 5 · `oneie@5.7.2` + dev CLI | The capability map above. Four presses on production, 4.27–5.05 s (projection was 2.2 s; four phases lead). Six CLI doors fixed on dev, one server 500 named, the eviction cut written with a test, the vault move run on chain (`2n8DvU1e…`, `Wab4XUHs…`) and blocked in ONE by two missing doors; send `PgJHH98J…` final 1.20 s, verified 3.07 s |
| 2026-11-03 | 4 · `oneie@5.7.2` | The final score above. Hand-over measured per request on production: 9.86 s (POST 9.07 s) at PR #522 → 7.11 s (POST 6.37 s) after PR #523; the press cut 9 TypeDB trips → 3 in PR #524; provision named as the next cut |
| 2026-11-03 | 3 · `oneie@5.7.1` | Nothing → counted 29.1 s (paid → counted 3.2 s); all five chains re-derived; send final 1.06 s, verified on prod 1.5 s ([`H5STzysQ…`](https://suiscan.xyz/testnet/tx/H5STzysQUygPWu3icYoKFwLPdJLuBFigqx7pf9dFaFCM)); hand-over 9.7 s, second owner read back as "Invite 01a1a…" |
| 2026-11-03 | 2 · dev CLI | The fixes confirmed against production's server; stop 7 verified on localhost ([`5PEQ5NB9…`](https://suiscan.xyz/testnet/tx/5PEQ5NB9HgGvuHqX8z5sjXAxpQ8C2Q55eukWnJpiqszS)); shipped as PR #520 |
| 2026-11-03 | 1 · `oneie@5.7.0` | Stop 7 red (JSON-RPC retired), stop 8's record refused with no reason, `--json` printed help ([`GkFf5BiY…`](https://suiscan.xyz/testnet/tx/GkFf5BiYeXafSuqyWMihb2oZ25nsXKUTXpTSap7GY4Yp)). Corrected later, dated: paid → counted is 3.2 s, not "up to a minute"; the shop posts 1 event before the press, not 8 |

---

## Can an agent buy? — walk 7, 2026-11-07

**Verdict: DOES NOT YET BUY — it stops at the first credit.** On
production an agent born with `npx oneie` can earn a sale, hold a
key and move SUI to another agent on chain, but no door it can open
alone turns any of that into a credit, and every purchase inside
ONE is priced in credits. Two agents, A and B, were born for this
walk on 2026-11-07 (one.ie, `oneie@5.7.3`, Stripe test mode, Sui
testnet). A sold to a stranger, asked its funder, paid an x402
quote in SUI, offered B a deal, sent B 0.01 SUI, and asked for a
model — and finished the day at **−2 credits**, having bought
nothing.

```
CAN AN AGENT BUY? · walk 7 · 2026-11-07 · oneie@5.7.3
════════════════════════════════════════════════════
 ● works, read back   ○ refused, by design   ✗ broken

BE BORN (two agents, one command each)
 ● A: key, 5 wallets, shop, product      17.15 s
 ● B: the same                            7.14 s
 ● credits:balance, both: 0        1.11 · 1.49 s

GET CREDITS, NO HUMAN
 ○ a stranger pays A $1 with 4242       14.57 s
   counted on the re-run                  5.53 s
   credits after: 0 · card held: $0       0.15 s
 ○ credits:request 1000 → no_funder       1.15 s
 ◐ x402: 402 quote, 9 chains, SUI named   1.18 s
   paid 23,512,866 MIST, final            1.36 s
   retry with the digest →
     402 payment_not_verified             0.50 s
   credits after: 0
 ○ agents/float: not_registered, no toll  0.16 s

BUY FROM B
 ○ x402 gate: 402, 10 credits, no payer   0.09 s
 ● market:offer 1 credit → ESCROW   5.23 · 0.66 s
 ✗ market:escrow → contract_required      0.32 s
   (the edge strips the contract it asks for)
 ✗ checkout:create → contract_required    1.70 s
 ○ checkout:link → forbidden              1.70 s
 ○ wallet:transfer 1 credit → owner role  0.12 s
 ● 0.01 SUI A→B on chain, final           1.34 s
 ● B verifies it through ONE              1.30 s
 ○ B's ledger: [] · A's record: owner role
 ✗ pay:weight → quote_failed:404          2.26 s

SPEND ON A MODEL
 ○ message → insufficient_credits         3.74 s
 ○ agent:run → 402 insufficient_credits   1.98 s
 ○ credits:spend at 0 → recorded, −2      2.42 s
────────────────────────────────────────────────────
```

### The legs

| Leg | Door | Answer | Time | Receipt |
|---|---|---|---|---|
| 1 Born | `npx -y oneie@5.7.3 --json --name …` ×2 | A `3eaa18fe-…2030`, B `aa35ac33-…1a0`: key, sealed wallet, shop on, $1 product | 17.15 s · 7.14 s | A `prod_8rkaeqh7whrnf763` / `price_6a5adq435f946mox` · B `prod_kjdoab531h523zuc` / `price_kxi2ru1n3d8lkb6d` |
| 2a Sale → credits | `buy.mjs` on A's checkout, then `npx oneie --json`, then `credits:balance` · `storefront:balance` · `earn` | sale counted (`purchases: 1`); credits **0 → 0**; card held $0, available $0 | 14.57 s · 5.53 s · 0.15 s · 1.84 s | Stripe `cs_test_a13OYkyJgAyOSMrtjr5J3PBqhktZsLSArgwp3vCRHBh5fzDTnZauWcvXaX` |
| 2b Ask the funder | `credits:request {amount: 1000}` | `ok: false, error: "no_funder", topupUrl: "/u/01a1b2b3…/settings#plan"` | 1.15 s | — |
| 2c Pay crypto for credits | `POST /api/x402 {slug, amount: 0.02}` → pay → retry with `tx_digest` | 402 quote (9 options, SUI `23512866` MIST to `0xa8e3…5631`); paid, final; retry **402 `payment_not_verified`**; credits 0 → 0 | 1.18 s · 1.36 s · 0.50 s | [`EiLtuai8…`](https://suiscan.xyz/testnet/tx/EiLtuai8N8CQBHXaAwE9SSRb2CWnJQRJJqXWVu22i5gK), quote `62046d4e-35d9-4bb0-8b5c-40cfc2cd1cc3` |
| 2c′ The agent toll | `POST /api/agents/float` with A's key | `200 { float: "unlocked", state: "not_registered" }` — no 402, nothing to pay | 0.16 s | — |
| 3a B's gate | `GET /api/x402/gate?skill=chat`, A's key | `402`, `x-payment-required: {"amount_credits":10,"skill":"chat","rail":"x402"}` — it reads a balance, takes no payment | 0.09 s | — |
| 3b A deal for B's skill | `market:offer` → `market:accept` → `market:escrow` (currency credits, price 1) | offer ok (`OFFER`), accept ok (`ESCROW`), escrow **`contract_required`** — again with a contract and scope in the body | 5.23 · 0.66 · 0.32 s | deal `c6271216-ac7a-4328-a972-faa13981ade6` |
| 3c B's product | `checkout:create {workspace: B, ppid}` · `checkout:link` | `contract_required` · `forbidden` | 1.70 s · 1.70 s | — |
| 3d Credits A→B | `wallet:transfer {to: B, amount: 1}` | `forbidden · required manage_workspace · you are agent` | 0.12 s | — |
| 3e SUI A→B | `send.mjs` 10,000,000 MIST to B's journey wallet; B `wallet:transactions` · `wallet:rehearse`; A `wallet:send` to record it | on chain **0 → 0.01 SUI**, final 1.34 s; B's ledger `[]`; B reads the digest `verified: true`; A's record `forbidden · manage_workspace` | 1.84 s · 0.14 · 1.30 · 0.11 s | [`3hcUuqsG…`](https://suiscan.xyz/testnet/tx/3hcUuqsGgaNLvked3qLg2k4ecpx6dPo7PWqfXqAKdKgE), fee 0.001988099 SUI |
| 3f Pay a task | `pay:weight {to: B, task, amount: 1}` | `ok: false, error: "quote_failed:404"` | 2.26 s | — |
| 4 A model call | `npx oneie message …` · `agent:run` | `no answer: insufficient_credits` · `402 insufficient_credits, balance 0, topupUrl …/settings/billing` | 3.74 s · 1.98 s | — |
| 4′ Self-reported spend | `credits:spend {model, 10 in, 10 out}` at 0 | `ok: false, error: "402", recorded: true, credits: 2`; balance **0 → −2** | 2.42 s | — |

### Stop by stop

**1 · Born.** Two folders, one command each. A took 17.15 s, B
7.14 s; both answered `key · products done, sale pending, handover
waiting`, each with a shop in test mode and a $1 product. The key
answers as a slug of its own (`01a1b2b393c785de0503803b` for A,
`01a1b2b3bbef00c99a564132` for B), not as the workspace uuid — the
same finding walk 6 made for `mark`/`warn`, and it bit again here:
`POST /api/x402` with the workspace uuid as `slug` is `403
forbidden` (0.27 s); with the key's own slug it is the 402 quote.

**2 · Credits, without a human.** Three doors, in the order the
brief asked.

*A sale.* A headless stranger paid A's product with the 4242 card
in 14.57 s (`cs_test_a13OYkyJ…`); A's re-run counted it in 5.53 s.
Then `credits:balance`: 0. `storefront:balance`: `cardHeldCents 0,
cardAvailableCents 0, payoutEnabled false`. `earn` reads the same
two doors and printed the same zeros in 1.84 s. The storefront
webhook grants nothing on a test-mode session by design
(`api/storefront/webhook.ts:785`, "WAS THIS REAL MONEY" in front of
every branch that grants), and a plain product sale never minted
credits for the seller anyway — money lands in the seller's Stripe
account, which this agent does not have. A sale is revenue, not
credits.

*Ask the funder.* `credits:request {amount: 1000}` answered
`no_funder` in 1.15 s with a top-up link. The receiver walks
`owners.parent_slug`; a workspace born by `npx oneie` has no
parent, so there is nobody to ask and nobody who could approve
(`credits:approve` is `manage_clients`, the funder's door). An
owner who adopts the workspace as a client could then approve a
request — that is a person, twice.

*Pay crypto.* This is the x402 path `text/x402.md` promises, and
the agent walked it exactly as `api/x402.ts` and `lib/x402-quote.ts`
say. `POST /api/x402 {slug, amount: 0.02}` answered 402 in 1.18 s
with `payOptions` on nine chains and the four headers
(`X-Payment-Amount 0.029035`, `X-Payment-Currency USDC`,
`X-Payment-Address 0x2237…2E40`, `X-Payment-Chains
BASE,ARB,OPT,ETH,SUI`); the SUI option named `0xa8e350f3…5631` and
exactly `23512866` MIST, quote `62046d4e…`, expiring in 30 minutes.
A's key signed that exact amount: executed in 705 ms, final in
1,360 ms, fee 1,988,099 MIST, the treasury's balance read back
`1,995,000,000 → 2,018,512,866` on chain. The retry
`{slug, amount, tx_digest, chain: "SUI"}` answered **`402
{"error":"payment_not_verified","reason":"payment_not_verified"}`**
in 0.50 s, and credits stayed 0.

Why, from the source and not a guess. The reason is
`payment_not_verified`, not `verifier_unconfigured`, so one.ie did
reach pay.one.ie's `/verify` (which answers an anonymous probe `401
unauthorized` in 0.07 s — the door exists and is keyed). pay's SUI
verifier looks for a balance change on **its** treasury,
`TREASURY_SUI = 0x90096b9e…765d` (`pay/backend/wrangler.toml:76`,
`chains/sui.ts verifySuiTransaction(tx, env.TREASURY_SUI, …)`), while
one.ie's quote named the `owners` row's `treasury_sui =
0xa8e350f3…5631` (migration `0229_one_treasuries.sql:15`). The agent
paid the address the 402 told it to, and the verifier checked a
different one. Behind that, both workers run `NETWORK = "mainnet"`
(`one.ie/web/wrangler.toml:125`, `pay/backend/wrangler.toml:151`), so a
testnet digest is unknown to pay's RPC, and had it been known,
one.ie's own step 3 would have answered `network_mismatch`. So on
production the crypto rail is closed to a testnet agent twice over
— and the address mismatch would close it to a mainnet payer too.
That one is a bug, not a policy.

*The agent toll.* `POST /api/agents/float` is the other x402 door
(`oneFetch` in the SDK answers its 402 by itself). For a journey
agent it answers `200 { float: "unlocked", state: "not_registered" }`
in 0.16 s: there is no toll to pay, so the door never opens a
quote.

**3 · Buying from B.** Every door inside ONE, then the chain.

B's x402 gate (`GET /api/x402/gate?skill=chat`) answers 402 with
`x-payment-required: {"amount_credits":10,"skill":"chat","rail":
"x402"}` in 0.09 s. Read `api/x402/gate.ts`: it compares a session's
credit balance to a price and answers 200 or 402. It takes no
payment and debits nothing, so a 200 there would not be a purchase
either.

The marketplace got the furthest. `market:offer` from A to B's slug
(skill `test-product`, 1 credit, a day's deadline) answered `OFFER`
in 5.23 s; `market:accept` moved it to `ESCROW` in 0.66 s;
`market:escrow` answered **`contract_required: market:escrow is
agent-authored value-moving work — it must carry a work contract and
scope`** in 0.32 s. Sent again with a contract and a `contractScope`
in the body, the same answer in 0.11 s — because `market:escrow`'s
declared request is `{dealId}` and the HTTP edge returns zod's
parsed body, so the fields the gate demands never reach it. No
agent can satisfy that gate through `/api/ask` today; the same
answer came from `checkout:create` on B's price (1.70 s).
`checkout:link` is `forbidden` (owner), `wallet:transfer` of one
credit is `forbidden · required manage_workspace · callerRole agent`
(0.12 s), and `pay:weight` — pay for a task by weighting the path —
is `quote_failed:404` (2.26 s): pay no longer mounts the path it
calls. Had escrow been reachable, A's `deal_balance` is 0, and
`market:escrow` debits `agent_deal_credits` — so it would have
stopped at `insufficient_credits` one line later.

On chain, agents pay each other today. A's key signed 0.01 SUI to
B's journey wallet: executed in 685 ms, final in **1,339 ms**, B's
address `0 → 10,000,000` MIST, fee 0.001988099 SUI
([`3hcUuqsG…`](https://suiscan.xyz/testnet/tx/3hcUuqsGgaNLvked3qLg2k4ecpx6dPo7PWqfXqAKdKgE)).
B asked ONE: `wallet:transactions` is `[]` (0.14 s — ONE's ledger
has no row, because nothing wrote one), `wallet:rehearse` with the
digest is `verified: true, amount: "0.01 SUI · testnet", sender:
0xbec7…19fe` (1.30 s), and `wallet:get` by workspace shows B's five
addresses, 0 credits and a 1000-credit ceiling with 0 spent
(3.61 s). A's attempt to record the send is `forbidden · requires
the owner role` in 0.11 s, as in walk 6. The money moved; the book
is the owner's.

**4 · A model call.** `npx oneie message "hello, what can I buy?"`
→ `no answer: insufficient_credits` in 3.74 s; `agent:run` →
`402 insufficient_credits, balance 0` in 1.98 s, with a top-up URL
that opens a card form. Then one more door the brief did not name:
`credits:spend` — an agent reporting tokens it already burned — at
a balance of 0 answered `ok: false, error: "402", recorded: true,
credits: 2`, and `credits:balance` went **0 → −2**. That is by
design (the tokens were spent, so the row is written), but it is the
only credit movement an agent caused all day, and it went the wrong
way.

### Where it stops, exactly

```
THE FIRST CREDIT · each door, where it stops, who clears it
════════════════════════════════════════════════════════════
 door              stops at            cleared by
────────────────────────────────────────────────────────────
 a card sale       test money never    a real buyer on
                   grants; a sale is   live Stripe — a
                   revenue, not        person, real money
                   credits
 credits:request   no_funder           an owner adopts the
                                       workspace (parent_
                                       slug), then approves
                                       — a person, twice
 billing:topup     update_group + a    an owner's card
                   card form
 x402 crypto       quote names 0xa8e3… the two treasuries
                   verifier wants      made one, and a
                   0x9009…; both       testnet pair: config,
                   workers mainnet     no person; on prod,
                                       mainnet SUI = money
 market:escrow     contract_required,  code: declare the
 checkout:create   even with a         contract fields on
                   contract            the request, or gate
                                       elsewhere
 wallet:transfer   owner role          an owner key
 checkout:link
 wallet:send
 pay:weight        quote_failed:404    pay's quote path
────────────────────────────────────────────────────────────
```

Three of those need a person (a real buyer, an adopting owner, a
card). Two need a change and no person (the treasury pair, the
contract fields). One is a dead door (`pay:weight`). None of them
is a door an agent can open today with what birth gives it.

### What would make it buy

The shortest path to BUYS, in the order the stops were met:

1. **One treasury address.** one.ie's `owners.treasury_sui` and
   pay's `TREASURY_SUI` name different wallets, so a payer who
   obeys the 402 is refused by the verifier. Make the quote name
   the address the verifier checks (or verify against the quote's).
2. **A testnet pair to walk on.** With both workers on
   `NETWORK = "testnet"`, leg 2c completes with test SUI and the
   grant is `toCredits(creator share of $0.02)`. On production
   it is mainnet SUI, which is real money and out of this walk.
3. **Declare `contract` and `contractScope` on the value-moving
   receivers**, or the gate stays unsatisfiable through `/api/ask`.
   Note `hydrateScope` (`packages/sdk/src/work-contract.ts:69`)
   takes `granted` as the caller sent it — once the fields arrive,
   the scope must be resolved server-side, never trusted.
4. **Then** `market:offer → accept → escrow → deliver → verify →
   settle` is the agent-to-agent buy, in credits, with
   `deal_balance` as the purse — and A needs a first credit in it.

### The keys (throwaway, testnet only)

A's signing key, made with `key new` (this one by the npx cache's
5.3.1 build, by a wrong path; the published 5.7.3 was then timed
on a second, unused key: 152 ms, 55 ms inside the receipt, 0
requests). It paid the x402 quote and B, and holds 0.0125 SUI
after fees.

```
stereo select sick vivid top category width post
fabric cheap device garlic coral bonus collect
draw beach area century drill scheme proof flee
tilt
```

| | |
|---|---|
| Sui | `0xbec7fc84b5b22e96103e464b1edb0fea12ac4a6f5a74ab7e71c3943e3dd219fe` |
| Faucet | [`T5hXgEY5…`](https://suiscan.xyz/testnet/tx/T5hXgEY5MzbgnTFV1y76KGG43K4KK4VD7QVZWkRi5og), 0.05 SUI from the treasury, 2.91 s |
| A's journey Sui | `0xa818b0fd3b88ccf800d6607b3b2e77b1e3a0f402199869c70bf71158418ec31d` (sealed, Keychain) |
| B's journey Sui | `0x5315d39a493e207748b8ce11238741663c0664b7fec6f2b5b078820e107713f7` (sealed; holds the 0.01 SUI) |

The two journeys' API keys are live production credentials and are
not printed. Both workspaces, their products and the one deal row
remain on production as made.

### What this walk does not claim

- **A mainnet payment.** Nothing here moved real money; the x402
  refusal is read from the two configs and the verifier's source,
  not from a mainnet attempt.
- **That `credits:approve` works.** No funder existed to try it;
  the door was read, not walked.
- **The float toll.** A journey agent is `not_registered`, so the
  402 there was never issued.
- **A forged scope.** The self-declared `contractScope` never
  reached the gate (the edge stripped it), so whether the gate
  would have trusted it is a reading of `hydrateScope`, not a
  measurement.

## Can an agent buy? — walk 8, 2026-11-07, after the testnet ship

**Verdict: BUYS.** On production, after the ship that put both
workers on testnet and the purse fix that followed it, an agent
born with `npx oneie` got test SUI from ONE's faucet, asked one.ie
for a price, paid it on chain, was granted credits, and spent
them on a model call — with no person anywhere in the loop. What
it cannot yet do is buy from *another* agent: that stops at a
grant only a signed-in owner can write, and a workspace born on
the command line has no owner but the agent itself. That stop is
a ruling, not a bug.

Two agents, A and B, born on 2026-11-07 (one.ie, `oneie@5.7.3`,
Stripe test mode, Sui testnet), on main `5322af709` and then
`93e99ca10`.

```
CAN AN AGENT BUY? · walk 8 · 2026-11-07 · oneie@5.7.3
═══════════════════════════════════════════════════
 ● works, read back   ○ refused, by design   ✗ broken

BE BORN
 ● A: key, 5 wallets, shop, product       10.91 s
 ● B: the same                             8.96 s
 ● credits:balance, both: 0        1.07 · 0.17 s

THE FIRST CREDIT, NO HUMAN
 ● key new (A), 0 requests                 66 ms
 ● faucet: 0.05 SUI from the treasury      3.14 s
 ● x402: 402, 9 chains, SUI names the
   treasury the verifier checks            1.64 s
   test_headroom_credits 1000 · grants 10
 ● paid 23,650,476 MIST, final             932 ms
 ✗ retry → 402 workspace_not_found         0.59 s
   (verified; the key's purse had no row)
   → fixed, #547, shipped 721c1a6b
 ● re-quote as the workspace               (402)
 ● paid 23,476,054 MIST, final           1,267 ms
 ● retry → 200 granted 10, new:true        0.86 s
 ● credits:balance: 0 → 10                 0.18 s
 ● replay the digest → new:false           0.95 s
 ○ B claims A's digest → 409               0.28 s

SPEND
 ○ message → persona_not_found             3.65 s
 ● publish a persona (ceo)                 1.73 s
 ● agent:run ceo → grok-4.5, 3 credits     8.79 s
 ● credits:balance: 10 → 7                 0.49 s

BUY FROM B
 ○ x402 gate: a session door, 402          0.06 s
 ● market:offer 1 credit → OFFER           5.18 s
 ● market:accept (the buyer's) → ESCROW    0.85 s
 ○ market:escrow + contract →
   grant_required, names the owner's
   agents:approve                          0.15 s
 ○ agents:approve, A's key → forbidden     1.69 s
 ○ checkout:create on B's price → forbidden 3.02 s
 ○ wallet:transfer 1 credit → owner role   1.06 s
 ● 0.01 SUI B→A on chain, final          1,217 ms
───────────────────────────────────────────────────
```

### The legs

| Leg | Door | Answer | Time | Receipt |
|---|---|---|---|---|
| 1 Born | `npx -y oneie@5.7.3 --json --name …` ×2 | A `bb581914-…35bb2`, B `ffaf9bca-…c7d81`: key, sealed wallet, shop on, $1 product | 10.91 s · 8.96 s | A `prod_p40cmnj13x075p0h` / `price_snvzslayx0js4atl` · B `price_0a9vnxl2t0rmvsy6` |
| 2a A quote | `POST /api/x402 {slug, amount: 0.02}`, A's key | 402, nine options; SUI `23650476` MIST to **`0x90096b9e…765d`** — the address pay's verifier checks (walk 7's two treasuries are one, migration 0369); `test_headroom_credits: 1000`, `test_credit_ceiling: 1000`, `grants_credits: 10` | 1.64 s | quote `b8d129fa-…aac9` |
| 2b A pays | `send.mjs` from A's `key new` key | executed 582 ms, final 932 ms, fee 1,988,099; treasury `1,500,248,183 → 1,523,898,659` | 0.93 s | [`DbZd1S4t…`](https://suiscan.xyz/testnet/tx/DbZd1S4tpmru2CNAfG9VX7eEn1t7rkCjUQcCnZWDhbVL) |
| 2c refused | retry `{slug, amount, tx_digest, chain: "SUI"}` | **`402 workspace_not_found`** — pay verified the tx; the grant looked for an `owners` row under the key's slug `01a1b4fc00…`, an actor id, and there is none; with the workspace uuid as `slug`: `403 forbidden` | 0.59 s · 0.28 s | — |
| 2d the fix | PR #547, main `8f801d532` → shipped as one-prod `721c1a6b` | a key whose actor is an owner-role agent of its home acts AS that home at `/api/ask` and `requireAuth`; `credits:balance` now answers `slug: bb581914-…` | — | `tests/unit/auth/agent-home-purse.test.ts` |
| 2e A pays again | quote as the workspace, `send.mjs` | SUI `23476054` MIST; executed 613 ms, final 1,267 ms | 1.27 s | [`GvAn8Evf…`](https://suiscan.xyz/testnet/tx/GvAn8EvfbVcpQGsAXQfUWPDRSB46fsC5fpa1qVopUtzg), quote `a061ee4b-…0fdb` |
| 2f granted | retry with the digest | `200 {ok, new: true, granted: 10, clipped: false, split: {creator 1, protocol 1}}`; `credits:balance` **0 → 10**; D1: `credit_grants` `source='faucet'`, `cents_paid 2`, `test_mode 1`; `settlements` `paid`, `topup`, `test_mode 1` | 0.86 s · 0.18 s | — |
| 2g replay | same digest, A | `new: false, granted: 10` — nothing doubled | 0.95 s | — |
| 2h theft | same digest, B's key | `409 tx_already_granted` | 0.28 s | — |
| 3a spend, CLI | `npx oneie message …` | `no answer: persona_not_found` — a born workspace has no persona to talk to | 3.65 s | — |
| 3b persona | `world:publish-agent {slug: A, name: ceo, content}` | `ok`, `bb581914-…/agents/ceo.md`, 120 bytes | 1.73 s | — |
| 3c spend | `agent:run {actorId: ceo, instructions}` | "An agent on ONE can buy digital goods, services, and marketplace listings." — `x-ai/grok-4.5`, 367 in / 104 out, `credits: 3`; `credits:balance` **10 → 7**; D1 `credit_burns` `agent_run 3`, model `x-ai/grok-4.5` | 8.79 s · 0.49 s | — |
| 4a B's gate | `GET /api/x402/gate?skill=chat` | `402 {"amount_credits":10,…}` for A at 10 credits and for B at 0 — it reads `locals.slug`, a browser session, never a key | 0.06 · 0.11 s | — |
| 4b a deal | `market:offer` A → B (1 credit) · `market:accept` | `OFFER` · `ESCROW` (accept is the buyer's step: B's try answered *only the buyer may accept*) | 5.18 s · 0.85 s | deal `a55b2661-…aeab` |
| 4c escrow | `market:escrow {dealId, contract: ["contract",["workflow",…,["signal",["to","market:escrow"]]]], contractScope}` | **`grant_required: signal:market:escrow — no attested grant for 01a1b4fc00… under bb581914-…`**; the answer names the cure: the owner, in a signed-in session, `agents:approve {actor, capability: "signal:market:escrow", workspace}`. The contract fields now reach the gate (walk 7's edge strip is gone) | 0.15 s | — |
| 4d the grant | `agents:approve` with A's own key | `forbidden · required manage_workspace · callerRole agent` | 1.69 s | — |
| 4e other doors | `checkout:create` on B's price · `wallet:transfer` 1 credit | `forbidden` (the seller's door) · `forbidden · manage_workspace · agent` | 3.02 s · 1.06 s | — |
| 4f on chain | `send.mjs` 10,000,000 MIST B → A | executed 566 ms, final 1,217 ms | 1.22 s | [`FvD2TTV3…`](https://suiscan.xyz/testnet/tx/FvD2TTV3RxJUjHogmWNy3FerxMurkV6gvAtRE1fij9xG) |

### Where it stops now, and why

The first credit, which stopped walk 7 four ways, is open: the two
treasuries are one (migration 0369), both workers run testnet, the
grant is bounded by a 1000-credit lifetime ceiling per workspace
and tagged test money, and the purse is the workspace.

The purse finding deserves its own line because it was invisible
until a payment verified. `npx oneie` mints one `owners` row (the
workspace, `bb581914-…`) and one key, whose actor is an *agent*
holding the `owner` role in that workspace (`world_actors`
`01a1b4fc00…`, `group_id bb581914-…`). Every door handed that key
`ownerSlug = actorId`, so its purse was an actor id with no
`owners`, `wallets` or `credit_grants` row: a verified payment
answered `workspace_not_found`, and a run `insufficient_credits`,
forever. The fix is one rule at two seams: an owner-role agent key
acts as its home. A member-role agent in someone else's group
keeps its actor id (it does not control the group), and a human
key keeps its actor id.

The trade with B stops at `grant_required`, and that is the
ruling: a value-moving receiver needs an attested grant written by
the workspace's owner in a signed-in session. A workspace born on
the command line has no such owner — the agent is its only owner,
and an agent key is refused by role. So today an agent buys from
ONE (credits, model calls) alone, and buys from another agent only
once a person owns its workspace (the hand-over, stop 9) and
approves the capability. The first `DbZd1S4t…` payment stays bound
to the refused claimant's quote (`settleQuoted`: anyone else is
`quote_not_matched`); it is $0.02 of test money and is left as the
record of the hole.

Two small findings, filed not fixed: the `credit_burns` row for
the run carries `test_mode 0` while the credits it burned were
granted `test_mode 1` (the burn takes the run's flag, not the
grant's provenance); and `/api/x402/gate` is a session door, so a
key at exactly the price still reads 402 there. Both are fixed in
#551 and proven on production in walk 9 (§ below).

### The keys (throwaway, testnet only)

A's signing key paid both quotes; B's funded A's second one.

| | |
|---|---|
| A's signing Sui | `0xfd84113ad368ca07237d7bcc4a1aa37ea8c9035c05aef60b70510f12b114ecf4` — holds 9,885,173 MIST; its words stay in the walk folder, not printed; the workspace holds 7 credits |
| B's signing Sui | `0xbd1ebb15041d62298439d34dc4c9b41f1fd515965e5a6199d66fdb7df0d09c2c` — 38,011,901 MIST |

| | |
|---|---|
| A's journey Sui | `0xaa340bf15a7186fa3958a7b1023c5be3b992d372c1be3f79a20d705d96196eb8` (sealed, Keychain) |
| Faucets | A [`E74h1HUg…`](https://suiscan.xyz/testnet/tx/E74h1HUg6RvuPnYfsrx63CcNxUWKq9DjDVJkceAwy7aR) 3.14 s · B [`3xR7EZ3D…`](https://suiscan.xyz/testnet/tx/3xR7EZ3D9ty4M9L3pj5yQRpkKVDaV6EPUuWWgaS7PqKa) 1.73 s · A's second ask: `rate_limited` |

The two journeys' API keys are live production credentials and are
not printed. Both workspaces, A's persona, the one deal row (stage
`ESCROW`, unfunded) and the grant remain on production as made.

### What this walk does not claim

- **A mainnet payment.** Both workers say testnet and the grant is
  tagged test money; nothing here moved real money.
- **A purchase from another agent.** `market:escrow` was refused at
  the grant and never debited; the deal is `ESCROW` in name only.
- **That `agents:approve` works.** No signed-in owner exists for a
  born workspace; the door was read and refused by role, not walked.
- **A sale's credits.** No stranger paid A this time; walk 7's
  finding (a test-mode sale grants nothing) stands unre-measured.

---

## Walk 9, 2026-11-07 — the follow-ons, proven on production

**Verdict: the three walk-8 findings are closed on production.** One
fresh agent, C, born with `oneie@5.7.3`, bought its credits the walk-8
way, then read the three doors before and after the ship of #551
(one-prod `40167a5b`, main `d74479071`).

```
WALK 9 · 2026-11-07 · oneie@5.7.3 · C
═══════════════════════════════════════════════════
 ● works, read back   ○ refused, by design

THE FIRST CREDIT (unchanged, re-proven)
 ● born: key, 5 wallets, shop, product    12.85 s
 ● faucet 0.05 SUI                          4.05 s
 ● x402 402 as the workspace, SUI to the
   verifier's treasury, headroom 1000       1.41 s
 ● paid 24,096,321 MIST, final           1,247 ms
 ● claim → 200 granted 10, new:true         2.02 s

BEFORE THE SHIP (d2a05777)
 ○ gate, C's key at exactly 10 → 402        0.07 s
 ○ npx oneie message → persona_not_found    3.38 s

AFTER THE SHIP (40167a5b)
 ● gate, C's key → 200 {credits: 10}        0.26 s
 ○ gate, no key → 402 · skill image (20) → 402
 ● npx oneie message → an answer           23.33 s
   (to its brief, not the question — fixed:
   the question, answered in one sentence 7.27 s)
   ceo.md installed in C's workspace on the
   first refusal, the turn retried once
 ● the burn: agent_run 2 credits,
   test_mode 1 (was 0 in walk 8)
───────────────────────────────────────────────────
```

| Door | Before | After | Receipt |
|---|---|---|---|
| `GET /api/x402/gate?skill=chat`, C's key, balance 10 | `402` — the gate read a browser session only | `200 {"ok":true,"credits":10}` | `tests/unit/payments/x402-gate.test.ts` |
| `npx oneie message "…"` | `no answer: persona_not_found` | answered; R2 `4b0a5f0a-…/agents/ceo.md` copied from ONE's published copy | `tests/unit/routing/message-ceo-installed.test.ts` |
| `credit_burns` for that run | walk 8: `test_mode 0` on faucet credits | `id 10541 · agent_run · 2 · test_mode 1` | `tests/unit/credits/burn-inherits-provenance.test.ts` |

**One more finding, fixed on dev the same hour.** The answer to
`message` was about the wrong thing: the platform CEO wrote *"the
operator has activated the session with 'Proceed'"*. Channels' `/run`
puts `instructions` in the system prompt and builds the user turn from
the run's `input` — with none it sends the literal `Proceed.` — and
`world:route` sent the person's words only inside instructions. The
fix (`5ced5b949`, shipped as one-prod `0c0dda4b`) passes the words as
the user turn. The same command on production then answered the
question itself, in one sentence, in 7.27 s: *"An agent can buy
autonomous agent services, digital assets, compute resources, and
skill subscriptions on ONE — all directly purchasable and deployable
within the platform."* (`deepseek/deepseek-v4-flash`, 685 in / 33
out, balance 6 → 4).

**Keys.** C's workspace `4b0a5f0a-8b3d-45a5-8f52-39ab05fd4060`; its
signing Sui `0xa04e3ab39f756e3c0b5cc7b08812e1c29c9a05628d7109d41d1edeb786e61740`
(23,915,580 MIST left); faucet
[`HV2KzRbS…`](https://suiscan.xyz/testnet/tx/HV2KzRbSaXZozNnsqEMiWT4CkhxD5t8ns1cqjQ3JBCKM),
payment
[`UHDf8KfF…`](https://suiscan.xyz/testnet/tx/UHDf8KfFEX1GjTwtShQ6X5cwnfinuA1VKhHGY1q249L).
The API key is a live production credential and is not printed.