x402-agent-score
v0.1.2
Published
Hono middleware to screen payer wallets before a paid x402 route runs
Maintainers
Readme
x402-agent-score
Hono middleware that checks the DJD Agent Score of the wallet paying your x402 API, and optionally blocks low-trust payers before your route does work.
Scores are based on on-chain signals: wallet age, transaction history, ETH balance, USDC activity, Basename ownership, and other screening inputs. Scores range 0-100.
Install
npm install x402-agent-score @x402/core @x402/evm @x402/hono honoUsage
import { HTTPFacilitatorClient } from '@x402/core/server'
import { ExactEvmScheme } from '@x402/evm/exact/server'
import { paymentMiddlewareFromConfig } from '@x402/hono'
import { Hono } from 'hono'
import { agentScoreGate } from 'x402-agent-score'
const app = new Hono()
const facilitator = new HTTPFacilitatorClient({ url: 'https://x402.org/facilitator' })
app.use(
paymentMiddlewareFromConfig(
{
'GET /my-api': {
accepts: {
scheme: 'exact',
network: 'eip155:8453',
payTo: '0xYourPayToAddress',
price: '$0.01',
},
description: 'Protected x402 endpoint',
},
},
facilitator,
[{ network: 'eip155:8453', server: new ExactEvmScheme() }],
),
)
// Run this after x402 payment verification.
app.use(agentScoreGate({
minScore: 25,
onUnknown: 'allow',
}))
app.get('/my-api', (c) => c.json({ result: 'ok' }))agentScoreGate() should run after the x402 middleware so it reads a verified x402 payment header, not an untrusted client-supplied value.
Every response gets three headers:
| Header | Value |
|--------|-------|
| X-Agent-Score | 0-100, or unscored if not yet cached |
| X-Agent-Tier | Elite / Trusted / Established / Emerging / Unverified / Unknown |
| X-Agent-Recommendation | proceed / proceed_with_caution / insufficient_history / high_risk / flagged_for_review |
The first request from a new wallet typically returns unscored, Unknown, and insufficient_history while the cache warms in the background.
Options
agentScoreGate({
// Minimum score to allow. Below this -> 403. Default: 0 (headers only, nothing blocked)
minScore: 25,
// What to do for wallets with no score yet. Default: 'allow'
// 'allow' -> let through, fetch score async for next request
// 'reject' -> return 403 until the wallet has been scored
onUnknown: 'allow',
// How to get the paying wallet from Hono context.
// Default order:
// 1. c.get('x402PayerAddress')
// 2. decoded PAYMENT-SIGNATURE / X-PAYMENT header from x402 clients
// 3. X-Agent-Wallet header
// 4. ?wallet query param
getWallet: (c) => c.get('myPayerAddress'),
// Score API base URL. Default: https://djdagentscore.dev
apiUrl: 'https://djdagentscore.dev',
// Local cache TTL (ms). Avoids a score API call on every request. Default: 5 min
cacheTtl: 300_000,
})How it works
- The middleware extracts the paying wallet address from x402 headers or your custom context.
- If the wallet has a cached score, it enforces
minScoreand adds decision headers. - If the wallet is unknown, it fires an async score fetch to warm the cache, then either allows or rejects based on
onUnknown. - The cache is in-process (a
Map). Scores are refreshed aftercacheTtlms.
The async-fetch design means the first request from any wallet is never delayed. It passes through while the score is fetched in the background, so the second request gets enforcement.
Extracting the wallet from x402 requests
The default wallet extractor tries these in order:
c.get('x402PayerAddress')if your own middleware sets it- Decoded
PAYMENT-SIGNATUREorX-PAYMENTx402 payment header X-Agent-Walletrequest header?walletquery parameter
If none of these work for your setup, provide getWallet:
agentScoreGate({
getWallet: (c) => {
return c.req.header('x-paying-wallet')
},
})Screening policy
To require a minimum trust score before serving any paid request:
agentScoreGate({
minScore: 20,
onUnknown: 'allow',
})A rejected request receives:
{
"error": "agent_score_too_low",
"score": 12,
"tier": "Unverified",
"minRequired": 20,
"improve": "https://djdagentscore.dev/docs"
}Rejected responses still include X-Agent-Score, X-Agent-Tier, and X-Agent-Recommendation headers so you can log or meter the decision consistently.
Optional identity context
The middleware does not require an identity profile. If your workflow uses identity metadata elsewhere, keep that as supporting context after the screening step rather than as the primary reason to trust a wallet.
Reference example
Full Hono example: examples/x402-hono.ts
License
MIT
