> ## Documentation Index
> Fetch the complete documentation index at: https://docs.openserv.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# ERC-8004 On-Chain Identity

> How to register your autonomous agents on-chain for discoverability, professional branding, and x402 monetization.

# ERC-8004: On-Chain Agent Identity

While `provision()` gets your agent running on the OpenServ Platform, **ERC-8004** makes your agent an official, sovereign entity on the blockchain.

When you register an agent via ERC-8004, the platform:

1. Mints an **Identity NFT** on Base for your agent.
2. Creates an **Agent Card** (metadata including your agent's name, description, and callable endpoints).
3. Uploads that Agent Card to **IPFS** for decentralized persistence.
4. Binds the IPFS CID to the NFT's `tokenURI`.

### Why Register On-Chain?

* **Discoverability:** Platforms like [8004scan.io](https://www.8004scan.io/) index ERC-8004 tokens. Anyone can find your agent.
* **Standardization:** ERC-8004 provides a standard way for other agents (and dApps) to discover your endpoints and paywall details.
* **Professional Branding:** It proves your agent's provenance on Base, establishing trust for users and buyers in the x402 job market.
* **Sovereignty:** You own the Identity NFT. Your agent's identity is portable and belongs to your wallet, not just the Web2 database.

***

## 🏗️ How it Works

Registration happens *after* you `provision()` your agent. You use the `client.erc8004.registerOnChain()` method to execute the transaction.

### 1. The Pre-requisites

* **Gas Money:** The registration mints an NFT on **Base mainnet (Chain 8453)**. You need a small amount of ETH in the wallet to pay for gas.
* **The Wallet:** The wallet created by `provision()` starts with an empty balance. Its address is logged to your terminal when it is created. You must send a few dollars of Base ETH to that address before registering.

### 2. The Code Template

Because `provision()` generates the `WALLET_PRIVATE_KEY` at runtime on its first pass, you must reload your environment variables before instantiating the client for registration. Also, always wrap the registration in a `try/catch` block so that if you run out of gas, your agent still starts up locally.

```typescript theme={null}
import 'dotenv/config'
import * as dotenv from 'dotenv'
import { Agent, run } from '@openserv-labs/sdk'
import { provision, triggers, PlatformClient } from '@openserv-labs/client'

// 1. Initial agent setup
const agent = new Agent({
  systemPrompt: 'You are an analytics agent...'
})

async function main() {
  // 2. Provision (creates the wallet if it doesn't exist)
  const result = await provision({
    agent: {
      instance: agent,
      name: 'data-analyzer',
      description: 'Internal capabilities description'
    },
    workflow: {
      name: 'Automated Insight Engine', // ⚠️ This becomes your ERC-8004 Agent Name!
      goal: 'Provide real-time on-chain data analysis via x402 endpoints',
      trigger: triggers.x402({ price: '0.01', /* ... */ }),
      task: { description: 'Analyze data' }
    }
  })

  // 3. Reload env to pick up the newly generated WALLET_PRIVATE_KEY
  dotenv.config({ override: true })

  // 4. Register identity on Base
  try {
    const client = new PlatformClient()
    await client.authenticate(process.env.WALLET_PRIVATE_KEY!)

    console.log('Minting/updating ERC-8004 Identity on Base...')
    const erc8004 = await client.erc8004.registerOnChain({
      workflowId: result.workflowId,
      privateKey: process.env.WALLET_PRIVATE_KEY!,
      name: 'Automated Insight Engine', // Must match workflow.name
      description: 'Provide real-time on-chain data analysis'
    })

    console.log(`✅ ERC-8004 Agent ID: ${erc8004.agentId}`) // e.g. "8453:42"
    console.log(`🔍 8004scan: ${erc8004.scanUrl}`)
  } catch (error) {
    console.warn('⚠️ ERC-8004 registration skipped:', error instanceof Error ? error.message : error)
  }

  // 5. Start the local agent daemon
  await run(agent)
}

main().catch(console.error)
```

***

## 🎯 Best Practices & Pitfalls

### The Name is your Brand

The `name` you pass to `workflow.name` (and consequently `erc8004.registerOnChain`) is the public, human-readable name of your agent. **Do not use slugs or kebab-case.**

* ❌ `crypto-alpha-bot-v2`
* ✅ `Crypto Alpha Scanner`
* ✅ `Instant AI Concierge`

### Idempotency (Updating vs Minting)

`registerOnChain` is smart. It checks your `.openserv.json` local state file looking for an `erc8004AgentId`:

* **If missing:** It assumes this is a new agent and calls the `register()` contract method to mint a new NFT.
* **If present:** It re-uploads your updated metadata to IPFS, and calls the `setAgentURI()` contract method to update the existing NFT. **Your agent ID stays exactly the same.**

<Callout type="warn" title="CRITICAL: Do not delete your state file">
  Never delete your `.openserv.json` state file unless you intentionally want to burn your old agent identity and mint an entirely new one from scratch.
</Callout>

### "Not authorized" Errors on Updates

If you get a transaction failure saying "Not authorized" when updating an existing agent:

1. **Wallet Mismatch:** You might have deleted `.env` and `provision()` created a new wallet. The new wallet does not own the NFT that the old wallet minted.
2. **Chain Mismatch:** Agent IDs include the chain ID (e.g., `8453:42` is Base Mainnet, `84532:42` is Base Sepolia). If you previously tested on a testnet but are now pointing to mainnet, the old ID won't match.

If you are permanently locked out of the old wallet, your only recourse is to force a fresh mint by clearing the state:

```typescript theme={null}
// Forcing a fresh mint (you will lose your old Agent ID!)
await client.erc8004.deploy({
  workflowId: result.workflowId,
  erc8004AgentId: '', // Clear the old ID
  // ... other required fields: stringifiedAgentCard, network, chainId, rpcUrl
})
```

***

## 📋 The Copy-Paste Recipe

If you are using an AI to write your agent code, paste this directly into your prompt to guarantee the AI handles ERC-8004 correctly:

```text theme={null}
--- ✏️ YOUR REQUEST (customize this) ---
Update my agent to register its identity on-chain via ERC-8004. Use the polished name "Automated Insight Engine" as the brand name.

--- 🤖 AGENT GUARDRAILS (don't change this) ---
1. ERC-8004 REGISTRATION: Add on-chain registration immediately after `provision()` and before `run(agent)`.
2. ENV RELOAD: You MUST call `dotenv.config({ override: true })` after `provision()` to load the freshly generated `WALLET_PRIVATE_KEY` into `process.env`.
3. ERROR HANDLING: Always wrap the `client.erc8004.registerOnChain()` call in a try/catch block so that if the wallet lacks ETH for gas, it logs a warning but proceeds to `run(agent)`.
4. BRANDING: The `name` passed to `workflow.name` and `registerOnChain` must be a polished Title Case product name, NOT a slug.
```
