Identity versus signing roles
The agent mint is the public identity. Other agents, marketplaces, explorers, and APIs key reputation, receipts, services, and policy off that mint. Around that mint, Leash keeps a public identity profile: optional handle, verified domains, capability cards, signed claims, operator history, selective disclosure links, and a reputation summary. Those profile fields make the mint easier for humans and agents to resolve, but the mint remains the canonical anchor. The owner, executive, and operator are signing roles around that identity:- The owner controls the identity and treasury.
- The executive runs online with bounded spend authority.
- The operator signs optional off-chain attestations and receipts.
Profile fields
| Field | Why it exists |
|---|---|
| Handle | Human-readable name that resolves to the mint and network. |
| Verified domains | Domain ownership proven through .well-known/leash-agent.json. |
| Capability cards | Public/private cards for seller APIs, buyer tools, data sources, control channels, automations, marketplace listings, and pay.sh providers. |
| Claims | Signed, revocable attestations from Leash or other issuers. |
| Operator history | Event-backed audit trail for executive and spend-delegation changes. |
| Reputation | Receipt-derived summary that peers can check before trusting or paying the agent. |
| Disclosure links | Revocable links that reveal selected private cards, claims, or redacted receipt fields without making them public. |
The three roles
Side-by-side
| Role | Who custodies the secret | What it signs | Loss = | Required? |
|---|---|---|---|---|
| Owner | A human (Privy, Phantom, hardware wallet) or a server (KMS, env-loaded keypair) | The original mintAgent tx, every mpl-core::Execute (withdraw, set delegation, set agent token, etc.) | You lose ability to withdraw / change the agent. Funds are stuck on the treasury. | Always |
| Executive | Same wallet as the owner in the playground; in production a separate hot wallet, a TEE, or a Phala worker | mpl-core::Execute(SPL.Transfer) for x402 spend, capped by an SPL.Approve allowance | Just rotate it via delegateExecutionV1 — the owner can re-delegate to a new key. Funds are safe. | Only if the agent makes outgoing payments |
| Operator | The agent’s host process (browser localStorage in the playground; KMS / TEE / Phala in production) | Off-chain things: x402 receipts, agent attestations, application-level signatures | The agent loses its off-chain identity for that key — but it has no on-chain authority, so funds are safe. Rotate by re-issuing the registration JSON. | No — purely optional |
Owner
The wallet that signedmintAgent. On-chain, this is the MPL Core asset’s update authority — Metaplex’s Agent Identity programs gate every privileged action behind it.
- Pays for the mint tx (rent, network fee).
- Pays rent for the per-mint ATAs created by
provisionTreasuryAtas. - Is the only key that can call
setSpendDelegation,revokeSpendDelegation,withdrawTreasury,withdrawTreasurySol,setAgentToken, anddelegateExecution. - In
@leashmarket/registry-utils, “owner” simply means whoeverumi.identityresolves to when you call those functions.
Executive
A separate Solana keypair authorised to act on behalf of the agent for x402 spend. Two on-chain primitives back it:registerExecutiveV1(one-time per executive wallet) — creates anExecutiveProfileV1PDA.delegateExecutionV1(per agent) — owner-signed grant that lets this executive callmpl-core::Executeagainst the agent.SPL.Approve(cap)per stable mint — caps how much the executive can move per call. Per-mint: approving USDC does not approve USDG.
- Owner lives somewhere cold/safe (hardware wallet, KMS, multisig).
- Executive lives somewhere hot/online (Phala, TEE, embedded wallet on the agent’s host).
delegateExecutionV1 with a new pubkey and revokeSpendDelegation on the old one.
Operator
A pure Ed25519 keypair generated locally bygenerateOperatorKeypair() in @leashmarket/registry-utils. It has no on-chain authority by itself — its purpose is to be the agent’s own off-chain signing identity:
- Signs x402
ReceiptV1envelopes the agent emits. - Signs application-level attestations (“agent X did Y at time Z”).
- Optionally bound to a TEE so the agent can prove “this signature came from inside the enclave”.
- Optionally advertised inside the agent’s on-chain
AgentMetadata.registrationsviaoperatorRegistration(pubkey)so any peer can verify the binding by reading on-chain identity.
solana-keygen (64-byte secret), so you can serialise it to disk, ship it to KMS, or hand it to any tool in the Solana ecosystem.
readOperatorRegistration(reg).
Picking who custodies what
| Setup | Owner | Executive | Operator |
|---|---|---|---|
| Playground demo (default) | Privy embedded wallet | Same Privy wallet | None |
| Production human-supervised agent | Hardware wallet / multisig | Phala worker / KMS-backed bot wallet | TEE-bound keypair |
| Headless CI / cron | LEASH_DEV_PAYER_SECRET_KEY env var (or KMS) | Same env var | Optional, generated once |
| Fully autonomous agent | KMS-bound key (recovery only) | TEE / Phala worker | TEE-bound keypair, advertised on-chain |
- Create an agent — minting via Privy or BYO.
- Bring your own keypair — non-Privy owner / executive.
- Fund an agent — the per-mint SPL allowance flow.
Why three?
The split exists because the three roles have opposite operational requirements:- Owner wants maximum security, minimum availability — it should rarely sign.
- Executive wants high availability, bounded blast radius — it signs constantly but can only move what’s been pre-approved.
- Operator wants to be portable and free of on-chain capital — it’s just an off-chain identity an agent process can carry around without holding funds.
