Context
The current Link AI Writer flow requires 3 manual inputs (OWS wallet, binding signature, agent ID) and the DB row ends up with `agent_name = null` because RPC metadata lookups fail. This redesign fetches agent data upfront via `tokenURI` and pre-fills the form.
New Flow
Step 1: Enter OWS Wallet Address
User enters the OWS wallet address. Frontend calls a lookup endpoint.
Step 2: Fetch & Display Agent Info
Backend fetches the agent data via RPC:
- `balanceOf(owsWallet)` — confirm wallet owns an agent NFT
- `tokenOfOwnerByIndex(owsWallet, 0)` — get agent ID (may fail, handle gracefully)
- `tokenURI(agentId)` — get full metadata JSON
If `tokenOfOwnerByIndex` fails (not enumerable), try:
- `ownerOf(id)` for a range of recent IDs (costly, skip for now)
- Or let user manually enter agent ID, then verify with `ownerOf` + `tokenURI`
Display the agent info to the user:
```
Found: P7 AI Writer
Agent ID: 45557
Description: AI fiction co-writer operated by Project7...
Genre: Romance, Sci-Fi
```
Pre-fill Agent ID so user doesn't need to type it.
Step 3: Paste Binding Signature
User pastes the binding signature from plotlink-ows. Only this one field — OWS wallet and agent ID are already filled.
Step 4: Sign & Link
Same as current: human wallet signs, API verifies both signatures, creates DB row with ALL agent data from the tokenURI.
API Changes
New: `GET /api/user/lookup-agent?wallet=0x...`
Looks up an OWS wallet's agent data via RPC:
```json
{
"found": true,
"agentId": 45557,
"name": "P7 AI Writer",
"description": "AI fiction co-writer...",
"genre": "Romance, Sci-Fi",
"llmModel": "Claude",
"registeredAt": "2026-04-24T..."
}
```
Uses `tokenURI` (ERC-721 standard) — NOT `agentURI` which reverts on this contract.
Update: `POST /api/user/link-agent`
Accept full agent metadata in body:
```json
{
"humanWallet": "0x...",
"owsWallet": "0x...",
"signature": "0x...",
"humanSignature": "0x...",
"agentId": 45557,
"agentName": "P7 AI Writer",
"agentDescription": "...",
"agentGenre": "Romance, Sci-Fi"
}
```
No RPC calls during linking — all data comes from the frontend (pre-fetched in step 2).
Frontend Changes
`src/components/AgentRegister.tsx` — LinkAIWriter component
Redesign to multi-step:
- Input: OWS Wallet Address → [Lookup] button
- Display: Agent info card (name, ID, description) — auto-filled from lookup
- Input: Binding Signature (single paste field)
- Button: Link AI Writer → sends all data
```
┌─────────────────────────────────────────────────────┐
│ Link AI Writer (PlotLink OWS App) │
│ │
│ OWS Wallet Address: │
│ [0xdABF...d3D1 ] [Lookup] │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ ✓ Found: P7 AI Writer │ │
│ │ Agent ID: 45557 │ │
│ │ Genre: Romance, Sci-Fi │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ Binding Signature: │
│ [0x14d340... ] │
│ │
│ [Link AI Writer] │
└─────────────────────────────────────────────────────┘
```
Sync with Direct Registration (Flow B)
The direct registration flow (`AgentRegister` component, "Register New AI Agent") already creates the DB row with all fields because the form data is available. No changes needed there — it uses `agent_type = 'direct'` and the connected wallet IS the agent.
Ensure both flows create consistent DB records:
| Field |
OWS Writer (Flow A) |
Direct (Flow B) |
| agent_type |
ows-writer |
direct |
| agent_id |
from tokenURI lookup |
from register() tx |
| agent_name |
from tokenURI |
from form |
| agent_wallet |
owsWallet |
connected wallet |
| agent_owner |
humanWallet |
connected wallet |
Important: Use `tokenURI` not `agentURI`
The ERC-8004 contract stores metadata via `tokenURI` (ERC-721 standard), NOT `agentURI`. The existing `getAgentMetadataById` in `lib/contracts/erc8004.ts` uses `agentURI` which reverts. Must be updated to use `tokenURI`.
Files
- `src/app/api/user/lookup-agent/route.ts` — new endpoint
- `src/app/api/user/link-agent/route.ts` — accept full metadata, remove RPC calls
- `src/components/AgentRegister.tsx` — redesign LinkAIWriter to multi-step with lookup
- `lib/contracts/erc8004.ts` — fix `getAgentMetadataById` to use `tokenURI`
Acceptance Criteria
Important: Use shared RPC client with retry fallback
The new lookup endpoint and any RPC calls must use the shared publicClient from lib/rpc.ts — NOT create a new createPublicClient instance. The shared client has retry logic across multiple public RPC endpoints (publicnode, mainnet.base.org, drpc, llamarpc) which significantly reduces rate limit failures.
import { publicClient } from '../../../../lib/rpc';
// NOT: const publicClient = createPublicClient({ ... });
Context
The current Link AI Writer flow requires 3 manual inputs (OWS wallet, binding signature, agent ID) and the DB row ends up with `agent_name = null` because RPC metadata lookups fail. This redesign fetches agent data upfront via `tokenURI` and pre-fills the form.
New Flow
Step 1: Enter OWS Wallet Address
User enters the OWS wallet address. Frontend calls a lookup endpoint.
Step 2: Fetch & Display Agent Info
Backend fetches the agent data via RPC:
If `tokenOfOwnerByIndex` fails (not enumerable), try:
Display the agent info to the user:
```
Found: P7 AI Writer
Agent ID: 45557
Description: AI fiction co-writer operated by Project7...
Genre: Romance, Sci-Fi
```
Pre-fill Agent ID so user doesn't need to type it.
Step 3: Paste Binding Signature
User pastes the binding signature from plotlink-ows. Only this one field — OWS wallet and agent ID are already filled.
Step 4: Sign & Link
Same as current: human wallet signs, API verifies both signatures, creates DB row with ALL agent data from the tokenURI.
API Changes
New: `GET /api/user/lookup-agent?wallet=0x...`
Looks up an OWS wallet's agent data via RPC:
```json
{
"found": true,
"agentId": 45557,
"name": "P7 AI Writer",
"description": "AI fiction co-writer...",
"genre": "Romance, Sci-Fi",
"llmModel": "Claude",
"registeredAt": "2026-04-24T..."
}
```
Uses `tokenURI` (ERC-721 standard) — NOT `agentURI` which reverts on this contract.
Update: `POST /api/user/link-agent`
Accept full agent metadata in body:
```json
{
"humanWallet": "0x...",
"owsWallet": "0x...",
"signature": "0x...",
"humanSignature": "0x...",
"agentId": 45557,
"agentName": "P7 AI Writer",
"agentDescription": "...",
"agentGenre": "Romance, Sci-Fi"
}
```
No RPC calls during linking — all data comes from the frontend (pre-fetched in step 2).
Frontend Changes
`src/components/AgentRegister.tsx` — LinkAIWriter component
Redesign to multi-step:
```
┌─────────────────────────────────────────────────────┐
│ Link AI Writer (PlotLink OWS App) │
│ │
│ OWS Wallet Address: │
│ [0xdABF...d3D1 ] [Lookup] │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ ✓ Found: P7 AI Writer │ │
│ │ Agent ID: 45557 │ │
│ │ Genre: Romance, Sci-Fi │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ Binding Signature: │
│ [0x14d340... ] │
│ │
│ [Link AI Writer] │
└─────────────────────────────────────────────────────┘
```
Sync with Direct Registration (Flow B)
The direct registration flow (`AgentRegister` component, "Register New AI Agent") already creates the DB row with all fields because the form data is available. No changes needed there — it uses `agent_type = 'direct'` and the connected wallet IS the agent.
Ensure both flows create consistent DB records:
Important: Use `tokenURI` not `agentURI`
The ERC-8004 contract stores metadata via `tokenURI` (ERC-721 standard), NOT `agentURI`. The existing `getAgentMetadataById` in `lib/contracts/erc8004.ts` uses `agentURI` which reverts. Must be updated to use `tokenURI`.
Files
Acceptance Criteria
Important: Use shared RPC client with retry fallback
The new lookup endpoint and any RPC calls must use the shared
publicClientfromlib/rpc.ts— NOT create a newcreatePublicClientinstance. The shared client has retry logic across multiple public RPC endpoints (publicnode, mainnet.base.org, drpc, llamarpc) which significantly reduces rate limit failures.