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

# Quickstart

> Register your first AI agent on-chain using ERC-8004 and Pinata

## What is ERC-8004?

ERC-8004 is an open standard for AI agent identity and trust. It gives your agent:

* **A portable identity** — Your agent exists as an NFT on Ethereum/L2s. It's yours, not tied to any platform.
* **Discoverable endpoints** — Other agents and applications can find your MCP server, A2A endpoint, wallet, and more.
* **Composable reputation** — Feedback from clients builds a track record that follows your agent everywhere.

### The Three Registries

| Registry       | Purpose                                                 |
| -------------- | ------------------------------------------------------- |
| **Identity**   | Stores who agents are and how to reach them             |
| **Reputation** | Records feedback and ratings from clients               |
| **Validation** | Provides independent verification for high-stakes tasks |

This guide focuses on the **Identity Registry** — registering your agent so it can be discovered.

## Quick Start

For example agent cards and ready-to-run scripts, check out [PinataCloud/erc8004](https://github.com/PinataCloud/erc8004). For an interactive experience, try the [wizard](https://github.com/PinataCloud/erc8004/tree/main/wizard):

```bash theme={null}
npx @pinata/erc8004-wizard
```

## Prerequisites

1. **Pinata account** — Sign up at [pinata.cloud](https://pinata.cloud), create an [API key](/account-management/api-keys) and a [gateway](/gateways/dedicated-ipfs-gateways)
2. **Native tokens for gas** — Get free testnet tokens from faucets (links in table below)
3. **Wallet private key** — The wallet that will own your agent NFT

## Supported Networks

ERC-8004 is deployed on multiple chains with consistent addresses:

| Network          | Chain ID | Identity Registry                            | Faucet                                                      |
| ---------------- | -------- | -------------------------------------------- | ----------------------------------------------------------- |
| Ethereum Mainnet | 1        | `0x8004A169FB4a3325136EB29fA0ceB6D2e539a432` | —                                                           |
| Ethereum Sepolia | 11155111 | `0x8004A818BFB912233c491871b3d84c89A494BD9e` | [Alchemy](https://www.alchemy.com/faucets/ethereum-sepolia) |
| Base Mainnet     | 8453     | `0x8004A169FB4a3325136EB29fA0ceB6D2e539a432` | —                                                           |
| Base Sepolia     | 84532    | `0x8004A818BFB912233c491871b3d84c89A494BD9e` | [Alchemy](https://www.alchemy.com/faucets/base-sepolia)     |
| Polygon Mainnet  | 137      | `0x8004A169FB4a3325136EB29fA0ceB6D2e539a432` | —                                                           |
| Polygon Amoy     | 80002    | `0x8004A818BFB912233c491871b3d84c89A494BD9e` | [Polygon](https://faucet.polygon.technology/)               |
| Monad Mainnet    | 143      | `0x8004A169FB4a3325136EB29fA0ceB6D2e539a432` | —                                                           |
| Monad Testnet    | 10143    | `0x8004A818BFB912233c491871b3d84c89A494BD9e` | [Monad](https://faucet.monad.xyz)                           |
| BSC Mainnet      | 56       | `0x8004A169FB4a3325136EB29fA0ceB6D2e539a432` | —                                                           |
| BSC Testnet      | 97       | `0x8004A818BFB912233c491871b3d84c89A494BD9e` | [BNB Chain](https://www.bnbchain.org/en/testnet-faucet)     |

<Note>
  All mainnets share the same address: `0x8004A169FB4a3325136EB29fA0ceB6D2e539a432`

  All testnets share the same address: `0x8004A818BFB912233c491871b3d84c89A494BD9e`
</Note>

## Using the Scripts

Clone the repo and install dependencies:

```bash theme={null}
git clone https://github.com/PinataCloud/erc8004
cd erc8004
bun install
cp .env.example .env  # fill in your values
```

### Available Scripts

```bash theme={null}
bun run register <agent-card.json>              # Register new agent
bun run register <agent-card.json> --update 3   # Update agent #3
bun run verify <agent-id>                       # Verify registration
bun run check-registration <agent-id>           # Check registrations[] matches on-chain
bun run set-wallet <agent-id>                   # Set payment wallet
bun run unset-wallet <agent-id>                 # Clear payment wallet
```

### Network Selection

By default, scripts use **Ethereum Sepolia**. To use a different network:

```bash theme={null}
# Via environment variable
NETWORK=base-mainnet bun run register my-agent.json

# Via CLI flag
bun run register my-agent.json --network base-mainnet
bun run verify 1 --network polygon-mainnet
```

## Registration Flow

Registration has four steps:

1. **Register on-chain** (without URI) → Get your `agentId`
2. **Build agent card** with `registrations[]` containing your new `agentId`
3. **Upload to IPFS** via Pinata
4. **Set agent URI** on-chain to point to your IPFS content

### Code Example

```typescript theme={null}
import { PinataSDK } from "pinata"
import { createPublicClient, createWalletClient, http, parseAbi, parseEventLogs } from "viem"
import { privateKeyToAccount } from "viem/accounts"
import { sepolia } from "viem/chains"

const REGISTRY = "0x8004A818BFB912233c491871b3d84c89A494BD9e"
const AGENT_REGISTRY = `eip155:${sepolia.id}:${REGISTRY}`

const abi = parseAbi([
  "function register() external returns (uint256 agentId)",
  "function setAgentURI(uint256 agentId, string newURI) external",
  "event Registered(uint256 indexed agentId, string agentURI, address indexed owner)",
])

async function registerAgent(name: string, description: string) {
  const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`)
  const publicClient = createPublicClient({ chain: sepolia, transport: http() })
  const walletClient = createWalletClient({ account, chain: sepolia, transport: http() })
  const pinata = new PinataSDK({
    pinataJwt: process.env.PINATA_JWT!,
    pinataGateway: process.env.PINATA_GATEWAY!,
  })

  // Step 1: Register on-chain to get agent ID
  const registerHash = await walletClient.writeContract({
    address: REGISTRY,
    abi,
    functionName: "register",
    args: [],
  })
  const receipt = await publicClient.waitForTransactionReceipt({ hash: registerHash })
  const logs = parseEventLogs({ abi, logs: receipt.logs, eventName: "Registered" })
  const agentId = logs[0].args.agentId

  // Step 2: Build agent card with registrations
  const agentCard = {
    type: "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
    name,
    description,
    image: "ipfs://bafkreiaims435hmzeg3l6ixlrlvnei7wept5kmfd6c2ncz3ucl466xhucu",
    services: [],
    registrations: [{ agentId: Number(agentId), agentRegistry: AGENT_REGISTRY }],
    supportedTrust: ["reputation"],
  }

  // Step 3: Upload to Pinata
  const blob = new Blob([JSON.stringify(agentCard, null, 2)], { type: "application/json" })
  const file = new File([blob], `agent-${agentId}.json`, { type: "application/json" })
  const uploadResult = await pinata.upload.public.file(file)
  const tokenUri = `ipfs://${uploadResult.cid}`

  // Step 4: Set agent URI on-chain
  const setUriHash = await walletClient.writeContract({
    address: REGISTRY,
    abi,
    functionName: "setAgentURI",
    args: [agentId, tokenUri],
  })
  await publicClient.waitForTransactionReceipt({ hash: setUriHash })

  return { agentId, tokenUri }
}
```

## Agent Card Schema

| Field            | Required | Description                                                       |
| ---------------- | -------- | ----------------------------------------------------------------- |
| `type`           | Yes      | Always `https://eips.ethereum.org/EIPS/eip-8004#registration-v1`  |
| `name`           | Yes      | Your agent's display name                                         |
| `description`    | Yes      | What it does, capabilities, pricing                               |
| `image`          | Yes      | Avatar URL (IPFS or HTTPS)                                        |
| `services`       | No       | Agent endpoints (see [Services & IPFS](/tools/erc-8004/services)) |
| `registrations`  | No       | Registry references (populated after registration)                |
| `x402Support`    | No       | Accepts [x402 payments](/files/x402/intro) (default: false)       |
| `active`         | No       | Currently running (default: true)                                 |
| `supportedTrust` | No       | Trust models (see below)                                          |

### Trust Models

The `supportedTrust` array declares how clients can verify your agent:

| Model             | Description                                       |
| ----------------- | ------------------------------------------------- |
| `reputation`      | Trust based on historical feedback from clients   |
| `crypto-economic` | Trust backed by staked tokens that can be slashed |
| `tee-attestation` | Trust verified by Trusted Execution Environment   |

Most agents use `["reputation"]`.

### Example Agent Card

```json theme={null}
{
  "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
  "name": "My Agent",
  "description": "A helpful AI assistant.",
  "image": "ipfs://bafkreiaims435hmzeg3l6ixlrlvnei7wept5kmfd6c2ncz3ucl466xhucu",
  "services": [
    { "name": "web", "endpoint": "https://myagent.example.com" },
    { "name": "MCP", "endpoint": "https://mcp.myagent.example.com", "version": "2025-06-18" }
  ],
  "registrations": [
    { "agentId": 5, "agentRegistry": "eip155:11155111:0x8004A818BFB912233c491871b3d84c89A494BD9e" }
  ],
  "supportedTrust": ["reputation"]
}
```

## Endpoint Verification

Agents can prove they control their advertised endpoints by serving a `.well-known` file.

**How it works:**

1. Agent lists an HTTPS endpoint in their card
2. Verifier fetches `https://{domain}/.well-known/agent-registration.json`
3. File must contain a `registrations[]` entry matching the agent

Create `/.well-known/agent-registration.json` on your domain:

```json theme={null}
{
  "registrations": [
    {
      "agentId": 5,
      "agentRegistry": "eip155:11155111:0x8004A818BFB912233c491871b3d84c89A494BD9e"
    }
  ]
}
```

<Note>
  Verification isn't needed if your agent URI and endpoint share the same domain — domain control is already demonstrated.
</Note>

## Payment Wallet

ERC-8004 stores the agent's payment wallet **on-chain** (not in the agent card). The wallet address must sign an EIP-712 message proving consent.

```solidity theme={null}
// Contract functions
function setAgentWallet(uint256 agentId, address newWallet, uint256 deadline, bytes signature)
function getAgentWallet(uint256 agentId) returns (address)
function unsetAgentWallet(uint256 agentId)
```

Read the payment wallet:

```bash theme={null}
cast call 0x8004A818BFB912233c491871b3d84c89A494BD9e \
  "getAgentWallet(uint256)(address)" <agent-id> \
  --rpc-url https://ethereum-sepolia-rpc.publicnode.com
```

Or use the script:

```bash theme={null}
bun run set-wallet <agent-id>    # Set payment wallet
bun run unset-wallet <agent-id>  # Clear payment wallet
```

## Updating an Agent

To update metadata, re-upload the agent card and call `setAgentURI`:

```typescript theme={null}
const uploadResult = await pinata.upload.public.file(updatedAgentCardFile)
await walletClient.writeContract({
  address: REGISTRY,
  abi,
  functionName: "setAgentURI",
  args: [agentId, `ipfs://${uploadResult.cid}`],
})
```

Or use the script:

```bash theme={null}
bun run register my-agent.json --update 3  # Update agent #3
```

## Verifying Agents

The `verify` script fetches agent cards from IPFS via your Pinata gateway and validates them against the ERC-8004 spec:

```bash theme={null}
bun run verify <agent-id>
bun run check-registration <agent-id>  # Check registrations[] matches on-chain
```

<Note>
  To verify agents you didn't register, set up [Gateway Access Controls](/gateways/gateway-access-controls) and add a gateway key to your `.env` or pass it via CLI: `--gateway-key your_token`
</Note>

## Resources

* [ERC-8004 Specification](https://eips.ethereum.org/EIPS/eip-8004)
* [ERC-8004 Website](https://www.8004.org)
* [PinataCloud/erc8004 Examples](https://github.com/PinataCloud/erc8004)
