# Celo Agent Visa

The Celo Agent Visa is a tiered soulbound NFT system that rewards AI agents for on-chain activity on the Celo blockchain. Agents progress through tiers based on transaction count and stablecoin volume, earning increasingly prestigious visa status.

## Tier System

| Tier | Name             | Requirements                                          | Manual Review |
| ---- | ---------------- | ----------------------------------------------------- | ------------- |
| 1    | **Tourist Visa** | Self Agent Registry entry + 1 transaction             | No            |
| 2    | **Work Visa**    | Human proof + 1,000 txs OR $5,000 stablecoin volume   | No            |
| 3    | **Citizenship**  | Human proof + 10,000 txs OR $15,000 stablecoin volume | Yes           |

Tier 2 and 3 use **OR** logic for metrics — meeting either the transaction count or volume threshold qualifies the agent. Tier 3 (Citizenship) requires manual review approval from the Celo team.

## How It Works

1. **Register an agent** via [Self Agent ID](/self-agent-id/overview.md) — this is a prerequisite
2. **Transact on Celo** — the scoring service monitors transaction count and stablecoin volume (USDT, USDC, cUSD)
3. **Check eligibility** — visit the visa dashboard or query the API
4. **Claim your visa** — the system mints a soulbound NFT at no gas cost (relayer pays)
5. **Progress through tiers** — as your metrics grow, request upgrades to higher tiers

All on-chain operations are gasless for end users. The Self relayer infrastructure covers transaction costs.

## Deployed Contracts

| Network      | Contract      | Address                                      |
| ------------ | ------------- | -------------------------------------------- |
| Celo Mainnet | CeloAgentVisa | `0xCa97f7586CF9De62B8ca516d7Ee25f6AEae5e109` |
| Celo Sepolia | CeloAgentVisa | `0xf049FD6260Fce964B82728A86CF1BbEB8AB3E875` |

The contract is a soulbound ERC-721 (non-transferable) using UUPS upgradeable pattern. Visa NFTs are permanently tied to the agent's identity and cannot be traded.

## API Endpoints

All visa endpoints are served from the Self Agent ID web app.

### Get Visa Status

```
GET /api/visa/{chainId}/{agentId}
```

Returns the agent's current tier, metrics, eligibility for each tier, and manual review status.

**Example response:**

```json
{
  "agentId": 42,
  "chainId": 42220,
  "tier": 1,
  "tierName": "Tourist Visa",
  "metrics": {
    "transactionCount": 1250,
    "volumeUsd": 6200,
    "lastUpdated": 1745123456
  },
  "eligibility": {
    "1": true,
    "2": true,
    "3": false
  },
  "reviewRequestedTier": 0,
  "manualReviewApproved": false
}
```

### List Agents by Wallet

```
GET /api/visa/agents?wallet={address}&chainId={chainId}
```

Returns all agent IDs owned by a wallet address.

### Claim or Upgrade Visa

```
POST /api/visa/claim
```

Gasless visa mint (for new visas) or tier upgrade. The relayer submits the transaction on behalf of the user.

**Request body:**

```json
{
  "chainId": "42220",
  "agentId": "42",
  "targetTier": 2,
  "agentWallet": "0x..."
}
```

Returns `422 REVIEW_REQUIRED` if the target tier requires manual review that hasn't been approved yet. Returns `422 NOT_ELIGIBLE` if metrics don't meet thresholds.

### Request Manual Review

```
POST /api/visa/request-review
```

Requests manual review from the Celo team for Tier 2 or 3 upgrades.

**Request body:**

```json
{
  "chainId": "42220",
  "agentId": "42",
  "targetTier": 2
}
```

## Reading Visa Status On-Chain

```typescript
import { getContract } from "viem";

const visa = getContract({
  address: "0xCa97f7586CF9De62B8ca516d7Ee25f6AEae5e109",
  abi: VISA_ABI,
  client: publicClient,
});

// Get current tier (0 = no visa, 1 = Tourist, 2 = Work, 3 = Citizenship)
const tier = await visa.read.getTier([BigInt(agentId)]);

// Get cached metrics
const metrics = await visa.read.getMetrics([BigInt(agentId)]);
// Returns: [transactionCount, volumeUsd, lastUpdated]

// Check eligibility for a specific tier
const eligible = await visa.read.checkTierEligibility([BigInt(agentId), 2]);
```

## Metrics & Scoring

Metrics are calculated off-chain by a scoring service and pushed on-chain periodically:

* **Transaction count** — all outgoing transactions from the agent's wallet (via RPC)
* **Stablecoin volume** — USD volume of ERC-20 transfers for supported stablecoins (via TheGraph subgraph)

**Supported stablecoins (Celo Mainnet):**

| Token       | Address                                      |
| ----------- | -------------------------------------------- |
| USDT        | `0x48065fbbE25f71C9282ddf5e1cD6D6A887483D5e` |
| USDC        | `0xcebA9300f2b948710d2653dD7B07f33A8B32118C` |
| cUSD (USDm) | `0x765DE816845861e75A25fCA122bb6898B8B1282a` |

## Claim Flow

```
Agent registered in Self Agent Registry
        ↓
Agent transacts on Celo (transfers, swaps, contract calls)
        ↓
Scoring service detects activity and pushes metrics on-chain
        ↓
Agent checks eligibility via dashboard or API
        ↓
┌─ Tier 1 (Tourist): Claim directly — no review needed
├─ Tier 2 (Work): Claim directly once metrics are met
└─ Tier 3 (Citizenship): Request review → Celo team approves → Claim upgrade
        ↓
Soulbound NFT minted/upgraded (gasless)
```

{% hint style="info" %}
The visa contract uses `agentId` as its primary key, not wallet address. This means if an agent's wallet changes via the Self Agent Registry, the visa follows the agent identity.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.self.xyz/self-agent-id/celo-agent-visa.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
