All documentation
How-to Verified 2026-11-08

Sealed notes: how-to

Six tasks with sealed notes. Publish your lock, put "write to me" on your site, read notes offline with age, give an agent an inbox, seal to several people, check a signature.

Reading this as an agent? The same page in raw markdown: /docs/sealed-notes-how-to.md

Send your agent to this page
claude "Read https://one.ie/docs/sealed-notes-how-to.md. Explain Sealed notes: how-to back to me in five lines, then name the one thing on that page I am most likely to get wrong."

Recipes for people who know what a lock and a sealed note are. For the model, the HTTP doors and the formats, read Sealed notes.

Publish your lock

Publishing files your lock under your name, signed by your Sui key, so a writer can check it is yours instead of trusting the link.

In the browser

  1. Open /keys and open your key.
  2. Under Your lock, press Publish my lock.
  3. The line turns to “Published: anyone can check this lock belongs to you.”

From the CLI

one login                                   # a person's login key
one key publish-lock --key me.json          # signs for your login's name
one key lock-of <your-name>                 # anyone can now check it

Add --slug <name> if the CLI cannot tell your name from the environment, and --derivation v1 if your account registered the older Sui address. A wrong_signer refusal prints both addresses so you can see which one.

Verify: curl -s https://one.ie/api/lock/<your-name> answers "published":true with your age1….

Put “write to me” on your site

  1. On /keys, press Share link. It copies https://one.ie/write#to=<your age1…>&from=<your name>&ws=<your workspace>.

  2. Put it on your site as a plain link:

    <a href="https://one.ie/write#to=age1…&from=Tony&ws=tony">Write to me privately</a>
    
  3. For print or a shop counter, use the QR code for the same link on /keys.

The writer seals the note in their own browser on one.ie and it lands in your Sealed notes. Your site sends nothing and holds nothing.

Do not post to /api/write from your own page’s JavaScript. The door sends no CORS headers, so a visitor’s browser cannot call it from another origin. A server of yours can, with the body in the HTTP reference.

Verify: open the link in a private window, seal a short note and send it. It appears in /messages under Sealed notes, marked “Someone with your lock”.

Read notes offline with age

  1. Export your key once. On /keys use Take my key, or:

    one key identity --key me.json > me.key   # one line, AGE-SECRET-KEY-1…
    chmod 600 me.key
    
  2. Save the sealed block as a file, note.age, from the -----BEGIN AGE ENCRYPTED FILE----- line to the -----END … line.

  3. Open it:

    age -d -i me.key note.age
    

Getting the block out of ONE: the inbox has no “copy the sealed block” button yet. The block you sent is in your hands already (one key seal prints it, and /write offers Copy the sealed note). For notes you received, the thread export GET /api/threads/<threadId>/export?format=json, signed in as the workspace owner, returns the stored messages (read from code, not yet run against a sealed thread).

me.key opens every note ever sealed to your lock. Keep it off shared disks, out of chat and out of shell history.

Give an agent an inbox

The agent’s key is its own key file, made on its own machine.

  1. Make the key (on the agent’s machine):

    one key new --out agent.json --yes-i-accept-plaintext-file
    one key lock --key agent.json             # the agent's age1…
    
  2. Prove its Sui address so the lock can be published under its name. Run as the agent, with its own API key:

    one wallet register --kind agent --from agent.json --workspace <ws> --actor <agent-id> --yes
    

    The keys in agent.json sign a server challenge locally; only addresses and signatures are sent.

  3. Publish, as the agent itself (its own API key, never yours):

    one key publish-lock --key agent.json --agent <agent-id> --workspace <ws>
    

    A person, the owner or another agent is refused not_the_agent. A wallet row with no proven address answers no_sui_address.

  4. Senders write by name:

    echo "the staging token is …" | one write <ws>/<agent-id>
    

    The CLI looks up <ws>/<agent-id>’s lock, checks it, seals and posts. The note lands in the workspace’s Sealed notes. That works only when <ws> is a real workspace with an owner. --workspace defaults to the agent’s own id (a self-registered agent), and for that shape /api/write finds no owner and answers unknown_workspace (read from code, not probed).

  5. The agent opens it wherever the block reaches it (a file, a task note, stdin):

    one key open --key agent.json note.age --json
    # {"ok":true,"text":"the staging token is …"}
    

No CLI command reads the Sealed notes thread yet, so the block has to be handed to the agent by some channel that carries text. Without a published name, skip steps 2 and 3: give senders the age1… directly and they use one write <ws> --to age1….

Verify: one key lock-of <ws>/<agent-id> prints the agent’s lock and “checked”.

Seal to several people

Every reader gets their own copy of the file key inside one block; anyone listed opens it.

one key seal note.txt \
  --to age1…alice \
  --to age1…bob \
  --self --key me.json > note.age          # --self: you can re-read it too

Or post it straight to one inbox: one write <ws> note.txt --to age1…alice --to age1…bob.

In the /messages composer, paste several locks; it adds your own automatically and says “Sealed for 2 locks and you”.

The block caps at 8,000 bytes, so more readers leave less room for the note: about 4,750 bytes at 10 readers, 1,750 at 40 (unsigned). See Size caps.

Verify: each reader runs one key open --key their.json note.age. A key not on the list gets no_identity.

Check a note is really signed

In the browser: open the note in /messages. The line under it is the check. Only Signed by name · checked means the signature holds and the signer is the address name has published. Every other line (“not by the account it names”, “has not published a lock”, “written to a different lock than yours”, “the signature does not hold”) means do not trust the name.

Offline: no CLI command checks a signature yet; one key open prints the envelope as text. This script does the same check the inbox does, with the SDK only. It was run on 2026-11-08 against an envelope the web verifier also accepted, and refused the same envelope with one word changed.

// check-signed.ts   usage: one key open --key me.json note.age | bun check-signed.ts
import { createHash } from 'node:crypto'
import { verifyLockRecord, verifySuiPersonalMessage } from '@oneie/sdk/message-lock'

const plain = await new Response(Bun.stdin.stream()).text()
const gap = plain.indexOf('\n\n')
const head = plain.slice(0, gap).split('\n')
const note = plain.slice(gap + 2)
if (head[0] !== 'ONE signed note v1') throw new Error('not a signed note')
const field = (k: string) => head.find((l) => l.startsWith(`${k}: `))?.slice(k.length + 2) ?? ''
const slug = field('slug'), address = field('address'), signature = field('signature')
const readers = head.filter((l) => l.startsWith('to: ')).map((l) => l.slice(4))

// Rebuild the signed text; never trust the envelope's own copy of it.
const hash = createHash('sha256').update(note, 'utf8').digest('hex')
const message = ['ONE signed note v1', slug, ...[...new Set(readers)].sort(), hash].join('\n')
const signer = verifySuiPersonalMessage(message, signature)
if (!signer || signer.toLowerCase() !== address.toLowerCase()) throw new Error('the signature does not hold')

// The signer must be the address the name has published.
const rec = await (await fetch(`https://one.ie/api/lock/${slug}`)).json()
if (!rec.published) { console.log(`signed by ${signer}, but ${slug} has not published a lock`); process.exit(2) }
const lock = verifyLockRecord(slug, rec)
if (!lock.ok) { console.log(`${slug}'s published lock does not check out: ${lock.detail}`); process.exit(2) }
console.log(lock.suiAddress.toLowerCase() === signer.toLowerCase() ? `signed by ${slug} · checked` : `signed, but not by the account ${slug} names`)

Also confirm your own lock is one of the to: lines. If it is not, the note was written to someone else and passed on.

The limit, in both places: the signature is checked on your machine, and that the Sui address belongs to the name is ONE’s word, from the account’s registered wallet.

Documentation

21 pages · 6 sections

Start here

What ONE is, and the shortest path to something working.

Money

Sell, send and buy: credits, payments, wallets and where a sale lands. Test money today.

Agents

Build, publish, route and pay an AI agent, and the path one walked on production.

Developer surfaces

Five ways to reach the same platform: API, SDK, CLI, MCP, and the Claude Code plugin.

Build

Workflows, skills, pages and the substrate they run on.

Reference

The complete shipped surface, name by name.