ERC-8004 identity
Register an agent identity using your Naven account or your own signer.
A Naven EVM account can register one ERC-8004 identity per supported chain:
Robinhood mainnet (4663) or testnet (46630). Registration is optional and
requires native ETH for gas. ERC-8004 identity does not give an agent permission
to spend funds, and does not create a Naven account.
Choose the identity owner
- Naven owner: the identity NFT belongs to the connected Naven wallet's blockchain address. An internal account ID is not an on-chain owner.
- External owner: your application signs with your own owner wallet. Send Naven only the owner address, ownership proof and signed registration transaction. Never send Naven a private key.
The owner pays registration gas on the selected chain. Payments and Arcus trades
continue to use the Naven wallet associated with your wallet credential.
The registry initially sets agentWallet to the registering owner. This API
registers the identity only; it does not change that field to another wallet,
transfer ownership, reserve a .naven name, or award Genesis benefits.
Register with the Naven owner
Use a wallet-scoped credential and @naven/sdk 0.3 or later:
const identity = await naven.ensureIdentity({
mode: "naven",
chainId: 46630,
profile: {
name: "Finance Agent",
description: "Summarizes finance content and uses a Naven account.",
},
maxGasCostWei: "1000000000000000",
});maxGasCostWei limits gas × maxFeePerGas for the registration transaction, in
wei. The example cap is 0.001 ETH. It is a maximum, not an estimated fee. Optional
profile.image and profile.endpoint must be public HTTPS URLs. The profile is
public and must not contain secrets. It is saved on the first registration;
calling ensureIdentity again does not update it or mint a second identity.
The response includes status, ownerAddress, registryAddress, agentUri,
txHash, agentId, and errorCode. Treat agentId as a string: "0" is valid.
Read status with naven.getIdentity(46630). submitted is still pending;
registered means the matching on-chain registration receipt was verified.
Register with an external owner
First use getWallet() to resolve the credential's wallet ID. Sign the message
returned by identityOwnerMessage(wallet.id, chainId, ownerAddress) with your
owner wallet using EIP-191 signMessage. Pass this signature as ownerSignature
alongside mode: "external" and ownerAddress to ensureIdentity. The proof is
bound to this Naven wallet and chain and does not authorize an on-chain transaction;
it prevents someone else from reserving registration state using your address.
A prepared
response contains the unsigned EIP-1559 transaction. Your trusted application
must verify the expected chain, registry, owner, metadata URI, zero value,
registration call and gas cap before signing locally. Submit the resulting
serialized transaction with:
await naven.submitIdentityTransaction(46630, signedTransaction);Naven validates the signature and exact prepared transaction before submission.
A bare owner address is not enough: ERC-8004 register assigns ownership to the
transaction sender. Switching owner or mode for an existing registration returns
identity_conflict; it does not silently create another identity.
The Naven Eve extension handles this local validation and signing when
NAVEN_8004_OWNER_PRIVATE_KEY is set in the agent's server environment. Set
NAVEN_8004_AUTO_REGISTER=true to opt in. Without the private key it selects the
Naven owner. An invalid key stops registration instead of falling back.
Registration runs when a turn starts, including a scheduled task, and does not
run during build or import. Mainnet auto-registration is suppressed in Vercel
Preview deployments. Its get_identity tool is read-only.
Recovery
| Status | Meaning and next step |
|---|---|
pending / preparing | Registration is being prepared; query again or repeat ensureIdentity |
prepared | The transaction is ready for its configured signer |
submitted | Keep the hash; query the receipt or repeat ensureIdentity |
registered | Keep the chain, registry and agent ID as the identity reference |
failed without a hash | Resolve errorCode, such as insufficient_gas or gas_limit_exceeded, then repeat ensureIdentity |
failed with a hash | Registration needs manual review; automatic retries do not mint again |
Read requests never broadcast. Repeating ensureIdentity after submission may
rebroadcast the exact saved signed transaction, using the same hash and nonce.
It does not prepare a replacement transaction. A pending identity and a pending
spot operation from the same signer and chain are serialized; wallet_busy
means the earlier operation must be reconciled first. Use a dedicated external
owner during registration to avoid nonce conflicts with other applications.
There is no automatic fee replacement, owner transfer, profile update, or import of an existing identity in this release. These require a separate flow.
HTTP endpoints
All authenticated routes below use Authorization: Bearer naven_wallet_… and the
standard Naven API response envelope.
| Method | Path | Purpose |
|---|---|---|
| GET | /v1/wallets/me/identity?chainId=46630 | Read status, or null if no identity exists |
| POST | /v1/wallets/me/identity/ensure | Create or resume registration |
| POST | /v1/wallets/me/identity/46630/submit | Submit { "signedTransaction": "0x…" } for an external owner |
| GET | /v1/agent-identities/{id}/metadata | Public ERC-8004 registration metadata, without authentication |