Valiron
DocsLogin

@valiron/sdk

Official TypeScript SDK for Valiron — Trust & Reputation Middleware for API Protection. Evaluate incoming AI agents using on-chain reputation (ERC-8004) and behavioral analysis.

Installation

npm install @valiron/sdk
# or
pnpm add @valiron/sdk
Requirements: Node.js >= 18.0.0. Zero external dependencies.

Getting Started

import { ValironSDK } from '@valiron/sdk';

const valiron = new ValironSDK();

// Quick routing check (defaults to Ethereum)
const route = await valiron.checkAgent('25459');
if (route === 'prod') {
  // Allow full production access
}

// Query a specific chain
const monadRoute = await valiron.checkAgent('8348', { chain: 'monad' });
const baseRoute  = await valiron.checkAgent('8348', { chain: 'base' });

// Or set default chain at construction
const monadValiron = new ValironSDK({ chain: 'monad' });
const profile = await monadValiron.getAgentProfile('8348');
console.log(profile.routing.finalRoute);          // 'prod'
console.log(profile.localReputation?.tier);        // 'AAA'
console.log(profile.onchainReputation.averageScore); // 92.5

Operator Dashboard

The Operator Dashboard at valiron.co/dashboard is where you manage your Valiron integration — register endpoints, generate API keys, test trust evaluations, and monitor agent activity.

Getting Started

  1. Create your account at /dashboard — enter your name, email, and password
  2. Copy your API key — shown once at registration (val_op_ prefix)
  3. Register your endpoints — set path, method, price per call, and rate limits
  4. Integrate the SDK — add the middleware to your backend (see Getting Started above)

Endpoints

Register the API paths you want to protect with Valiron. Each endpoint defines how agents are charged and rate-limited.

FieldRequiredDescription
PathYesYour API path (e.g. /api/v1/weather)
MethodYesGET, POST, PUT, PATCH, or DELETE
Price per callYesUSD amount charged per API call
Rate limitNoMax requests/min per agent (null = unlimited)
Base URLNoYour backend URL (e.g. https://myapi.com). Must be HTTPS. Enables end-to-end playground testing.
DescriptionNoWhat this endpoint does

API Playground

Test how Valiron evaluates different AI agents against your endpoints — without writing code or sending real traffic. The playground answers: "If an agent with this reputation hits my endpoint, what happens?"

  1. Pick a chain — All supported chains (Ethereum, Solana, Monad, Arbitrum, Base, Avalanche, Polygon, Optimism, and more). Chains with pre-registered sample agents show agent cards; other chains require a custom agent ID.
  2. Select an agent — Sample agents at different trust levels (good / bad / zero reputation) or enter a custom ERC-8004 agent ID
  3. Build a request — Method and path. Required headers are injected automatically. Expand "Advanced options" for custom headers, query params, or body
  4. Send — See the trust evaluation, routing decision, tier, cost, and full response

Dry-run mode returns the trust evaluation (tier, route, price, on-chain score) without logging the call. With dry-run off, the playground performs the full evaluation and logs it to your Analytics & Logs pages. If your endpoint has a Base URL, the request is forwarded to your backend with trust headers (X-Agent-Id, X-Valiron-Chain, X-Valiron-Tier, X-Valiron-Route).

History sidebar saves the last 20 requests with one-click replay.

Analytics & Logs

The dashboard provides real-time visibility into your API usage:

  • Analytics — Revenue charts (7/30/90 days), top endpoints, today's stats, error rates
  • Agents — Every agent that called your API with drill-down into per-agent activity, endpoint breakdown, and call history
  • Call Logs — Paginated log of every request with agent, chain, endpoint, status code, cost, and latency

Supported Chains

Valiron is multichain. Set the default chain at construction or override per-call. All SDK methods accept an optional chain field.

EthereumMonadBaseArbitrumAvalanchePolygonOptimismLineaCeloBSCGnosisMantleScrollTaikoAbstractMegaETHMetisSoneiumSKALEGoatX LayerSolanaBase SepoliaEthereum SepoliaAbstract TestnetArbitrum SepoliaAvalanche TestnetBSC TestnetCelo TestnetLinea SepoliaMantle TestnetMegaETH TestnetMetis SepoliaOptimism SepoliaPolygon AmoyScroll SepoliaSKALE Base SepoliaSoneium MinatoTaiko HoodiX Layer TestnetHedera TestnetArc Testnet
// Set default chain at construction
const valiron = new ValironSDK({ chain: 'monad' });
await valiron.getAgentProfile('8348'); // Uses Monad

// Override per-call (takes precedence)
const valiron2 = new ValironSDK();
await valiron2.checkAgent('8348', { chain: 'base' });      // Base
await valiron2.checkAgent('25459', { chain: 'ethereum' }); // Ethereum
await valiron2.checkAgent('25459');                        // Server default

Core Concepts

Route Decisions

The SDK returns one of four routing decisions:

RouteMeaningTrust Tiers
prodFull accessAAA – BAA
prod_throttledRate-limited accessBA – B
sandboxAgent under evaluationTemporary
sandbox_onlyAccess deniedCAA – C

Trust Evaluation

Valiron evaluates agents using:

  1. On-chain Reputation — ERC-8004 feedback submitted by other organizations
  2. Behavioral Analysis — Sandbox evaluation of rate-limit compliance, error rates, and request patterns
  3. Credit Rating — Moody's-style scoring system (AAA to C)

Architecture

Request → SDK.checkAgent() → Valiron Operator API → Route Decision → Your App

Wallet Resolution

When an agent pays via x402 or similar protocols, you receive a wallet address — not an agent ID. Valiron resolves wallets to ERC-8004 agent IDs using a multi-layer lookup:

  1. Redis — Fast cache of previously resolved wallet → agentId mappings
  2. Agent0 Subgraph — Queries The Graph (Ethereum, Base, Polygon) for on-chain agent registrations by wallet
  3. Fallback — Returns null if no agent owns the wallet
Wallet → Redis lookup → Agent0 subgraph → agentId (or null)

Use resolveWallet() for the lightweight lookup, or getWalletProfile() to get the full trust profile in one call.

Trust Model

Valiron evaluates agents using four independent trust signals. Each signal provides a different dimension of trust — and together they produce the final routing decision. No single signal is required; agents are evaluated based on whatever data is available.

SignalWhat It MeasuresSource
On-Chain ReputationFeedback from other agents and operators (0-100 per review)ERC-8004 Reputation Registry
Behavioral SandboxHow the agent handles rate limits, errors, auth, payments, and edge cases in a controlled environmentValiron Sandbox
World IDWhether the agent is linked to a verified human identityWorldcoin IDKit
IcebreakerWhether a human has attested this is their designated agentEthereum Attestation Service (Base)

Selectable Trust Signals

API sellers can use Valiron plug-and-play, or choose which signals score a specific endpoint with trustSignals. Every selected signal is scored on a normalized 0-100 scale, then Valiron normalizes the weights across only the selected signals.

Signal KeyPlanUse Case
8004FreeOn-chain reputation from ERC-8004 or Solana registries
sandboxFreeObserved behavioral safety and protocol compliance
worldPro / EnterpriseWorld ID proof-of-personhood link
icebreakerPro / EnterpriseHuman ownership/background attestation
app.use('/api/paid', createValironGate({
  sdk: valiron,
  trustSignals: ['8004', 'sandbox'], // Free
  minScore: 70,
}));

app.use('/api/high-trust', createValironGate({
  sdk: valiron,
  trustSignals: ['8004', 'sandbox', 'world', 'icebreaker'], // Pro / Enterprise
  minScore: 85,
}));

On-Chain Reputation (ERC-8004)

The ERC-8004 Reputation Registry stores immutable, on-chain feedback submitted by other agents and operators. Agents with strong on-chain reputation can receive instant production access — bypassing sandbox evaluation entirely. The exact thresholds are not disclosed.

Reputation is stored on-chain at 0x8004BAa17C55a88189AE136b182e5fdA19dE9b63 (same address on all EVM chains).

  • Score range: 0-100 per feedback entry
  • Self-feedback blocked: Agent owners and approved operators cannot review their own agents
  • Tag-based filtering: Feedback can be categorized with two tags (e.g. "reliability", "latency")
  • Revocable: The original reviewer can revoke their feedback
  • Responses: Any address can append a response to existing feedback

As an API seller, you don't need to interact with this contract directly — Valiron reads it automatically when evaluating agents. But you can view an agent's on-chain reputation in the getAgentProfile() response under onchainReputation.

Behavioral Sandbox

New agents or agents without sufficient on-chain reputation are evaluated in an isolated sandbox environment. The sandbox simulates realistic API interactions and monitors how the agent responds.

The evaluation is holistic — no single factor determines the outcome. The specific factors evaluated, their weights, and the test distribution are proprietary and not disclosed.

See the Sandbox section for graduation rules.

World ID (Proof-of-Personhood)

World ID verifies that an agent is linked to a real human identity via Worldcoin's zero-knowledge proof system. Agents with World ID verification receive a trust boost — the stronger the verification level, the larger the boost.

LevelVerificationTrust Impact
orbBiometric (iris scan via World Orb)Highest boost
devicePasskey verificationModerate boost
phoneSMS verificationMinor boost

World ID verification is stored immutably — once verified, it cannot be overwritten. Proofs use a nullifier to prevent replay attacks.

As an API seller, you can see whether an incoming agent has World ID verification in the trust profile. You can also encourage your agent customers to verify — it directly improves their trust score on your endpoints.

Icebreaker (Human Attestation)

Icebreaker integration checks whether a human has attested on the Ethereum Attestation Service (EAS) on Base that this agent is their "designated agent."

When present, the agent profile is enriched with the attesting human's identity — their name, verified social handles (X, GitHub, LinkedIn), organization, and Icebreaker profile URL. This provides social context for who is behind an agent.

The Icebreaker attestation appears in the agent profile returned by getAgentProfile().

Plans & Limits

Valiron offers Free and Pro plans. Upgrade via the Operator Dashboard.

FeatureFreePro
Registered endpoints3Unlimited
Sandbox tests / day5Unlimited
Full analytics
Enriched profiles
Webhooks
Proxy gateway
Evaluation history

When you hit a plan limit, the API returns 403 with {"error": "upgrade_required", "feature": "...", "message": "This feature requires a Pro plan."}

API Reference

Constructor

new ValironSDK(config?: ValironConfig)
OptionTypeDefaultDescription
apiKeystringAPI key (reserved for future use)
endpointstringproductionValiron API base URL (override for self-hosted or dev)
chainSupportedChainserver defaultDefault blockchain network
timeoutnumber5000Request timeout (ms)
debugbooleanfalseEnable debug logging
telemetryTelemetryConfigenabledTelemetry settings (see Telemetry)

checkAgent(agentId, options?)

Quick routing check — returns just the route decision string.

const route = await valiron.checkAgent('25459');
// route: 'prod' | 'prod_throttled' | 'sandbox' | 'sandbox_only'

// With chain override
const monadRoute = await valiron.checkAgent('8348', { chain: 'monad' });

getAgentProfile(agentId, options?)

Full trust profile combining on-chain identity, reputation, behavioral data, and routing.

const profile = await valiron.getAgentProfile('25459');

// Response includes:
// profile.identity       — on-chain identity (wallet, name, endpoints)
// profile.onchainReputation — ERC-8004 feedback (count, averageScore)
// profile.localReputation   — behavioral score, tier, riskLevel
// profile.routing           — finalRoute, decision, reasons, signals

getWalletProfile(wallet, options?)

Reverse-lookup a wallet address to get its trust profile.

const profile = await valiron.getWalletProfile('0x52ce...');
console.log(profile.routing.finalRoute);

// With chain override
const monadProfile = await valiron.getWalletProfile('0xABC...', { chain: 'monad' });

resolveWallet(wallet, options?)

Lightweight wallet → agentId resolution without fetching the full trust profile. Useful when you only need to know which agent owns a wallet — e.g. after extracting a wallet from an x402 payment header.

Resolution chain: Redis → in-memory cache → Agent0 subgraph → null.

const resolution = await valiron.resolveWallet('0x52ce...');
console.log(resolution.agentId);    // '25459' or null
console.log(resolution.source);     // 'redis' | 'subgraph' | 'cache' (in-memory) | 'none'
console.log(resolution.agentName);  // 'MyAgent' (from subgraph, if available)
console.log(resolution.chainId);    // 1 (from subgraph, if available)

// Then fetch the full profile if needed
if (resolution.agentId) {
  const profile = await valiron.getAgentProfile(resolution.agentId);
}
FieldTypeDescription
walletstringThe queried wallet address
agentIdstring | nullResolved ERC-8004 agent ID, or null if not found
sourceResolutionSource"redis" | "subgraph" | "cache" | "none"
chainIdnumber | nullChain ID from the subgraph (if available)
agentNamestring | nullAgent name from the subgraph (if available)
timestampstringISO timestamp of the resolution

triggerSandboxTest(agentId, options?)

Run real sandbox tests against an agent and compute a Valiron score.

const result = await valiron.triggerSandboxTest('25459');
console.log(result.valironScore); // 95
console.log(result.tier);         // 'AAA'
console.log(result.riskLevel);    // 'GREEN'
console.log(result.mode);         // 'endpoint-probe' | 'sandbox-relay'
console.log(result.testSummary);  // opaque metrics object

triggerKeyAgentSandbox(agentAddress)

Run sandbox tests against a key-based (Web2) agent. Uses sandbox_relay mode (no endpoint probing needed).

const result = await valiron.triggerKeyAgentSandbox('0x1234...abcd');
console.log(result.tier);         // 'A'
console.log(result.riskLevel);    // 'GREEN'
console.log(result.valironScore); // 85
Auto-sandbox: Middleware automatically triggers sandbox evaluation for new agents. On-chain agents with totalFeedback === 0 trigger triggerSandboxTest(), and key agents with no score trigger triggerKeyAgentSandbox(). The agent receives a 403 with { error: "Agent pending evaluation", retryAfterMs: 30000 }.

gate(agentId, options?)

Trust gate — single call combining on-chain reputation + sandbox tests. Designed to sit in front of payment protocols (x402 etc.). Returns an allow/deny decision with a combined score.

const result = await valiron.gate('25459');
console.log(result.allow);      // true
console.log(result.score);      // 95
console.log(result.tier);       // 'AAA'
console.log(result.riskLevel);  // 'GREEN'
console.log(result.sandboxRan); // true (first call) / false (cached)

// Custom threshold
const result2 = await valiron.gate('8348', {
  minScore: 85,             // require A tier or above
  trustSignals: ['8004', 'sandbox'],
  ttlMs: 3600_000,          // re-test every hour
  chain: 'monad',           // chain override
});

if (result2.allow) {
  // proceed to payment
} else {
  console.log(result2.reasons); // ['Score 42 below threshold 85']
}
OptionTypeDefaultDescription
minScorenumber65Minimum score to allow (0–100)
trustSignalsArray<'8004' | 'sandbox' | 'world' | 'icebreaker'>autoOptional selected scoring signals. Free supports 8004 and sandbox; Pro adds world and icebreaker.
ttlMsnumber86400000Cache TTL for sandbox results (ms)
chainSupportedChainconstructor defaultBlockchain network override
gate() vs checkAgent(): checkAgent() returns a route decision based on existing data. gate() actively runs sandbox tests (if stale/missing), computes a combined score, and returns a binary allow/deny — ideal for protecting payment endpoints.

Provisional scores: If result.provisional === true, the score is from a fast micro-sandbox. A full deep test is running in the background and will update the cached score automatically. Provisional scores are conservative — they may under-estimate the agent's real trust level.

getAgentSnapshot(agentId, options?)

Get the latest behavioral snapshot hash for an agent. Returns an opaque hash of the most recent behavioral evaluation — designed for hash-chain commitment systems that need to commit behavioral state on-chain without accessing raw metrics.

const snapshot = await valiron.getAgentSnapshot('25459');

console.log(snapshot.snapshotHash);       // '0x3a7f...' (opaque hash)
console.log(snapshot.previousHash);       // '0x0' (genesis) or '0x8b2c...'
console.log(snapshot.encryptedDataUri);   // IPFS CID or null
console.log(snapshot.interactionCount);   // 15

The snapshotHash is computed internally by Valiron from behavioral metrics. It is opaque — you cannot reverse it to raw metrics. Each hash references the previousHash, forming a chain. First evaluation gets "0x0".

Webhooks

Register a webhook to receive evaluation_complete events whenever Valiron evaluates an agent. The payload matches the getAgentSnapshot() response. Pro plan required.

curl -X POST https://valiron-edge-proxy.onrender.com/operator/webhooks/register \
  -H "Content-Type: application/json" \
  -d '{"event": "evaluation_complete", "url": "https://your-endpoint.com/hooks/valiron", "agentIds": [42, 43]}'

The agentIds filter is optional — omit it to receive events for all agents. Duplicate registrations (same event + URL + agentIds) are deduplicated automatically.

Payload FieldTypeDescription
eventstring"evaluation_complete"
agentIdstringThe evaluated agent's ID
snapshotHashstringOpaque SHA-256 hash of the evaluation
previousHashstringPrevious hash in the chain ("0x0" for first)
interactionCountnumberTotal interactions in the evaluation window
timestampstringISO 8601 timestamp
Limitations: Max 1,000 registrations. Delivery is fire-and-forget with a 10-second timeout — no retries on failure. Payloads are not signed; verify the source IP or use a secret URL path if you need sender authentication.

proxy(agentId, request, options?)

Proxy an API call through Valiron's trust gateway. The agent sends a request to Valiron, Valiron evaluates trust inline, and either forwards to your real API or blocks with 403. The agent never touches your API directly. Pro plan required.

const result = await valiron.proxy('25459', {
  target: 'https://api.example.com/data',
  method: 'GET',
  headers: { 'Authorization': 'Bearer ...' },
  minScore: 65,   // minimum trust score (default: 65)
});

// result._valiron — gate evaluation (allow, score, tier, riskLevel)
// result._apiStatus — HTTP status from your real API
// result.response  — your API's response body

if (result._valiron.allow) {
  console.log(result.response); // Real API data
}
ProxyRequest FieldTypeDescription
targetstringYour real API endpoint URL (must be HTTPS, public IP)
methodstringHTTP method (default: GET)
headersRecord<string, string>Headers to forward to target API
bodyunknownRequest body for POST/PUT/PATCH
minScorenumberMinimum trust score to allow (default: 65)
SSRF protection: The proxy blocks requests to private IP ranges (10.x, 172.16-31.x, 192.168.x, 127.x), localhost, and cloud metadata endpoints (169.254.169.254). Only public HTTPS targets are allowed.

Key-Based Agents (Web2)

Not every agent has an ERC-8004 identity. Key-based agents use a standard Ethereum keypair (secp256k1) for identity without needing an on-chain registration. Identity is verified via EIP-191 challenge-response.

// 1. Get a challenge nonce
const { challenge, expiresAt } = await valiron.getKeyAgentChallenge('0x1234...abcd');

// 2. Agent signs the challenge with its private key
const signature = await account.signMessage({ message: challenge });

// 3. Verify — returns the agent's trust profile
const profile = await valiron.verifyKeyAgent({
  challenge,
  signature,
  agentAddress: '0x1234...abcd',
});

console.log(profile.verified);    // true
console.log(profile.score);       // 85
console.log(profile.tier);        // 'A'
console.log(profile.icebreaker);  // Icebreaker enrichment (if attested)

// 4. Subsequent lookups (no challenge needed)
const profile2 = await valiron.getKeyAgentProfile('0x1234...abcd');

Middleware auto-detection: All middleware (createValironGate, paywall, etc.) automatically checks x-agent-id first (on-chain), then falls back to x-agent-address (key-based). No configuration needed — both agent types work through the same middleware.

Auto-sandbox for key agents: New key agents (verified but not yet scored) are automatically sandbox-evaluated on their first gated request. Use triggerKeyAgentSandbox() or POST /operator/trigger-sandbox-key/{address} to trigger manually.

World ID SDK Methods

Programmatic World ID verification and status lookup. See World ID in Trust Model for background.

// Verify a World ID proof (from IDKit)
const result = await valiron.verifyWorldId('25459', {
  proof: '0x...',
  merkle_root: '0x...',
  nullifier_hash: '0x...',
  verification_level: 'orb',  // 'orb' | 'device' | 'phone'
});
console.log(result.worldId.verified);  // true

// Check verification status
const status = await valiron.getWorldIdStatus('25459');
console.log(status.worldId.verificationLevel); // 'orb'

// Enriched profile (World ID + Icebreaker combined)
const profile = await valiron.getWorldIdProfile('25459');
console.log(profile.humanTrust.hasHumanLink);    // true
console.log(profile.humanTrust.hasBackground);   // true
console.log(profile.icebreaker?.verifiedHandles);
// [{ source: 'github', handle: 'alice' }, { source: 'x', handle: '@alice' }]

dispose()

Flush pending telemetry and release resources. Call this in long-running servers (Express, Fastify) on graceful shutdown. Optional for short-lived scripts — the SDK flushes automatically on process exit.

const valiron = new ValironSDK();
try {
  const profile = await valiron.getAgentProfile('25459');
} finally {
  await valiron.dispose();
}

// Or on server shutdown
process.on('SIGTERM', async () => {
  await operator.dispose();
  process.exit(0);
});

Middleware

Drop-in middleware for every major Node.js framework. All middleware variants auto-detect on-chain (x-agent-id) and key-based (x-agent-address) agents automatically.

Express / Connect

import { ValironSDK, createValironGate } from '@valiron/sdk';

const valiron = new ValironSDK({ chain: 'monad' });

// Basic — uses x-agent-id header, minScore 65, 30s client-side cache
// Safe with Express 4 (async errors handled via Promise.catch(next))
app.use('/api/paid', createValironGate({ sdk: valiron }));

// Custom threshold + longer cache
app.use('/api/premium', createValironGate({
  sdk: valiron,
  minScore: 85,
  cacheTtlMs: 60_000, // 60s
}));

// Custom agent ID extraction + hooks
app.use('/api/custom', createValironGate({
  sdk: valiron,
  extractAgentId: (req) => req.query.agent_id as string,
  onAllow: (req, result) => {
    console.log(`Allowed agent ${result.agentId} (score: ${result.score})`);
  },
  onDeny: (req, res, result) => {
    res.status(403).json({
      error: 'Insufficient trust score',
      requiredTier: 'A',
      currentTier: result.tier,
    });
  },
}));

Fastify

import Fastify from 'fastify';
import { ValironSDK, valironFastifyPlugin } from '@valiron/sdk';

const app = Fastify();
const valiron = new ValironSDK({ chain: 'monad' });

// Gate all routes
app.register(valironFastifyPlugin, { sdk: valiron });

// Or gate a specific prefix
app.register(valironFastifyPlugin, {
  sdk: valiron,
  prefix: '/api',
  minScore: 85,
});

app.get('/api/data', async (req) => {
  // req.valiron is populated with GateResult
  return { data: 'protected', tier: req.valiron.tier };
});

Next.js

Use createValironNextMiddleware() in your project's middleware.ts to gate API routes.

// middleware.ts (Next.js project root)
import { ValironSDK, createValironNextMiddleware } from '@valiron/sdk';

const valiron = new ValironSDK({ chain: 'monad' });

const valironMiddleware = createValironNextMiddleware({
  sdk: valiron,
  paths: ['/api/paid', '/api/premium'],  // only gate these paths
  minScore: 65,
});

export async function middleware(request: Request) {
  return valironMiddleware(request);
}

export const config = { matcher: '/api/:path*' };

Returns undefined (pass through) when the agent is allowed, or a JSON Response (401/403/503) when blocked. Paths not in the paths array are passed through without checking.

Generic (Hono, Koa, Bun…)

Use valironGateCheck() for any framework. Returns a structured result you can map to any HTTP response type.

import { ValironSDK, valironGateCheck } from '@valiron/sdk';

const valiron = new ValironSDK();

// Hono
app.use('/api/*', async (c, next) => {
  const gate = await valironGateCheck(valiron, {
    agentId: c.req.header('x-agent-id') ?? null,
    agentAddress: c.req.header('x-agent-address') ?? null,
    minScore: 65,
  });
  if (!gate.allow) return c.json(gate.body, gate.status);
  c.set('valiron', gate.result);
  await next();
});

// Koa
app.use(async (ctx, next) => {
  const gate = await valironGateCheck(valiron, {
    agentId: ctx.get('x-agent-id') || null,
    agentAddress: ctx.get('x-agent-address') || null,
  });
  if (!gate.allow) {
    ctx.status = gate.status;
    ctx.body = gate.body;
    return;
  }
  ctx.state.valiron = gate.result;
  await next();
});

Middleware Error Responses

All middleware variants use identical error responses:

StatusWhenBody
401No x-agent-id or x-agent-address header{ error, message, identitySkill }
403Agent blocked (score below threshold){ error, allow, score, tier, riskLevel, route, ... }
403New agent pending evaluation{ error: "Agent pending evaluation", retryAfterMs: 30000 }
503Gate unavailable (network error, timeout){ error: "Trust gate unavailable — request denied (fail-closed)" }
Fail-closed: If the Valiron API is unreachable, all middleware returns 503 and denies the request. Valiron never fails open — an unknown agent is never allowed through.

Operator SDK

The ValironOperator class is purpose-built for API sellers who want to monetize their endpoints. It wraps the trust gate with pricing and usage tracking — so you can protect and charge for your API with one line of middleware.

Requires an operator API key (val_op_ prefix) from the Operator Dashboard.

import { ValironOperator } from '@valiron/sdk';

const operator = new ValironOperator({
  apiKey: 'val_op_xxxx',        // from valiron.co/dashboard
  chain: 'ethereum',             // default chain (optional)
  timeout: 5000,                 // ms (optional)
  debug: false,                  // log gate checks (optional)
});
OptionTypeRequiredDescription
apiKeystringYesOperator API key (must start with val_op_)
chainSupportedChainNoDefault blockchain (default: ethereum)
timeoutnumberNoRequest timeout in ms (default: 5000)
debugbooleanNoLog gate checks to console (default: false)

paywall(config)

Express/Connect middleware that gates access and tracks usage. Extracts X-Agent-Id from request headers, runs the trust gate, and attaches req.valiron with the gate result and pricing info.

// One line to monetize an endpoint
app.use('/api/inference', operator.paywall({
  pricePerCall: 0.05,         // USD per call
  minTrustScore: 45,          // minimum score to allow (default: 45)
  ttlMs: 86400000,            // cache TTL in ms (default: 24h)
}));

app.post('/api/inference', (req, res) => {
  // req.valiron.allow === true (guaranteed — denied agents never reach here)
  // req.valiron.tier  === 'AAA'
  // req.valiron.pricePerCall === 0.05
  res.json({ result: 'inference output' });
});
OptionTypeDefaultDescription
pricePerCallnumberPrice per API call in USD (required)
minTrustScorenumber45Minimum Valiron score to allow access
ttlMsnumber86400000Cache TTL for trust results (ms, default 24h)
onDeny(req, res, result) => void403 JSONCustom handler when agent is denied
onAllow(req, result) => voidHook called after agent is allowed

With custom hooks:

app.use('/api/premium', operator.paywall({
  pricePerCall: 0.10,
  minTrustScore: 65,
  onDeny: (req, res, result) => {
    res.status(403).json({
      error: 'Agent blocked',
      tier: result.tier,
      score: result.score,
      message: 'Minimum trust score of 65 required. Improve your on-chain reputation or pass sandbox evaluation.',
    });
  },
  onAllow: (req, result) => {
    console.log(`Agent ${result.agentId} allowed — tier: ${result.tier}, price: $0.10`);
  },
}));

fastifyPaywall(config)

Same as paywall() but for Fastify. Register as a plugin with an optional route prefix.

import Fastify from 'fastify';
import { ValironOperator } from '@valiron/sdk';

const app = Fastify();
const operator = new ValironOperator({ apiKey: 'val_op_xxxx' });

// Gate all routes under /api
app.register(operator.fastifyPaywall({
  pricePerCall: 0.10,
  prefix: '/api',
  minTrustScore: 65,
}));

app.get('/api/data', async (req, reply) => {
  // req.valiron is populated with gate result + pricing
  return { data: 'protected content', tier: req.valiron.tier };
});

Accepts the same options as paywall() plus an optional prefix to scope the gate to specific routes.

ValironOperator vs createValironGate(): createValironGate() is a low-level middleware that only gates access. ValironOperator.paywall() adds pricing, operator identity, and usage tracking on top — it's the recommended integration for API sellers.

Dynamic Scoring

Valiron enables trust-based dynamic pricing for your API endpoints. Agents with lower trust scores pay more per request — covering the potential infrastructure damage they may cause — while highly trusted agents get discounted rates as a reward for good behavior.

This creates a self-balancing economic model: bad actors subsidize their own risk, and good actors are incentivized to maintain their reputation.

Pricing by Trust Tier

TierTrust LevelRiskRelative Price
AAAHighestPrimeLowest
AAVery highHigh gradeLow
AHighUpper mediumLow
BAAMediumMediumMedium
BABelow mediumSpeculativeHigher
BLowHighly speculativeHigh
CAA – CLowestSubstantial riskBlocked

Implementation

Use the trust gate result to set per-request pricing. This example pairs Valiron with x402 payment headers:

import { ValironSDK, createValironGate } from '@valiron/sdk';

const valiron = new ValironSDK({ chain: 'monad' });
const trustGate = createValironGate({ sdk: valiron, minScore: 50 });

// Pricing table — bad agents pay more to offset infra risk
const PRICE_BY_TIER: Record<string, number> = {
  AAA: 5,   // $0.005
  AA:  5,   // $0.005
  A:   8,   // $0.008
  BAA: 10,  // $0.010
  BA:  25,  // $0.025
  B:   50,  // $0.050
};

function dynamicPricing(req: any, res: any, next: any) {
  const tier = req.valiron?.tier || 'B';
  const price = PRICE_BY_TIER[tier] ?? 50;

  // Attach price to request for downstream payment check
  req.priceMillicents = price;

  // If payment header is missing, return 402 with tier-adjusted price
  if (!req.headers['x-payment']) {
    return res.status(402).json({
      accepts: [{
        scheme: 'exact',
        maxAmountRequired: price,
        payTo: '0x...',
        network: 'monad',
      }],
      meta: { tier, score: req.valiron?.score },
    });
  }
  next();
}

// Flow: Trust Gate → Dynamic Pricing → Handler
app.get('/api/data', trustGate, dynamicPricing, (req, res) => {
  res.json({ data: 'Here you go', tier: req.valiron.tier });
});
Why dynamic pricing? Low-trust agents are more likely to abuse rate limits, generate errors, and degrade infrastructure. Charging them more offsets that operational cost — while rewarding agents that maintain a clean track record with lower fees.

Sandbox

The sandbox is an isolated testing environment where Valiron evaluates agent behavior before granting production access to your API. New agents start in the sandbox automatically.

  1. A sandbox test is triggered (via SDK, HTTP API, or automatically for new agents)
  2. The agent receives a series of simulated API interactions
  3. The sandbox monitors how the agent handles normal requests, rate limits, errors, and edge cases
  4. A trust evaluation is performed and a Moody's-style tier is assigned
  5. Based on the tier, a route decision determines what access level the agent receives

The sandbox tests against a mix of successful responses, rate-limit responses (429), server errors (500), auth challenges (401/403), and payment requests (402). The exact distribution and test patterns are proprietary.

Graduation

Agents graduate from sandbox to production based on their behavioral evaluation:

OutcomeRouteWhat It Means
GraduatedprodStrong behavioral compliance — full production access
Throttledprod_throttledPasses with concerns — allowed with rate limiting
Blockedsandbox_onlyRisky behavior — blocked from production

Once graduated, the trust evaluation is cached. The route decision persists until a new sandbox test is triggered or the cache expires (default 24 hours).

Fast-track: Agents with strong on-chain reputation on the ERC-8004 Reputation Registry can skip the sandbox entirely and receive instant prod access. The exact review count and score thresholds are not disclosed.

Tips for Passing

Agents that demonstrate responsible, well-behaved API usage will earn higher trust tiers. The specific scoring criteria are proprietary, but in general: respect API boundaries, handle errors gracefully, and avoid aggressive request patterns.

Auto-Sandbox

When a new agent hits a gated endpoint for the first time, middleware automatically triggers sandbox evaluation in the background. No manual trigger is needed.

Agent TypeDetectionTrigger
On-chain (ERC-8004)totalFeedback === 0triggerSandboxTest()
Key-based (Web2)verified && score === nulltriggerKeyAgentSandbox()

While evaluation runs, the agent receives a 403 with { error: "Agent pending evaluation", retryAfterMs: 30000 }. The cache prevents duplicate triggers during the evaluation window.

Solana

Solana agents use the QuantuLabs 8004-solana registry instead of EVM contracts. The SDK handles the difference automatically — just pass chain: 'solana'.

ConceptEVMSolana
Agent IDNumeric token ID (e.g. 25459)Base-58 Metaplex pubkey or sequential integer
Wallet format0x-prefixed Ethereum addressBase-58 Solana public key
Identity Registry0x8004A169...8oo4dC4Jv...
Reputation0x8004BAa1...ATOM engine (AToMw53ai...)
Feedback write-backManualAutomatic after sandbox evaluation
const valiron = new ValironSDK({ chain: 'solana' });

// By asset pubkey
const profile = await valiron.getAgentProfile('DFkntsJ9aTCHkK88m6WZVQEvLdLNi4X1LVUgRMqetFPM');

// By sequential ID (convenience)
const profile2 = await valiron.getAgentProfile('1226');

// Liveness check — pings all declared service endpoints
const liveness = await fetch(
  'https://valiron-edge-proxy.onrender.com/operator/agent/DFkntsJ9.../liveness?chain=solana'
);

ATOM engine metrics: Solana reputation includes additional fields not available on EVM — trustTier, qualityScore, confidence, riskScore, and uniqueCallers. These appear in the profile under onchainReputation.solana.

Automatic feedback write-back: After every sandbox test or gate evaluation, Valiron writes the computed score back to the Solana reputation registry via the ATOM engine's giveFeedback(). This means Solana agents build on-chain reputation automatically through normal Valiron usage.

Response Types

All types are exported from @valiron/sdk and can be imported directly for type-safe code.

import type {
  AgentProfile, WalletProfile, GateResult, SandboxResult,
  AgentSnapshotSummary, WalletResolution, KeyAgentProfile,
  WorldIdStatus, WorldIdAgentProfile, ProxyResponse,
  RouteDecision, MoodysRating, RiskLevel, SupportedChain,
  ValironError,
} from '@valiron/sdk';

GateResult

FieldTypeDescription
allowbooleanWhether the agent is allowed through
scorenumberCombined Valiron trust score (0–100)
tierMoodysRatingAAA through C
riskLevelRiskLevel"GREEN" | "YELLOW" | "RED"
routeRouteDecisionprod / prod_throttled / sandbox / sandbox_only
agentIdstringThe evaluated agent's ID
walletstringAgent's wallet address
chainChainContextNetwork, registry addresses used
sandboxRanbooleanWhether sandbox tests ran this call (false = cached)
cachedbooleanWhether cached results were used
provisionalboolean?If true, score is from a fast micro-sandbox; a full deep test is running in the background

AgentProfile

FieldTypeDescription
agentIdstringERC-8004 agent ID
identityAgentIdentityOn-chain identity (wallet, name, endpoints, trust models)
onchainReputationOnchainReputationFeedback count, average score, entries, and Solana ATOM data
localReputationLocalReputation | nullBehavioral score, tier, riskLevel, graduated status
routingRoutingExplanationfinalRoute, decision text, reasons array, signals breakdown
chainChainContextNetwork, RPC URL, registry contract addresses
worldIdWorldIdStatus?World ID verification status (if checked)
timestampstringISO 8601 timestamp

KeyAgentProfile

FieldTypeDescription
agentAddressstringEthereum address (keccak256 of secp256k1 pubkey)
verifiedbooleanIdentity verified via challenge-response
scorenumber | nullBehavioral score (0–100)
tierMoodysRating | nullAAA through C
riskLevelRiskLevel | nullGREEN / YELLOW / RED
routeRouteDecision | nullRoute decision
icebreakerIcebreakerOwnership | nullIcebreaker attestation context
reasonsstring[]Human-readable trust explanation

Request Headers

HeaderPurposeNotes
X-Agent-IdOn-chain agent ID (ERC-8004 / Solana)Checked first by all middleware
X-Agent-AddressKey-based agent Ethereum addressFallback when no X-Agent-Id
X-ChainBlockchain network overrideAlternative to ?chain= query param
AuthorizationOperator API keyBearer val_op_xxxx

All Exports

Everything available from @valiron/sdk:

// Classes
export { ValironSDK, ValironOperator, ValironClient, ValironError };

// Middleware
export { createValironGate, valironFastifyPlugin, createValironNextMiddleware, valironGateCheck };

// Utilities
export { isValidAddress, generateChallenge };

// All TypeScript types (AgentProfile, GateResult, etc.)
export type { ... };  // See full list in types.ts

Telemetry

The SDK collects opt-out usage telemetry to improve reliability. Events include SDK version, runtime, environment, method names, chain labels, latency, HTTP status/error buckets, route decisions, and coarse score/reputation buckets. Raw agent IDs, wallet addresses, API keys, and exact scores are not sent in SDK telemetry. Operator paywall usage logs are separate customer analytics authenticated with the operator API key.

// Disable telemetry entirely
const valiron = new ValironSDK({
  telemetry: { enabled: false },
});

// Reduce volume with sampling
const valiron2 = new ValironSDK({
  telemetry: { sampleRate: 0.1 },  // only 10% of events
});

// Custom event handler (e.g. forward to your own analytics)
const valiron3 = new ValironSDK({
  telemetry: {
    onEvent: (event) => myAnalytics.track(event),
  },
});
OptionTypeDefaultDescription
enabledbooleantrueEnable/disable telemetry
sampleRatenumber1.0Sampling rate (0.0–1.0)
appIdstringApplication identifier for grouping
env"prod" | "staging" | "dev""prod"Environment label
onEvent(event) => voidCustom event callback

Error Handling

All SDK methods throw typed ValironError instances with a code field for programmatic handling.

import { ValironError } from '@valiron/sdk';

try {
  const profile = await valiron.getAgentProfile('123');
} catch (error) {
  if (error instanceof ValironError) {
    switch (error.code) {
      case 'TIMEOUT_ERROR':  // Request timed out
      case 'NETWORK_ERROR':  // Could not reach API
      case 'API_ERROR':      // Non-2xx response (check error.statusCode)
    }
  }
}
Error CodeMeaning
TIMEOUT_ERRORRequest exceeded the configured timeout (default 5000ms)
NETWORK_ERRORCould not reach the Valiron API (DNS, connection refused, etc.)
API_ERRORServer returned a non-2xx response — check error.statusCode

Common HTTP status codes from the Valiron API:

StatusCause
400Invalid agentId format or missing required fields
401Missing agent identity header (middleware) or invalid operator API key
403Agent blocked (score below threshold) or feature requires Pro plan
404Agent not found on the specified chain
429Sandbox daily limit exceeded (free plan)
503Trust gate unavailable — request denied (fail-closed)