Valiron
DocsLogin

Valiron Docs

Valiron provides trust middleware for autonomous agent traffic. It evaluates agent identity, reputation, and behavior at the application boundary, enabling policy-based access control before request handling.

Installation

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

Getting Started

The primary integration path is SDK middleware deployed within the API backend. Middleware evaluates each identified agent and returns a deterministic route decision before the application handler processes the request.

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 middleware integration — 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. Test trust decisions — use the playground before adding middleware to production routes
  4. Monitor traffic — inspect agent activity, usage, errors, and cost once your middleware is live

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 an upstream API 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, predictive risk, 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 chain-agnostic. 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

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 five 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
SelfWhether the agent is linked to a Self-verified eligible humanSelf Enterprise
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
selfPro / EnterpriseSelf eligible-human proof and optional Agent ID 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', 'self', '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.

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.

Predictive Risk

Valiron forecasts how likely an agent is to pass its next evaluation or safely handle the next protected action. The model combines recent sandbox scores, score trend, behavioral fingerprints, and production call history into a predicted next score, pass probability, risk direction, confidence, recommended policy, and suggested next tests.

Predictive risk is explainable: each forecast includes human-readable reasons such as worsening score trend, repeated 429 disrespect, elevated error rate, missing backoff behavior, or stable recovery after errors. Low-confidence forecasts mean Valiron has sparse evidence and should usually trigger another sandbox run before broadening production access.

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.

Self (Eligible-Human Proof)

Self verifies that an agent is linked to a real eligible human through Self Enterprise. Valiron creates a Self verification session, redirects the user to Self, verifies Self's signed webhook, and stores the result as the selectable self trust signal.

Self Agent ID can be included when creating the session. When present and confirmed, Valiron records it as a stronger sub-signal; it is not required for the base eligible-human proof.

const session = await valiron.createSelfSession('25459', {
  selfAgentId: 'self-agent-...',
});

console.log(session.self.verificationUrl);

Production integrations should use createSelfSession() plus Self's signed /operator/self/webhook delivery. Trusted-payload ingestion is disabled unless SELF_ALLOW_TRUSTED_PAYLOADS=true for local/internal tests.

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
Hosted wrappers / 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' | 'self' | 'icebreaker'>autoOptional selected scoring signals. Free supports 8004 and sandbox; Pro adds world, self, 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. Local, Web2, and non-ERC-8004 agents use a persistent Ethereum-style keypair for identity without needing an on-chain registration. Identity is verified via EIP-191 challenge-response.

Agent typeHeaderLookup path
ERC-8004 / Solanax-agent-id/operator/agent/:agentId
Local / Web2 / non-ERC-8004x-agent-address/operator/key/:agentAddress
Important: Do not send a local agent name such as my-agent to /operator/agent/:agentId. That path is for registry-backed on-chain agents. Local agents should generate or reuse a persistent keypair, complete auth.md, and use their verified x-agent-address.
// 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' }]

Self SDK Methods

Programmatic Self Enterprise session creation, status lookup, and profile retrieval. See Self in Trust Model for background.

// Create a Self Enterprise verification session
const session = await valiron.createSelfSession('25459', {
  selfAgentId: 'self-agent-...',
  successUrl: 'https://example.com/verified',
  failureUrl: 'https://example.com/failed',
});
console.log(session.self.verificationUrl);

// Check Self status
const status = await valiron.getSelfStatus('25459');
console.log(status.self.verified);

// Full Self eligible-human / Agent ID profile
const profile = await valiron.getSelfProfile('25459');
console.log(profile.humanTrust.hasHumanLink);

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 — checks x-agent-id first, then x-agent-address, minScore 65
// Includes a 30s client-side cache for payment retries and cold starts
// 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).

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)

API Scaffolding

API Scaffolding is a separate Valiron product for exposing existing HTTPS APIs through hosted, agent-facing URLs. It supports rapid distribution and evaluation while providing a migration path to first-party backend deployments protected by Valiron middleware.

Agent -> /wrap/{operatorId}/{path}
        -> x402 or MPP payment challenge, if price > 0
        -> optional Valiron trust gate
        -> rate limit + SSRF protection
        -> upstream API request

Dashboard Setup

  1. Open valiron.co/dashboard.
  2. Go to Make API Agent-Ready.
  3. Enter the public path, HTTP method, upstream API base URL, price, payment protocol, payment network, and payout wallet.
  4. Enable trust checks when the wrapper should require agent identity and trust evaluation before forwarding upstream.
  5. Configure upstream auth if your existing API needs a bearer token, API key header, or HMAC signing secret.
  6. Distribute the generated wrapper URL to agent clients.
FieldDescription
pathPublic wrapper path, for example /weather.
targetUrlExisting upstream HTTPS base URL. Valiron appends path when forwarding.
pricePerCallUse 0 for free wrappers, or a positive USD amount for paid calls.
paymentProtocolx402 or mpp.
paymentNetworkUse eip155:8453 or eip155:84532 for x402; tempo:4217 or tempo:42431 for MPP.
trustEnabledWhen true, Valiron requires agent identity headers and checks trust before forwarding.

HTTP API Setup

The dashboard uses the same JWT-authenticated endpoint you can call directly:

curl -X POST https://valiron-edge-proxy.onrender.com/operator/endpoints \
  -H "authorization: Bearer $VALIRON_JWT" \
  -H "content-type: application/json" \
  -d '{
    "path": "/weather",
    "method": "GET",
    "pricePerCall": 0.001,
    "targetUrl": "https://api.example.com",
    "paymentProtocol": "x402",
    "paymentNetwork": "eip155:8453",
    "payoutAddress": "0xYourPayoutWallet",
    "trustEnabled": false,
    "upstreamAuthType": "none"
  }'

Calling Wrappers

Agent clients call the generated public wrapper URL. Free wrappers forward immediately. Paid wrappers return a 402 Payment Required challenge and require the caller to retry with payment.

curl -i https://valiron-edge-proxy.onrender.com/wrap/{operatorId}/weather

x402 & MPP

x402 wrappers use Base-compatible HTTP payments. An unpaid request returns a 402 challenge, and the paid retry includes an X-PAYMENT header. MPP wrappers use WWW-Authenticate: Payment and retry with Authorization: Payment ....

pnpm exec mppx account create
pnpm exec mppx https://valiron-edge-proxy.onrender.com/wrap/{operatorId}/research

Deploy With Middleware Protection

For production deployments that require full backend control, implement Valiron middleware directly in the service using createValironGate() or ValironOperator.paywall().

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

const valiron = new ValironSDK();

app.use('/api/weather', createValironGate({
  sdk: valiron,
  minScore: 70,
}));