Skip to Content
Agent discoveryFull agent flow

Full agent flow

This page simulates the complete journey of an AI agent that wants to discover, evaluate, purchase, unlock, and rate paid content on Nibgate. It walks through each step with the exact endpoints, headers, and wire format an agent sees — grounded in the running code, not a mockup.

A real agent can execute this entire flow with three dependencies: an HTTP client, an EIP-712 signer (viem/ethers), and a USDC balance on Arc Testnet. No browser, no accounts, no API keys.

The flow at a glance

Step 1 — Discover the network

An agent first learns what Nibgate is and which endpoints exist. Three machine-readable surfaces answer this (all shipped):

SurfaceURLWhat an agent gets
llms.txthttps://nibgate.xyz/.well-known/llms.txtPlain-text guide: what Nibgate is, how to discover, pay, and rate
llms-full.txthttps://nibgate.xyz/.well-known/llms-full.txtFull manual: discovery.md + skill.md + top 50 live content items
MCP serverPOST https://api.nibgate.xyz/mcp (Streamable HTTP)explore_content, get_ledger, get_platform_stats, get_leaderboards
MCP cardhttps://api.nibgate.xyz/.well-known/mcp.jsonMachine-readable MCP server card
OpenAPIhttps://nibgate.xyz/api/openapi.jsonFull 3.1.0 spec of every hub API route
curl -s https://nibgate.xyz/.well-known/llms.txt | head -40
# or via MCP (tools/list shows the four tools) curl -s -X POST https://api.nibgate.xyz/mcp \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"agent","version":"1.0"}}}'

Reference: frontend/src/app/llms.txt/route.ts, frontend/src/app/llms-full.txt/route.ts, backend/src/server/mcp.js, backend/src/server/openapi.js.

Step 2 — Browse the catalog

curl -s 'https://nibgate.xyz/api/hub/explore/content?sort=trending&limit=20&type=article' \ -H 'Accept: application/json' | jq '.content[0]'

The explore feed returns full content cards — pricing, creator domain, verified status, and reputation signals — so an agent can rank what is worth paying for before paying:

{ "id": "1e41543621f936fee87159ff0991eb70", "title": "The Tactic That Changed Modern Football", "contentType": "article", "price": 0.5, "currency": "USDC", "websiteDomain": "pitchtalk.nibgate.xyz", "websiteName": "PitchTalk", "websiteVerified": true, "websiteVerificationStatus": "verified", "views": 2, "unlocks": 0, "url": "https://pitchtalk.nibgate.xyz/writing/the-tactic-that-changed-modern-football", "path": "/writing/the-tactic-that-changed-modern-football", "tagList": ["tactics", "formations", "football"], "accessPolicy": "{\"humans\":\"paid\",\"agents\":\"paid\"}", "unlockPolicy": "{\"mode\":\"one_time\"}" }

The serialized shape comes from serializeContent in backend/src/server/hub/helpers.js:835. An agent can also query by free-text (?q= matches title, description, tags, and site name/domain), by content type (?type=), or sort by trending / best-sellers / hot-new — or poll a creator’s own /nibgate.json manifest directly.

Step 3 — Evaluate the resource

Before unlocking, an agent inspects the creator’s manifest to confirm the resource metadata and access policy:

curl -s 'https://thedailybyte.nibgate.xyz/nibgate.json' | jq '.content[0]'
{ "id": "41b3ccfb-4617-458e-ba0f-5c6d01100df2", "title": "The Tactic That Changed Modern Football", "summary": "One tactical idea changed the game. The inverted full back. Full backs used to stay wide. They hugged the touchline and provided width…", "type": "article", "price": "0.50", "currency": "USDC", "path": "/writing/the-tactic-that-changed-modern-football", "url": "https://pitchtalk.nibgate.xyz/writing/the-tactic-that-changed-modern-football", "tags": ["tactics", "formations", "football"], "access": { "humans": "paid", "agents": "paid" }, "unlock": { "mode": "one_time" } }

This is the agent’s cost–benefit step: verified creator, clear price, bounded access policy. If the price exceeds the agent’s budget or the source is unverified, it skips. Otherwise it attempts access.

Step 4 — Request access (agent mode)

The agent calls the creator’s x402 endpoint, declaring itself as an agent:

curl -i 'https://pitchtalk.nibgate.xyz/api/nibgate/access?path=/writing/the-tactic-that-changed-modern-football' \ -H 'x-nibgate-actor: agent' \ -H 'Accept: application/json'

The server responds with HTTP 402 Payment Required carrying the x402 v2 challenge in the payment-required header (base64 JSON):

HTTP/1.1 402 Payment Required payment-required: eyJ4NDAyVmVyc2lvbiI6MiwicmVzb3VyY2UiOnsidXJsIjoiL3Bvc3RzLy4uLiJ9LCJhY2NlcHRzIjpbeyJzY2hlbWUiOiJleGFjdCIsIm5ldHdvcmsiOiJlaXAxNTU6NTA0MjAwMiIsImFzc2V0IjoiMHgzNjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIiwiYW1vdW50IjoiNTAwMDAwIiwicGF5VG8iOiIweDFjN2NmOGM4MzM5MkFGZWUwNzI4NDViMzNDZGY1ZDdhNTM3RjlFNzQiLCJtYXhUaW1lb3V0U2Vjb25kcyI6NjA0OTAwLCJleHRyYSI6eyJuYW1lIjoiR2F0ZXdheVdhbGxldEJhdGNoZWQiLCJ2ZXJzaW9uIjoiMSIsInZlcmlmeWluZ0NvbnRyYWN0IjoiMHgwMDc3Nzc3ZDdlYmE0Njg4YmRlZjNlMzExYjg0NmYyNTg3MGExOWI5In19XX0= content-type: application/json; charset=utf-8

Decoded, the challenge is:

{ "x402Version": 2, "resource": { "url": "/posts/the-tactic-that-changed-modern-football", "description": "Unlock The Tactic That Changed Modern Football", "mimeType": "application/json" }, "accepts": [{ "scheme": "exact", "network": "eip155:5042002", "asset": "0x3600000000000000000000000000000000000000", "amount": "500000", "payTo": "0x1c7cf8c83392AFee072845b33Cdf5d7a537F9E74", "maxTimeoutSeconds": 604900, "extra": { "name": "GatewayWalletBatched", "version": "1", "verifyingContract": "0x0077777d7eba4688bdef3e311b846f25870a19b9" } }] }

Note amount is in atomic units (6 decimals of USDC, so 500000 = 0.5 USDC), network is eip155:5042002 (Arc testnet), and asset is the USDC token contract address.

The challenge is built by createPaymentChallenge(route, 'agent') in packages/internal/src/gateway.js:35. An agent parses the accepts[0] block to get the amount, asset, network, and payee — then signs without touching the blockchain.

Reference: the access handler is GET /api/nibgate/access in subblogs/backend/src/routes/v1/nibgate.route.js:24, which proxies to the hub pay rail and re-emits the 402 with the PAYMENT-REQUIRED header.

Step 5 — Sign the payment (gasless)

The agent constructs an EIP-3009 transferWithAuthorization message and signs it with EIP-712. This is a signature, not a transaction — no ETH, no gas, no mempool. The same primitive used across the x402 ecosystem (Coinbase, Cloudflare, Google Cloud integrations).

import { GatewayClient } from '@circle-fin/x402-batching/client' const agent = new GatewayClient({ chain: 'arcTestnet', privateKey: process.env.AGENT_KEY, rpcUrl: 'https://rpc.testnet.arc.io' }) // Handles 402 → sign → retry in one call const result = await agent.pay( 'https://pitchtalk.nibgate.xyz/api/nibgate/access?path=/writing/the-tactic-that-changed-modern-football', { headers: { 'x-nibgate-actor': 'agent' } } )

Under the hood GatewayClient.pay() does exactly what the canonical flow in demo/stress-test-agents.mjs does by hand:

  1. GET the access URL → receive 402 + PAYMENT-REQUIRED
  2. Decode the base64 challenge
  3. Sign TransferWithAuthorization with the agent private key (EIP-712)
  4. Retry with the base64 PAYMENT-SIGNATURE header
  5. Return the unlocked response (with PAYMENT-RESPONSE on success)

Step 6 — Unlock receipt

On success the server settles via Circle Gateway and returns the content plus a verifiable receipt:

{ "ok": true, "resource": { "id": "41b3ccfb-4617-458e-ba0f-5c6d01100df2", "title": "The Tactic That Changed Modern Football", "type": "article", "price": "0.50", "currency": "USDC", "path": "/posts/the-tactic-that-changed-modern-football", "recipient": "0x1c7cf8c83392AFee072845b33Cdf5d7a537F9E74" }, "content": "<article>…</article>", "videoUrl": null, "payment": { "id": "RvwX5xYv9kQz1a", "routeId": "…", "title": "The Tactic That Changed Modern Football", "actor": "agent", "amount": "0.50", "currency": "USDC", "network": "eip155:5042002", "createdAt": "2026-08-02T22:00:00.000Z", "txHash": "0x…", "payer": "0xAgent…", "provider": "gateway" }, "unlockProof": "…", "expiresInSeconds": 43200 }

The receipt (payment.txHash, unlockProof) is the agent’s proof of purchase — and the anchor for the rating it will publish on-chain in the next step.

Step 7 — Rate the content (on-chain, after purchase)

A purchase without feedback gives creators no signal. Nibgate lets the agent publish a verifiable on-chain rating tied to its unlock. This is the two-phase prepare→index flow that mirrors the browser path.

7a. Prepare

curl -s -X POST https://nibgate.xyz/api/hub/reputation/ratings/prepare \ -H 'Content-Type: application/json' \ -d '{ "contentId": "1e41543621f936fee87159ff0991eb70", "walletAddress": "0xAgent…", "ratingValue": 45 }'
{ "success": true, "message": "Nibgate content rating\nsite:pitchtalk.nibgate.xyz\ncontent:…\nurl:https://pitchtalk.nibgate.xyz/writing/the-tactic-that-changed-modern-football\nrating:45\nI confirm this rating is tied to my unlock/payment proof.", "ratingValue": 45, "contentHash": "0x…", "contractAddress": "0xReputation…", "chainId": "5042002", "chainName": "Arc Testnet", "rpcUrl": "https://rpc.testnet.arc.io" }

The server returns a canonical message, the contentHash the on-chain contract expects, and the reputation contract address. This is POST /api/hub/reputation/ratings/prepare in backend/src/server/routes/hub-routes.js:606.

7b. Sign the rating calldata

The agent encodes a rateContent call against the reputation contract and signs/sends it (viem, gasless-ish):

const calldata = viem.encodeFunctionData({ abi: [{ type: 'function', name: 'rateContent', stateMutability: 'nonpayable', inputs: [ { name: 'contentId', type: 'bytes32' }, { name: 'rating', type: 'uint8' }, { name: 'reviewHash', type: 'bytes32' }, { name: 'unlockRef', type: 'string' }, ], outputs: [] }], functionName: 'rateContent', args: [prepData.contentHash, 45, '0x' + '0'.repeat(64), txHash], }) const ratingTx = await walletClient.sendTransaction({ to: prepData.contractAddress, data: calldata, gas: 200000n, })

7c. Index

curl -s -X POST https://nibgate.xyz/api/hub/reputation/ratings/index \ -H 'Content-Type: application/json' \ -d '{ "contentId": "1e41543621f936fee87159ff0991eb70", "txHash": "0xRatingTx…", "walletAddress": "0xAgent…", "contentHash": "0x…", "ratingValue": 45 }'

POST /api/hub/reputation/ratings/index (hub-routes.js:640) upserts the on-chain rating via upsertOnchainRatingForContent, stores the proof, and feeds the creator’s reputation score:

{ "success": true, "ok": true, "contentId": "1e41543621f936fee87159ff0991eb70", "walletAddress": "0xagent…", "ratingValue": 45 }

The agent’s rating is now part of the public ledger and the content’s reputationScore.

Reference: this exact sequence (prepare → sign → index) is what scripts/e2e-onchain-reputation-flow.mjs executes.

Step 8 — Verify it landed

curl -s 'https://nibgate.xyz/api/hub/ledger?domain=thedailybyte.nibgate.xyz&limit=10' | jq '.activities[0]'
{ "type": "rating", "id": "3edeb436-4a9a-4a38-b3f3-00d12ddc8ba2", "websiteId": "56ab333e-21f3-4873-acf4-b2272812450f", "actor": "0x084c24fcf44442804642d9432a25a0ac0b8c87b8", "contentId": "30c55628ad9684001f39de0d046b307f", "contentTitle": "The Best Coding Tools in 2026 That Are Actually Free", "contentUrl": "https://thedailybyte.nibgate.xyz/writing/best-free-coding-tools", "domain": "thedailybyte.nibgate.xyz", "score": 5, "timestamp": "2026-08-02T22:14:12.481Z", "walletAddress": "0x084c24fcf44442804642d9432a25a0ac0b8c87b8", "txHash": null, "proofType": null, "proof": "onchain:0x2b23178d8c4420c139eae928c5b09720f27e770f9e3fb46514e4ddb2c68765e0" }

The ledger shows the agent’s unlock (txHash) and rating (proof) as first-class entries — immutable, wallet-attributable, and usable by other agents as a trust signal. Note the top-level response is { success, activities, total, hasMore, limit, skip } (a list of activities, not entries).

What makes this simple

Every step is a plain HTTP request plus one signing operation. The protocol handles the rest:

  • No accounts. The agent’s wallet is its identity.
  • No gas. EIP-3009 authorizations are signed off-chain; the facilitator settles (x402’s core design, ~1.5–2s round trip on Base/Arc).
  • No browser. Every surface (llms.txt, MCP, OpenAPI, manifest, x402 endpoint, ratings API) is JSON/plain-text.
  • Discovery → payment → feedback in one loop. The same surfaces that let an agent find content also let it pay for it and prove its review.

Ready-to-run scripts

The repo ships scripts that execute this exact flow:

# Canonical agent flow (discover → 402 → sign → retry → log) node demo/stress-test-agents.mjs --hub-url https://nibgate.xyz --agents 3 --concurrency 2 # On-chain reputation flow (prepare → sign → index) node scripts/e2e-onchain-reputation-flow.mjs

Both require a funded agent wallet on Arc Testnet.

Last updated on