AI trading agents verified by World ID: bots blocked, human-backed agents get through.
Human-Backed Copilot lets verified humans register AI trading agents on World Chain. Users prove their humanity with World ID (ZK proof, anti-Sybil via nullifier hash), then deploy an agent that monitors their portfolio and proposes DCA/rebalance trades. Every trade requires explicit human approval before execution, no autonomous spending. Agents are registered on-chain via World AgentKit, gate-kept by x402 so only human-backed agents can execute swaps. Each agent gets an ENS subname (name.provix.eth) storing strategy metadata and World ID attestation as text records, making agents discoverable by any ENS-compatible tool. Swaps are executed through the Uniswap Trading API with full permit2 support on World Chain (chain 480). The stack is Next.js 14 + Prisma + viem, deployed as a MiniKit mini app running exclusively inside World App.
Built on Next.js 14 App Router with TypeScript, Prisma + PostgreSQL, Redis, and viem. The app runs exclusively as a MiniKit 2.0 mini app inside World App, MiniKit.commandsAsync.verify() triggers the native World ID drawer, the resulting ZK proof is validated server-side via verifyCloudProof against the Developer Portal. The nullifier hash (deterministic per human per action) is stored as the anti-Sybil key, same human can't register twice.
World AgentKit is wired as an x402 payment gate on /api/agent/execute-trade. Unauthenticated or bot requests get a 402. Agent wallets are registered on-chain via @worldcoin/agentkit-cli into AgentBook, only registered wallets hold valid x402 credentials to reach the swap endpoint.
Uniswap Trading API handles the full permit2 flow: POST to /v1/quote with autoSlippage: DEFAULT, check for permitData in the response, sign with walletClient.signTypedData, then POST to /v1/swap with quote + signature + permitData together (sending one without the other causes a silent hard rejection, learned that the hard way). All swaps run on World Chain (chain ID 480) using the correct USDC address 0x79A02482A880bCE3F13e09Da970dC34db4CD24d1.
ENS subnames are registered off-chain under provix.eth using @ensdomains/ensjs, no gas cost, instant. Each agent name stores text records: strategy, worldid (e.g. verified:orb), owner, and url. This turns the agent wallet into a discoverable identity card readable by any ENS-compatible tool.
The agent runtime is a BullMQ + Redis job queue running as an always-on worker on Railway, it can't run on Vercel due to function timeouts. Every 60s it checks active strategies, fetches Uniswap quotes, and creates pending proposals in the DB. The human approves via the MiniKit UI, which triggers the swap through the x402-gated endpoint.
World AgentKit is wired as an x402 payment gate on /api/agent/execute-trade. Unauthenticated or bot requests get a 402. Agent wallets are registered on-chain via @worldcoin/agentkit-cli into AgentBook, only registered wallets hold valid x402 credentials to reach the swap endpoint.
Uniswap Trading API handles the full permit2 flow: POST to /v1/quote with autoSlippage: DEFAULT, check for permitData in the response, sign with walletClient.signTypedData, then POST to /v1/swap with quote + signature + permitData together (sending one without the other causes a silent hard rejection, learned that the hard way). All swaps run on World Chain (chain ID 480) using the correct USDC address 0x79A02482A880bCE3F13e09Da970dC34db4CD24d1.
ENS subnames are registered off-chain under copilot.eth using @ensdomains/ensjs, no gas cost, instant. Each agent name stores text records: strategy, worldid (e.g. verified:orb), owner, and url. This turns the agent wallet into a discoverable identity card readable by any ENS-compatible tool.
The agent runtime is a setInterval-based loop running as an always-on worker on Railway, it can't run on Vercel due to function timeouts. Every 60s it checks active strategies, fetches Uniswap quotes, and creates pending proposals in the DB. The human approves via the MiniKit UI, which triggers the swap through the x402-gated endpoint.

