# Valiron integration documentation Source: https://www.valiron.co/docs/agents/AGENT-READY-APIS.md # API Scaffolding API Scaffolding is a separate Valiron product for exposing existing HTTPS APIs through hosted, agent-facing URLs. It can add x402 or MPP payment handling, optional Valiron trust checks, rate limits, upstream forwarding, and usage logs without requiring immediate SDK middleware integration. Use this flow when Valiron should host the payment and optional trust layer for an existing HTTPS API: ```text Agent or client -> Valiron-hosted wrapper URL -> x402 or MPP payment check -> optional Valiron trust check -> provider's existing API -> response returned through Valiron ``` > **Important: protect the origin.** A hosted wrapper evaluates and logs only > requests sent to its Valiron URL. It is not a network firewall in front of a > separately public API origin. If callers can reach your origin directly, they > can bypass the wrapper's payment, trust, rate-limit, and analytics path. > Publish the generated wrapper URL as the agent-facing URL and configure your > origin to accept only authenticated requests from Valiron. The wrapper is intentionally narrow: Valiron forwards valid HTTP requests to an existing upstream API. It does not need direct database access, internal service access, or provider infrastructure credentials beyond the optional upstream auth secret needed to call the API. ## When To Use This Use API Scaffolding when: - You already have an HTTPS API and want to sell per-call access to agents. - You want x402 or MPP payment challenges without implementing those protocols yourself. - You want Valiron trust checks before paid traffic reaches your API. - You need a no-code or low-code path from an existing API to an agent-compatible endpoint. Use the SDK middleware instead when: - You want payments to be handled entirely by your own server. - You need custom payment terms, subscriptions, account billing, or business-specific authorization. - Valiron should run directly in the API backend as the primary trust and policy enforcement layer. ## Provider Setup Providers configure one wrapper per public endpoint. | Field | Required | Description | |-------|----------|-------------| | Public path | Yes | Path callers use on Valiron, for example `/weather`. | | HTTP method | Yes | `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, or `HEAD`. | | Upstream base URL | Yes | Existing HTTPS API base URL, for example `https://api.example.com`. | | Price per call | Yes | USD amount charged for paid requests. Use `0` for a free wrapper. | | Payment protocol | Yes | `x402` or `MPP`. | | Payment network | Yes | x402: `eip155:8453` or `eip155:84532`; MPP: `tempo:4217` or `tempo:42431`. | | Payout wallet | Paid only | EVM address receiving payment. | | Upstream auth | Required to prevent origin bypass | Auth Valiron adds when forwarding to your upstream. Use `hmac` for a public origin. | | Rate limit | No | Max requests per minute per client. | | Trust check | No | Whether callers must pass Valiron agent trust evaluation before forwarding. | Example existing API: ```text GET https://api.example.com/weather ``` Example Valiron URL: ```text GET https://valiron-edge-proxy.onrender.com/wrap/{operatorId}/weather ``` Valiron preserves query strings and appends the public wrapper path to the upstream base URL. If your upstream base URL is `https://api.example.com/v1` and your public path is `/weather`, Valiron forwards to: ```text https://api.example.com/v1/weather ``` ## Dashboard Flow 1. Open [valiron.co/dashboard](https://www.valiron.co/dashboard). 2. Go to **Make API Agent-Ready**. 3. Click **Make API Agent-Ready**. 4. Enter the upstream URL, public path, method, price, protocol, network, and payout wallet. 5. Choose whether Valiron trust checks are required. 6. Configure upstream authentication. For a public origin, choose `hmac` and store the same secret in your origin's verification middleware. 7. Create the wrapper. 8. Distribute only the generated Valiron URL to agent clients or API customers. 9. Verify that a direct request to your origin is rejected and a request to the wrapper is recorded in Valiron call logs. Create, list, and deactivate wrappers in the dashboard. ## Calling A Wrapper Call the generated URL directly: ```bash curl -i https://valiron-edge-proxy.onrender.com/wrap/{operatorId}/weather ``` For a free wrapper, Valiron forwards immediately and returns the upstream response with Valiron wrapper headers: ```text x-valiron-wrapper-id: ... x-valiron-payment-protocol: free x-valiron-trust-enabled: false ``` For a paid x402 wrapper without payment, Valiron returns `402` and an x402 payment challenge: ```text HTTP/1.1 402 Payment Required x-payment-required: ... ``` For a paid MPP wrapper without payment, Valiron returns `402` and an MPP challenge: ```text HTTP/1.1 402 Payment Required WWW-Authenticate: Payment ... ``` ## x402 Paid Client Use an x402-capable client to retry with payment. The example below uses: - `@x402/fetch` - `@x402/core/client` - `@x402/evm/exact/client` - `viem/accounts` Minimal client shape: ```typescript import { wrapFetchWithPayment } from "@x402/fetch"; import { x402Client } from "@x402/core/client"; import { ExactEvmScheme } from "@x402/evm/exact/client"; import { privateKeyToAccount } from "viem/accounts"; const account = privateKeyToAccount(process.env.BUYER_PRIVATE_KEY as `0x${string}`); const client = new x402Client(); client.register("eip155:*", new ExactEvmScheme(account)); const fetchWithPayment = wrapFetchWithPayment(fetch, client); const response = await fetchWithPayment( "https://valiron-edge-proxy.onrender.com/wrap/{operatorId}/weather", { method: "GET", headers: { "x-agent-id": "25459" } } ); console.log(response.status); console.log(await response.text()); ``` The buyer wallet must hold the required token on the selected x402 network. For Base mainnet, the default production path expects USDC on Base. ## MPP Paid Client Valiron MPP support uses the official `mppx` SDK with the Tempo `charge` intent. Server behavior: - Unpaid request returns `402`. - Response includes `WWW-Authenticate: Payment ...`. - Paid request includes `Authorization: Payment ...`. - Successful paid response includes `Payment-Receipt`. Recommended testnet client flow: ```bash pnpm exec mppx account create pnpm exec mppx https://valiron-edge-proxy.onrender.com/wrap/{operatorId}/research ``` Use `tempo:42431` for Tempo testnet and `tempo:4217` for Tempo mainnet. Default Tempo currencies from `mppx`: | Network | Chain ID | Default currency | |---------|----------|------------------| | Tempo mainnet | `4217` | USDC (`0x20C000000000000000000000b9537d11c60E8b50`) | | Tempo testnet | `42431` | pathUSD (`0x20c0000000000000000000000000000000000000`) | ## Optional Trust Checks When `trustEnabled` is `false`, Valiron only handles payment, rate limiting, upstream auth, and forwarding. When `trustEnabled` is `true`, callers must identify the agent: ```text x-agent-id: 25459 ``` Valiron evaluates the agent before forwarding. If the agent is denied, the upstream API is not called. Use trust checks when: - You want to block risky agents even if they can pay. - You want route decisions and call logs tied to agent IDs. - You plan to vary pricing, limits, or access based on trust tiers. Use payment-only wrappers when: - You want the lowest-friction paid endpoint. - You do not need agent identity yet. - You are testing x402 or MPP integration. ## Upstream Auth Valiron stores the configured secret encrypted and injects or derives it only when forwarding a request that has reached the wrapper. This is how your origin distinguishes an authenticated wrapper request from a direct public request. For a public API origin, configure upstream authentication before announcing or indexing the wrapper. Otherwise, a caller can send traffic directly to the origin and bypass Valiron entirely. `none` is appropriate only when the origin is already inaccessible to untrusted callers or bypass is intentionally acceptable. Supported auth modes: | Mode | Behavior | |------|----------| | `none` | No upstream auth is added. | | `bearer` | Adds `Authorization: Bearer `. | | `api_key` | Adds the secret to the configured header name. | | `hmac` | Signs the request using the secret and adds signature headers. | The calling agent never sees your upstream secret. ### Recommended production pattern: HMAC origin verification Choose `hmac` for an origin that is publicly reachable. Valiron sends: ```text x-valiron-signature: sha256= x-valiron-timestamp: ``` Your origin must reject requests when the signature is missing, invalid, or too old. Verify the signature against the request method, public wrapper path, raw body SHA-256, and timestamp with the shared secret configured on the wrapper. Use constant-time signature comparison and a short timestamp window to reduce replay risk. Do **not** treat headers such as `x-valiron-wrapper-id`, `x-valiron-payment-protocol`, or `x-valiron-trust-enabled` as proof that a request came through Valiron. They are request metadata, not a credential, and can be forged by a caller that reaches your origin directly. ### Origin-lockdown checklist Before production: 1. Set `upstreamAuthType` to `hmac` and configure a unique secret. 2. Deploy origin middleware that verifies the HMAC and timestamp before the API handler runs. 3. Make the Valiron `/wrap/{operatorId}/{path}` URL the only public URL in agent discovery metadata, examples, and client configuration. 4. Send a direct request to the origin without the signature and confirm a `401` or `403` response. 5. Send a request through the wrapper and confirm the expected payment/trust result and a corresponding Valiron call-log entry. ## Security Defaults In production, Valiron wrappers: - Require HTTPS upstream URLs. - Block localhost, private IP ranges, link-local IPs, metadata hosts, and internal hostnames. - Resolve upstream DNS and block private resolved IPs. - Strip hop-by-hop and sensitive inbound headers before forwarding. - Do not forward inbound `Authorization`, `Cookie`, `x-payment`, or `payment-signature` headers to the upstream. - Add Valiron wrapper metadata headers to forwarded requests. - Apply per-endpoint rate limits. - Enforce request body size limits. - Time out slow upstream calls. ## Current Limits The first wrapper release supports: - Per-call x402 payments. - Per-call MPP Tempo charge payments. - Free wrappers. - Optional trust checks. - Optional upstream auth injection. - Per-endpoint rate limits. It does not yet support: - MPP sessions or subscriptions. - Multi-upstream routing. - Cross-protocol fallback on a single endpoint. - Non-HTTPS production upstreams. --- Source: https://www.valiron.co/docs/agents/API-REFERENCE.md # Valiron API Reference Machine-readable contract: [Valiron OpenAPI](https://www.valiron.co/openapi.json). [MCP setup](https://www.valiron.co/docs/agents/MCP.md). Base URL: `https://valiron-edge-proxy.onrender.com` Supported integration endpoints: - **Trust evaluation** (`/operator/agent/*`, `/operator/gate/*`, etc.) — Profile reads, runtime gate and identity-verification requests require an operator key; Pro trust signals and wallet intelligence require a Pro account with `Authorization: Bearer val_op_...`. - **Agent-ready wrappers** (`/wrap/:operatorId/*`) — Public agent-facing URLs created from Dashboard endpoint configs. These can enforce x402/MPP payment, optional trust checks, rate limits, and upstream forwarding. --- ## Authentication Get an operator API key from [the dashboard](https://www.valiron.co/dashboard). Send `Authorization: Bearer val_op_...` from your backend for profile/status reads and trust operations. Missing, invalid, or revoked credentials return HTTP 401. Keep keys out of browser code and public repositories. Health and key-identity enrollment remain accessible without an operator key. Enrollment proves control of an agent key; it does not authorize profile reads or protected actions. Human verification uses signed proofs/provider callbacks. The private Icebreaker lookup also accepts a verified agent session for that agent's own address. Manage accounts, keys, and analytics through the website. ## Access and data boundaries Profile endpoints require operator authentication and return identity and trust summaries. They do not return raw behavioral metrics, stored-evidence links, RPC URLs, internal errors, or verification-provider records. Self and World ID responses return an allowlisted verification summary; nullifiers, credential subjects, and provider storage references are private. Sandbox runs require an operator API key. Enriched profiles, the trust-gated proxy, and webhook registration require a Pro operator API key. Webhook deliveries are scoped to the operator that initiated the evaluation and the selected chain. Legacy global evaluation history and platform statistics are restricted to Valiron administrators; view your own account analytics in the dashboard. The gate also requires agent challenge-response headers (`x-agent-address` plus a valid `x-agent-session`, or a signed fresh challenge). Operator credentials do not replace agent identity. See [authentication](https://www.valiron.co/auth.md). ## Monthly request allowance Free includes **100,000 metered API requests per account per UTC calendar month**. Request 100,000 is allowed; subsequent requests return HTTP 429 with `code: "MONTHLY_REQUEST_LIMIT_EXCEEDED"`, `error: "upgrade_required"`, `limit`, `used`, `resetsAt`, and `upgradeUrl`. Upgrade to Pro or wait until the first of the next month at 00:00 UTC. Pro ($149/month) and Enterprise have no monthly request cap; existing feature gates, per-endpoint rate limits and traffic protections still apply. Crossing the limit never automatically subscribes or charges an account. The shared account allowance counts admitted calls to: - `POST /operator/gate/:agentId` - `POST /operator/identity/verify` - `POST /operator/trigger-sandbox/:agentId` and `/operator/trigger-sandbox-key/:agentAddress` - `POST /proxy/:agentId` (still Pro-only) - Any configured `/wrap/:operatorId/*` request, charged to the endpoint owner. Direct metered calls require `Authorization: Bearer val_op_...`. Gate/proxy agent identity requirements still apply. Wrappers resolve the account from the stored endpoint; an internal trust check is included in the wrapper request, not counted again. Each attempt admitted by the monthly counter counts, even if payment, trust or upstream work later fails. Requests rejected by authentication or the monthly limit do not count. Summary profile/discovery reads, identity challenges, health, account management, checkout, and analytics are outside this allowance. Responses include `X-Valiron-Monthly-Used` and `X-Valiron-Monthly-Reset`. Free responses also include `X-Valiron-Monthly-Limit` and `X-Valiron-Monthly-Remaining`. A quota rejection includes `Retry-After`. If persistent usage storage is unavailable, metered calls return HTTP 503; there is no process-local fallback that could bypass the allowance. ## Trust Evaluation Endpoints ### POST /operator/identity/verify Normalize and verify a provider-backed agent identity proof. This endpoint is provider-independent. SDK 1.3 exposes it as `verifyAgentIdentity()` and provides dedicated middleware for `x-valiron-identity-*` proof headers. The ANS adapter and provider credentials run inside Valiron's hosted service. An empty body returns `identityStatus: "anonymous"`. Supplying an agent ID with an incomplete or failed proof returns HTTP 200 with `identityStatus: "claimed"` and a machine-readable `failureReason`. Only a validated authority binding, fresh signature, and unused nonce return `identityStatus: "verified"`. #### Request body ```json { "provider": "ans", "agentId": "ans://v1.0.0.sales-agent.acme.com", "signature": "BASE64URL_OR_0xHEX_SIGNATURE", "timestamp": "2026-09-04T12:00:00.000Z", "nonce": "nonce-0123456789abcdef", "requestDigest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "keyId": "optional-provider-key-id", "policy": { "anonymous": "challenge", "claimed": "block", "verified": "allow", "minReputationScore": 65, "belowMinimumScore": "limit", "mediumRisk": "limit", "highRisk": "block" } } ``` | Field | Type | Required | Description | | --- | --- | --- | --- | | `provider` | string | for a claimed identity | Registered resolver name. `ans` is implemented; DNS, DID, and API-key adapters are future integrations | | `agentId` | string | no | Provider identity. Omit it to classify the request as anonymous | | `signature` | string | for verification | Base64/base64url or `0x`-hex signature unless the resolver defines a provider-specific proof | | `timestamp` | ISO timestamp | for verification | Signed time; default acceptance window is five minutes | | `nonce` | string | for verification | 16–256 URL-safe characters; atomically claimed to prevent replay | | `requestDigest` | string | for verification | `sha256:` plus 64 hexadecimal characters for the protected request bytes | | `keyId` | string | no | Selects one provider-resolved verification key | | `policy` | object | no | Per-status and per-risk actions. Every action must be `allow`, `limit`, `challenge`, or `block` | The signature covers the exact canonical payload documented in [PROVIDER-IDENTITY.md](https://www.valiron.co/docs/agents/PROVIDER-IDENTITY.md#low-level-verification-request). SDK identity gates calculate `requestDigest` from the exact received request bytes rather than trusting a digest header. #### Response — verified ```json { "agentId": "ans://v1.0.0.sales-agent.acme.com", "provider": "ans", "organization": "Acme Corp", "identityStatus": "verified", "humanIdentified": false, "stableIdentityId": "identity:ans:", "credentialId": "7b93c61c-e261-488c-89a3-f948119be0a0", "credentialVersion": "1.0.0", "verifiedAt": "2026-09-04T12:00:00.000Z", "reputationScore": 82, "riskLevel": "low", "policyDecision": { "action": "allow", "reason": "identity_verified" } } ``` For ANS, `stableIdentityId` is derived from `agentHost`, so reputation and activity remain continuous across versioned registrations. `credentialId` is the Registry Authority UUID and `credentialVersion` is the resolved version. #### Response — claimed, resolver unavailable ```json { "agentId": "ans://v1.0.0.sales-agent.acme.com", "provider": "ans", "organization": null, "identityStatus": "claimed", "humanIdentified": false, "stableIdentityId": null, "verifiedAt": null, "failureReason": "resolver_unavailable", "reputationScore": null, "riskLevel": "unknown", "policyDecision": { "action": "challenge", "reason": "resolver_unavailable" } } ``` This response occurs when the requested provider is not registered. For ANS it also occurs when the deployment does not have the required ANS credentials and trusted CA configuration. #### Error responses | Status | Error | Meaning | | --- | --- | --- | | 400 | `invalid_identity_policy` | A policy is not an object, an action is unsupported, or `minReputationScore` is outside 0–100 | | 503 | `identity_verification_unavailable` | Valiron could not safely resolve identity or atomically claim replay state | See [Provider-Backed Identity Errors](https://www.valiron.co/docs/agents/ERRORS.md#provider-backed-identity-errors) for all `failureReason` values and retry guidance. --- ### GET /operator/agent/:agentId Retrieve the complete trust profile for an agent. ### Parameters | Parameter | Location | Type | Required | Description | |-----------|----------|------|----------|-------------| | `agentId` | path | string | yes | ERC-8004 token ID | | `chain` | query | string | no | Network override (default: ethereum) | ### Response — 200 OK ```json { "agentId": "25459", "identity": { "agentId": "25459", "wallet": "0x52ce...", "tokenUri": "data:application/json;base64,...", "name": "Agent Name", "image": "https://...", "description": "Agent description", "endpoints": { "agentWallet": "eip155:1:0x...", "api": "https://api.example.com" }, "trustModels": ["reputation_on_chain", "behavioral_sandbox"] }, "onchainReputation": { "feedbackCount": 12, "averageScore": 92.5 }, "routing": { "finalRoute": "prod", "meetsThreshold": true }, "chain": { "name": "ethereum", "chainId": 1 }, "timestamp": "2026-03-23T12:00:00.000Z" } ``` ### Error Responses | Status | Meaning | |--------|---------| | 404 | Agent not found in ERC-8004 registry | | 500 | Internal server error | --- ## GET /operator/wallet/:wallet Reverse-lookup a wallet address to get its trust profile. ### Parameters | Parameter | Location | Type | Required | Description | |-----------|----------|------|----------|-------------| | `wallet` | path | string | yes | Ethereum address (0x...) or Solana pubkey (base-58, with `chain=solana`) | | `chain` | query | string | no | Network override | ### Response — 200 OK Same structure as `GET /operator/agent/:agentId`. --- ## GET /operator/wallet-risk/:wallet (Pro) Return an explainable wallet-history assessment. Requires a Pro or Enterprise operator API key in `Authorization: Bearer val_op_...`. ### Parameters | Parameter | Location | Type | Required | Description | |-----------|----------|------|----------|-------------| | `wallet` | path | string | yes | EVM address or Solana public key | | `chain` | query | string | no | `ethereum`, `base`, `arbitrum`, `optimism`, `polygon`, or `solana` | ### Response — 200 OK ```json { "available": true, "wallet": "0x52ce...", "network": "base", "provider": "alchemy", "score": 78, "rawScore": 85, "risk": 22, "confidence": 0.81, "riskLevel": "LOW", "reasons": [ "Wallet has at least one year of history", "Score is based on a bounded transaction sample" ], "hardFlags": [], "features": { "transactionCount": 146, "activeDays": 41, "walletAgeDays": 620, "uniqueCounterparties": 77, "historyTruncated": true }, "observedAt": "2026-07-20T12:00:00.000Z", "expiresAt": "2026-07-20T18:00:00.000Z" } ``` `score` is trust-oriented: higher is better. `risk` is `100 - score`. `confidence` dampens sparse assessments toward neutral. `historyTruncated: true` means the score uses a bounded sample rather than complete transaction history. Provider failures return HTTP 200 with `available: false`, `provider: "none"`, and an `error` explaining why the signal was unavailable. Gate/profile endpoints exclude unavailable wallet intelligence from composite scoring. ### Error Responses | Status | Meaning | |--------|---------| | 400 | Invalid EVM or Solana wallet address | | 403 | Missing operator key or plan does not include enriched profiles | | 500 | Unexpected wallet-risk route failure | --- ## GET /operator/resolve-wallet/:wallet Lightweight wallet → agentId resolution. Returns just the agent ID and how it was resolved, without the full trust profile. Wallet resolution returns the associated agent ID when available. ### Parameters | Parameter | Location | Type | Required | Description | |-----------|----------|------|----------|-------------| | `wallet` | path | string | yes | Ethereum address (0x...) or Solana pubkey (base-58, with `chain=solana`) | | `chain` | query | string | no | Network override (default: ethereum) | ### Response — 200 OK ```json { "wallet": "0x52ce...", "agentId": "25459", "source": "subgraph", "chainId": 1, "agentName": "MyAgent", "timestamp": "2024-01-01T00:00:00.000Z" } ``` --- ## POST /operator/trigger-sandbox/:agentId Execute real-time sandbox tests against an agent and compute a trust evaluation. ### Parameters | Parameter | Location | Type | Required | Description | |-----------|----------|------|----------|-------------| | `agentId` | path | string | yes | ERC-8004 token ID | | `chain` | query | string | no | Network override | ### Response — 200 OK ```json { "ok": true, "agentId": "25459", "wallet": "0x52ce...", "tier": "AAA", "riskLevel": "GREEN", "meetsThreshold": true, "testSummary": {}, "chain": { "name": "ethereum", "chainId": 1 }, "message": "Sandbox evaluation complete" } ``` > **Note:** The `testSummary` object contains opaque test metrics. Its internal structure is proprietary and may change without notice. --- ## POST /operator/gate/:agentId Trust gate — combined on-chain reputation + sandbox check. Returns an allow/deny decision. Designed for protecting payment endpoints (x402, etc.). ### Parameters | Parameter | Location | Type | Required | Description | |-----------|----------|------|----------|-------------| | `agentId` | path | string | yes | ERC-8004 token ID | ### Request Body ```json { "minScore": 65, "trustSignals": ["8004", "sandbox", "wallet"], "ttlMs": 86400000 } ``` | Field | Type | Default | Description | |-------|------|---------|-------------| | `minScore` | number | 65 | Minimum composite trust score required to allow | | `trustSignals` | string[] | automatic | Selected signals. `wallet`, `world`, `self`, and `icebreaker` require Pro | | `ttlMs` | number | 86400000 | Cache TTL in milliseconds (default 24 hours) | ### Response — 200 OK ```json { "allow": true, "tier": "AAA", "riskLevel": "GREEN", "meetsThreshold": true, "route": "prod", "agentId": "25459", "wallet": "0x52ce...", "chain": { "name": "ethereum", "chainId": 1 }, "sandboxRan": false, "cached": true, "walletRisk": { "available": true, "score": 78, "risk": 22, "riskLevel": "LOW", "confidence": 0.81, "hardFlags": [] } } ``` ### Decision Logic 1. If the agent meets the trust threshold → `allow: true` 2. If the agent does not meet the threshold → `allow: false` 3. Cached sandbox results are reused within the `ttlMs` window 4. If no cached result exists, sandbox tests run automatically 5. If `wallet` is selected and available, its confidence-damped score is included in the composite result 6. Unavailable wallet history is excluded; any populated wallet hard flag forces `sandbox_only` --- ## GET /operator/agent/:agentId/snapshot Get the latest behavioral snapshot hash for an agent. Returns an opaque hash suitable for on-chain commitment systems. ### Parameters | Parameter | Location | Type | Required | Description | |-----------|----------|------|----------|-------------| | `agentId` | path | string | yes | ERC-8004 token ID | | `chain` | query | string | no | Network override | ### Response — 200 OK ```json { "agentId": "25459", "snapshotHash": "0x3a7f2b...", "previousHash": "0x0", "timestamp": "2026-04-01T12:00:00.000Z" } ``` ### Error Responses | Status | Meaning | |--------|---------| | 400 | Invalid agentId | | 404 | Agent not found or no snapshot available (trigger a sandbox evaluation first) | | 500 | Internal server error | --- ## POST /operator/webhooks/register Register a public HTTPS webhook with a Pro operator API key. Events are limited to evaluations initiated by that operator on the selected `chain`; registrations cannot subscribe to other operators. Existing registrations must be recreated after the privacy update. Set `?chain=` when registering; use `?chain=key` for key-based evaluations. ### Request Body ```json { "event": "evaluation_complete", "url": "https://your-endpoint.com/hooks/valiron", "agentIds": [42, 43] } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | `event` | string | yes | Must be `"evaluation_complete"` | | `url` | string | yes | HTTPS endpoint to receive webhook POST requests | | `agentIds` | number[] | no | Filter to specific agent IDs. Omit for your own evaluations on the selected chain. | ### Response — 201 Created ```json { "id": "a1b2c3d4-...", "event": "evaluation_complete", "url": "https://your-endpoint.com/hooks/valiron", "agentIds": [42, 43], "createdAt": "2026-04-01T12:00:00.000Z" } ``` ### Webhook Payload When an evaluation completes, Valiron POSTs the following to your registered URL: ```json { "event": "evaluation_complete", "agentId": "25459", "tier": "AAA", "riskLevel": "GREEN", "route": "prod", "meetsThreshold": true, "snapshotHash": "0x3a7f2b...", "previousHash": "0x8b2c1a...", "encryptedDataUri": null, "timestamp": "2026-04-01T12:05:00.000Z", "interactionCount": 16 } ``` #### Webhook Payload Fields | Field | Type | Description | |-------|------|-------------| | `event` | string | Always `"evaluation_complete"` | | `agentId` | string | The evaluated agent ID | | `tier` | string | Moody's-style trust tier (AAA–C) | | `riskLevel` | string | GREEN / YELLOW / RED | | `route` | string | Route decision (`prod`, `prod_throttled`, `sandbox`, `sandbox_only`) | | `meetsThreshold` | boolean | Whether the agent passed the trust gate | | `snapshotHash` | string | Deterministic hash of the behavioral evaluation | | `previousHash` | string | Hash from the prior evaluation | | `encryptedDataUri` | string\|null | IPFS CID of encrypted snapshot data | | `timestamp` | string | ISO 8601 timestamp | | `interactionCount` | number | Total interactions in the evaluation window | #### Webhook Limitations - **Maximum registrations:** 1,000 per operator - **Delivery:** Fire-and-forget — no retries on failure - **Timeout:** 10 seconds — your endpoint must respond within 10s - **Signatures:** Webhooks are not signed — verify via IP allowlisting or shared secrets if needed - **Events:** Only `evaluation_complete` is currently supported --- ## POST /proxy/:agentId (Pro) Forward a request through Valiron's edge proxy with automatic trust gating, logging, and SSRF protection. ### Parameters | Parameter | Location | Type | Required | Description | |-----------|----------|------|----------|-------------| | `agentId` | path | string | yes | Agent to gate | ### Request Body ```json { "targetUrl": "https://your-api.com/data", "method": "POST", "headers": { "Content-Type": "application/json" }, "body": "{\"query\": \"example\"}" } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | `targetUrl` | string | yes | Your origin URL to forward to | | `method` | string | no | HTTP method (default: `GET`) | | `headers` | object | no | Headers to forward | | `body` | string | no | Request body | ### Response — 200 OK ```json { "statusCode": 200, "responseHeaders": {}, "responseBody": "...", "responseMs": 145, "costCharged": "0.0500", "route": "prod", "tierResolved": "AA" } ``` > **SSRF Protection:** The proxy blocks requests to private IPs (10.x, 172.16-31.x, 192.168.x), localhost, link-local addresses, and cloud metadata endpoints (169.254.169.254). --- ## Key-Based Agent Endpoints For Web2 agents that don't have on-chain identities, Valiron supports key-based authentication using EIP-191 challenge-response. ### POST /operator/key/:agentAddress/challenge Get a challenge nonce for key-based authentication. | Parameter | Location | Type | Required | Description | |-----------|----------|------|----------|-------------| | `agentAddress` | path | string | yes | Ethereum address (0x...) | #### Response — 200 OK ```json { "challenge": "valiron-challenge-abc123...", "expiresAt": "2026-04-01T12:05:00.000Z", "agentAddress": "0x..." } ``` ### POST /operator/key/verify Verify a signed challenge to authenticate a key-based agent. #### Request Body ```json { "agentAddress": "0x...", "challenge": "valiron-challenge-abc123...", "signature": "0x..." } ``` #### Response — 200 OK ```json { "verified": true, "agentAddress": "0x...", "score": null, "tier": null, "riskLevel": null, "route": null, "icebreaker": null, "reasons": [], "timestamp": "2026-04-01T12:00:00.000Z" } ``` ### GET /operator/key/:agentAddress Get the summary profile of a key-based agent using your operator API key. Icebreaker context and reasons are redacted from this response. #### Response — 200 OK ```json { "agentAddress": "0x...", "verified": true, "score": 82, "tier": "A", "riskLevel": "GREEN", "route": "prod", "icebreaker": null, "reasons": [], "timestamp": "2026-04-01T12:00:00.000Z" } ``` ### GET /operator/key/:agentAddress/icebreaker Get the Icebreaker owner context for a verified key-based agent. Supply a Pro operator API key as `Authorization: Bearer val_op_...`. The agent may instead authenticate with its Valiron `x-agent-address` and `x-agent-session` headers. The route returns `401` for a missing agent session and `403` when the caller is neither that agent nor a Pro operator. ```typescript const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY }); const { icebreaker } = await valiron.getKeyAgentIcebreaker(agentAddress); ``` ```json { "agentAddress": "0x...", "icebreaker": { "attested": true, "uid": "0x...", "owner": "Jane Doe", "verifiedHandles": [{ "source": "github", "handle": "janedoe" }], "organization": "Acme", "profileUrl": "https://app.icebreaker.xyz/profiles/...", "credentialUrl": "https://app.icebreaker.xyz/credentials/..." } } ``` When no matching credential exists, `icebreaker` is `{ "attested": false }`. These are verified profile handles, not Icebreaker connections or mutuals. Valiron checks the off-chain EAS signature, UID, signer, schema, recipient, credential name, and expiry before returning `attested: true`. The lookup uses Icebreaker's profile API and does not independently check off-chain revocation. The Web2 middleware's behavioral score does not change when this attestation appears; the API seller must enforce any policy that uses it. --- ## World ID Endpoints Verify agent-human linkage via Worldcoin's zero-knowledge proof system. ### POST /operator/world-id/verify/:agentId Submit a World ID proof for an on-chain agent. `verification_level` is required and must be `orb`, `device`, or `phone`. ```json { "merkle_root": "0x...", "nullifier_hash": "0x...", "proof": "0x...", "verification_level": "orb" } ``` #### Response — 200 OK ```json { "ok": true, "agentId": "25459", "worldId": { "verified": true, "verificationLevel": "orb" }, "timestamp": "2026-04-01T12:00:00.000Z" } ``` ### GET /operator/world-id/status/:agentId Read verification status with your operator API key. ```json { "agentId": "25459", "worldId": { "verified": true, "verificationLevel": "orb" }, "timestamp": "2026-04-01T12:00:00.000Z" } ``` ### GET /operator/world-id/profile/:agentId Requires a Pro operator key. Returns `agentId`, the same allowlisted `worldId` summary, `identity`, `icebreaker`, `humanTrust`, `reasons`, and `timestamp`. `identity` can be `null`; `icebreaker` is `{ "attested": false }` when no attestation is found. The `humanTrust` object contains `hasHumanLink`, `hasBackground`, and `verificationLevel`. --- ## Self Endpoints Create Self Enterprise verification sessions, receive signed Self webhooks, and read Self eligible-human verification plus optional Self Agent ID binding. Use the `self` trust signal when an endpoint should consider Self proof during Valiron scoring. ### POST /operator/self/session/:agentId Create a Self Enterprise verification session for an agent. | Parameter | Location | Type | Required | Description | |-----------|----------|------|----------|-------------| | `agentId` | path | string | yes | ERC-8004 token ID | #### Request Body ```json { "selfAgentId": "self-agent-...", "selfAgentRegistry": "0x...", "successUrl": "https://example.com/verified", "failureUrl": "https://example.com/failed", "expiresInSeconds": 900, "metadata": {} } ``` #### Response — 200 OK ```json { "ok": true, "agentId": "25459", "self": { "sessionId": "sess_...", "externalUuid": "00000000-0000-0000-0000-000000000000", "verificationUrl": "https://verify.self.xyz/s/...", "status": "pending", "expiresAt": "2026-04-01T12:15:00.000Z" }, "timestamp": "2026-04-01T12:00:00.000Z" } ``` ### GET /operator/self/status/:agentId Check if an agent has a verified Self eligible-human link. ### GET /operator/self/profile/:agentId Requires a Pro operator key. Returns `self` eligibility and agent-binding predicates, `identity`, `humanTrust`, `reasons`, and `timestamp`. Provider identifiers are omitted from `self`. --- ## GET /operator/health Health check endpoint. ### Response — 200 OK ```json { "status": "ok", "supportedChains": ["ethereum", "monad", "arbitrum", "base", ...], "defaultChain": "ethereum" } ``` --- ## Solana Support All `/operator/*` endpoints support Solana agents when `chain=solana` is passed as a query parameter or `x-chain: solana` header. Solana agent identity and reputation data is provided by [QuantuLabs 8004-solana](https://8004.qnt.sh/), while EVM chains use the 8004 team's registry contracts. The two registries have different schemas — this is by design. ### Key Differences from EVM | Area | EVM | Solana | |------|-----|--------| | **Agent ID format** | Numeric token ID (e.g. `25459`) | Base-58 Metaplex Core asset pubkey (e.g. `GL4k...`) or sequential ID (e.g. `1`, `42`) | | **Wallet format** | `0x`-prefixed hex address | Base-58 public key | | **Identity source** | ERC-8004 `ownerOf()` on-chain call | QuantuLabs `loadAgent()` SDK call | | **Reputation source** | ERC-8004 `getSummary()` | QuantuLabs ATOM engine (`getEnrichedSummary()`) | | **Extra reputation fields** | — | `solana.trustTier`, `solana.qualityScore`, `solana.confidence`, `solana.riskScore`, `solana.uniqueCallers` | | **Wallet → Agent resolution** | Supported EVM registries | Supported Solana registry | | **Liveness check** | — | `isItAlive()` endpoint-by-endpoint health probe | | **Feedback write-back** | — | Valiron scores written on-chain via `giveFeedback()` when enabled by Valiron | ### Sequential Agent IDs Solana agents are primarily identified by their base-58 asset pubkey, but the QuantuLabs indexer also assigns sequential integer IDs (1, 2, 3, …). You can use either format: ```bash # By asset pubkey (primary) curl -H "Authorization: Bearer $VALIRON_API_KEY" "https://valiron-edge-proxy.onrender.com/operator/agent/GL4k...?chain=solana" # By sequential ID (convenience) curl -H "Authorization: Bearer $VALIRON_API_KEY" "https://valiron-edge-proxy.onrender.com/operator/agent/42?chain=solana" ``` When a sequential ID is used, the response includes a `sequentialId` field mapping back to the numeric ID. ### Liveness Check `GET /operator/agent/:agentId/liveness?chain=solana` Pings each service endpoint from the agent's on-chain metadata and returns a health report. Only available for Solana agents. **Response:** ```json { "agentId": "GL4k...", "chain": { "network": "solana", "cluster": "mainnet-beta" }, "liveness": { "status": "live", "okCount": 3, "totalPinged": 3, "skippedCount": 0, "results": [ { "type": "rest", "endpoint": "https://...", "ok": true, "latencyMs": 120 } ] } } ``` The `trigger-sandbox` endpoint also includes a `liveness` summary in its response for Solana agents. ### Feedback Write-Back When feedback write-back is enabled, Valiron automatically writes evaluation scores back to the Solana reputation registry after sandbox testing and gate evaluations. This closes the trust loop — other consumers of the 8004-solana registry can see Valiron's scores. Feedback is submitted as fire-and-forget using the `starred` tag with `tag2: "valiron"` for attribution. ### Solana-Specific Response Fields When querying a Solana agent, the `onchainReputation` object may include an additional `solana` block with ATOM engine metrics: ```json { "onchainReputation": { "count": "42", "averageScore": 88.5, "feedbackEntries": [], "totalFeedback": 42, "solana": { "trustTier": "trusted", "qualityScore": 92.1, "confidence": 0.87, "riskScore": 0.08, "uniqueCallers": 15 } } } ``` ### Example Requests ```bash # Get Solana agent profile curl -H "Authorization: Bearer $VALIRON_API_KEY" "https://valiron-edge-proxy.onrender.com/operator/agent/GL4k...?chain=solana" # Get Solana agent by sequential ID curl -H "Authorization: Bearer $VALIRON_API_KEY" "https://valiron-edge-proxy.onrender.com/operator/agent/42?chain=solana" # Gate a Solana agent curl -H "Authorization: Bearer $VALIRON_API_KEY" -X POST "https://valiron-edge-proxy.onrender.com/operator/gate/GL4k...?chain=solana" # Check liveness curl -H "Authorization: Bearer $VALIRON_API_KEY" "https://valiron-edge-proxy.onrender.com/operator/agent/GL4k.../liveness?chain=solana" # Look up by Solana wallet curl -H "Authorization: Bearer $VALIRON_API_KEY" "https://valiron-edge-proxy.onrender.com/operator/wallet/7xKX...?chain=solana" # Trigger sandbox for Solana agent curl -H "Authorization: Bearer $VALIRON_API_KEY" -X POST "https://valiron-edge-proxy.onrender.com/operator/trigger-sandbox/GL4k...?chain=solana" ``` ## Agent-Ready Wrapper Endpoint ### ALL /wrap/:operatorId/* Public agent-facing wrapper URL. This endpoint is created by `POST /operator/endpoints` or the **Make API Agent-Ready** dashboard flow. ```text https://valiron-edge-proxy.onrender.com/wrap/{operatorId}/{path} ``` The wrapper matches the operator ID, path, and HTTP method to an active endpoint config. It can enforce payment, optional trust checks, rate limits, SSRF protection, upstream auth injection, and request forwarding. These controls apply only to traffic sent to this wrapper URL. Protect a public upstream with `hmac` auth and reject direct, unsigned origin traffic. See [API Scaffolding](https://www.valiron.co/docs/agents/AGENT-READY-APIS.md#recommended-production-pattern-hmac-origin-verification). #### Caller Headers | Header | Required | Description | |--------|----------|-------------| | `X-PAYMENT` | paid x402 retry | x402 payment payload returned by an x402-capable client. | | `Authorization: Payment ...` | paid MPP retry | MPP payment authorization header. | | `x-agent-id` | if trust enabled | ERC-8004 agent ID. | | `x-agent-address` | not supported by hosted trust wrappers | Use SDK middleware in your own backend when you need key/address identity support. | #### Free Wrapper Response If `pricePerCall` is `0`, the wrapper forwards directly to the upstream API: ```bash curl https://valiron-edge-proxy.onrender.com/wrap/{operatorId}/status ``` #### x402 Paid Wrapper Response If `paymentProtocol` is `x402` and no valid payment is attached, the wrapper returns: ```http HTTP/1.1 402 Payment Required X-PAYMENT-RESPONSE: ... Content-Type: application/json ``` The caller should retry with a valid `X-PAYMENT` header. See [AGENT-READY-APIS.md](https://www.valiron.co/docs/agents/AGENT-READY-APIS.md#paid-x402-client) for a complete TypeScript client. #### MPP Paid Wrapper Response If `paymentProtocol` is `mpp` and no valid payment is attached, the wrapper returns: ```http HTTP/1.1 402 Payment Required WWW-Authenticate: Payment ... Content-Type: application/json ``` The caller should retry with `Authorization: Payment ...`. For command-line testing: ```bash pnpm exec mppx https://valiron-edge-proxy.onrender.com/wrap/{operatorId}/research ``` #### Error Responses | Status | Code | Meaning | |--------|------|---------| | 402 | `payment_required` | Paid wrapper needs valid x402 or MPP payment. | | 403 | `trust_denied` | Trust checks are enabled and the agent did not pass. | | 404 | `wrapper_not_found` | No active wrapper matched operator ID, path, and method. | | 413 | `payload_too_large` | Request body exceeds wrapper limit. | | 429 | `rate_limit_exceeded` | Caller exceeded wrapper rate limit. | | 502 | `wrapper_request_failed` | Upstream request failed or returned an invalid response. | --- --- Source: https://www.valiron.co/docs/agents/CHAINS.md # Supported Chains Valiron operates across 41 EVM blockchain networks plus Solana. ## EVM Chains The ERC-8004 contracts are deployed at the same addresses on every EVM chain. Identity and reputation data is provided by the [8004 team](https://erc8004.org). ### Contract Addresses (all EVM chains) | Contract | Address | |----------|---------| | Identity Registry | `0x8004A169FB4a3325136EB29fA0ceB6D2e539a432` | | Reputation Registry | `0x8004BAa17C55a88189AE136b182e5fdA19dE9b63` | ### Supported EVM Networks | Chain ID | Name | SDK Value | |----------|------|-----------| | — | Ethereum | `ethereum` | | — | Monad | `monad` | | — | Arbitrum | `arbitrum` | | — | Base | `base` | | — | Avalanche | `avalanche` | | — | Celo | `celo` | | — | Polygon | `polygon` | | — | Linea | `linea` | | — | Abstract | `abstract` | | — | BSC (Binance Smart Chain) | `bsc` | | — | Gnosis | `gnosis` | | — | Goat | `goat` | | — | Mantle | `mantle` | | — | MegaETH | `megaeth` | | — | Metis | `metis` | | — | Optimism | `optimism` | | — | Scroll | `scroll` | | — | SKALE Base | `skale_base` | | — | Soneium | `soneium` | | — | Taiko | `taiko` | | — | X Layer | `xlayer` | | — | Base Sepolia | `base_sepolia` | | — | Ethereum Sepolia | `ethereum_sepolia` | | — | Abstract Testnet | `abstract_testnet` | | — | Arbitrum Sepolia | `arbitrum_sepolia` | | — | Avalanche Testnet | `avalanche_testnet` | | — | BSC Testnet | `bsc_testnet` | | — | Celo Testnet | `celo_testnet` | | — | Linea Sepolia | `linea_sepolia` | | — | Mantle Testnet | `mantle_testnet` | | — | MegaETH Testnet | `megaeth_testnet` | | — | Metis Sepolia | `metis_sepolia` | | — | Optimism Sepolia | `optimism_sepolia` | | — | Polygon Amoy | `polygon_amoy` | | — | Scroll Sepolia | `scroll_sepolia` | | — | SKALE Base Sepolia | `skale_base_sepolia` | | — | Soneium Minato | `soneium_minato` | | — | Taiko Hoodi | `taiko_hoodi` | | — | X Layer Testnet | `xlayer_testnet` | | — | Hedera Testnet | `hedera_testnet` | | — | Arc Testnet | `arc_testnet` | ## Solana Solana support is powered by [QuantuLabs 8004-solana](https://8004.qnt.sh/) — a separate registry from the EVM 8004 contracts. | Network | SDK Value | Registry Provider | |---------|-----------|-------------------| | Solana Mainnet | `solana` | QuantuLabs 8004-solana | ### Program IDs (Solana) | Program | Address | |---------|---------| | Identity Registry | `8oo4dC4JvBLwy5tGgiH3WwK4B9PWxL9Z4XjA2jzkQMbQ` | | Reputation Registry (ATOM) | `AToMw53aiPQ8j7iHVb4fGt6nzUNxUhcPc3tbPBZuzVVb` | ### Key Differences - **Agent IDs** are base-58 Metaplex Core asset pubkeys (not numeric token IDs) - **Wallets** are base-58 Solana public keys (not `0x`-prefixed) - **Reputation** may include ATOM engine metrics: `trustTier`, `qualityScore`, `confidence`, `riskScore`, `uniqueCallers` - **Identity** is resolved via `loadAgent()` on the QuantuLabs SDK - **Wallet → Agent resolution** uses `getAgentsByOwner()` (no subgraph) ### Configuration | Environment Variable | Default | Description | |---------------------|---------|-------------| | `SOLANA_CLUSTER` | `mainnet-beta` | Solana cluster (`mainnet-beta` or `devnet`) | | `SOLANA_RPC_URL` | Public RPC | Custom Solana RPC endpoint for production use | ## Wallet Intelligence Coverage Wallet intelligence is available on a smaller network subset than identity and ERC-8004 reputation: | Network | SDK Value | History Provider | |---------|-----------|------------------| | Ethereum Mainnet | `ethereum` | Alchemy | | Base Mainnet | `base` | Alchemy | | Arbitrum Mainnet | `arbitrum` | Alchemy | | Optimism Mainnet | `optimism` | Alchemy | | Polygon Mainnet | `polygon` | Alchemy | | Solana Mainnet | `solana` | Helius | For other supported chains, identity and reputation continue to work, but a requested wallet assessment returns `available: false` and is excluded from composite scoring. | Environment Variable | Default | Description | |---------------------|---------|-------------| | `ALCHEMY_API_KEY` | — | Enables EVM wallet history on the five supported mainnets | | `HELIUS_API_KEY` | — | Enables Solana mainnet wallet history | | `WALLET_HISTORY_CACHE_TTL_SECONDS` | `21600` | Available-assessment cache duration in seconds | | `WALLET_HISTORY_TIMEOUT_MS` | `4000` | Per-provider request timeout in milliseconds | Wallet history is a bounded sample. See [TRUST-MODEL.md](https://www.valiron.co/docs/agents/TRUST-MODEL.md#wallet-intelligence) for scoring behavior and limitations. ## Specifying a Chain ### SDK ```typescript // At initialization (default for all calls) const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY, chain: "monad" }); // Per-call override const route = await valiron.checkAgent("25459", { chain: "arbitrum" }); ``` ### HTTP API ```bash # Query parameter curl -H "Authorization: Bearer $VALIRON_API_KEY" https://valiron-edge-proxy.onrender.com/operator/agent/25459?chain=monad ``` ## Querying Supported Chains ```bash curl https://valiron-edge-proxy.onrender.com/operator/health ``` Returns: ```json { "status": "ok", "supportedChains": ["ethereum", "monad", "arbitrum", ...], "defaultChain": "ethereum" } ``` --- Source: https://www.valiron.co/docs/agents/DASHBOARD.md # Operator Dashboard > Manage your Valiron integration from a single web interface — register endpoints, monitor agent activity, test trust evaluations, and view analytics. **Dashboard URL:** [https://www.valiron.co/dashboard](https://www.valiron.co/dashboard) --- ## Getting Access To create an account: 1. Go to [valiron.co/dashboard](https://www.valiron.co/dashboard) and click **Create account** 2. Enter your name, email, and password, or continue with Google or GitHub 3. On success, you'll see a **one-time API key** — copy it immediately (it won't be shown again) 4. Complete the same guided setup for every sign-up method: Account, Signals, Policy, Endpoint, Install, Deploy, and Finish Onboarding completion is stored on the operator account, so an unfinished setup resumes after email, Google, or GitHub login and on another browser. If the original one-time key is no longer available, the wizard can generate a dedicated setup key. Existing operators are not forced back through onboarding. The Signals step supports registered ERC-8004/Solana agents, persistent key-based agents, and ANS or other provider-backed identities. ANS is an agent identity option; it is not required to create a Valiron operator account. After registration, sign in with your email and password, Google, or GitHub. Sign in on the website to manage your account. Keep the operator API key in your backend environment. --- ## Overview **Route:** `/dashboard` Your landing page after signing in. Shows a summary of your integration at a glance: - **Top stats** — Total Revenue, Total Calls, Unique Agents, Avg Latency - **Secondary stats** — Active API Keys, Registered Endpoints, Calls Today, Plan + fee rate - **Recent Activity** — Last 5 call logs with method, path, agent, cost, and timestamp - **Quick Start** — 3-step guide: get API key → make an API agent-ready → test with agents --- ## Agents **Route:** `/dashboard/agents` View every AI agent that has called your API, sorted by last seen, call volume, spend, or error count. Each agent card shows: - Agent ID (ERC-8004 token ID) - Chain badges (multi-chain support) - Last seen, total calls, total spent, avg latency, error count **Click an agent** to drill into: - Predictive risk — forecasted next score, pass probability, trend, confidence, recommended policy, suggested tests, and plain-English reasons - Summary stats and first/last seen dates - Endpoint breakdown table — which of your endpoints they called, how many times, spend, avg latency, errors - Recent call log for that agent Predictive risk is computed from recent sandbox evaluations, behavioral fingerprints, and your operator call logs. It does not replace the trust gate. Low-confidence forecasts mean Valiron has sparse evidence and should usually trigger another sandbox run before broadening production access. --- ## Analytics **Route:** `/dashboard/analytics` Revenue and usage analytics with time-range filtering. - **Stats grid** — Total Revenue, Total Calls, Unique Agents, Avg Latency - **Today's stats** — Calls Today, Revenue Today, Error Rate (highlighted if > 5%) - **Daily Revenue chart** — Bar chart with tooltips (7 / 30 / 90 day range selector) - **Top Endpoints** — Ranked by call volume with revenue, avg latency, and unique agent count --- ## Call Logs **Route:** `/dashboard/logs` Paginated log of every API call made through your Valiron-gated endpoints. Each row shows: - Timestamp - Agent label + ID - Chain badge - Endpoint (method + path) - Status code (color-coded: green for 2xx, yellow for 4xx, red for 5xx) - Cost charged - Latency - Session ID **Filters:** - Time range: All time, Last 24h, 7 days, 30 days, 90 days - Pagination: 50 entries per page --- ## API Keys **Route:** `/dashboard/keys` Manage your operator API keys. These keys authenticate your backend when calling Valiron's trust evaluation API via the SDK. **Actions:** - **Generate new key** — Creates a new `val_op_` prefixed key. Shown once — copy it immediately. - **Revoke key** — Permanently disables a key. Revoked keys are shown separately. Each key shows its prefix, label, last used date, and creation date. --- ## Make API Agent-Ready **Route:** `/dashboard/endpoints` Create hosted Valiron wrappers for existing HTTP APIs. A wrapper provides a public agent-facing URL, handles optional x402/MPP payment challenges, optionally checks Valiron trust, applies rate limits, forwards to the upstream API, and records call logs. This product is appropriate when an API must be callable by autonomous agents without requiring immediate SDK integration in the provider backend. ### Hosted wrapper flow 1. Open **Make API Agent-Ready**. 2. Click **Make API Agent-Ready**. 3. Enter your upstream API details and payment settings. 4. Configure upstream authentication to protect your origin. 5. Save the wrapper. 6. Distribute only the generated wrapper URL to agent clients: ```text https://valiron-edge-proxy.onrender.com/wrap/{operatorId}/{path} ``` When an agent calls the wrapper: 1. Valiron matches `{operatorId}`, path, and method to your wrapper config. 2. If `pricePerCall` is greater than `0`, Valiron returns a `402 Payment Required` challenge unless valid payment is attached. 3. If trust checks are enabled, Valiron evaluates the agent identity headers. 4. Valiron appends the wrapper path to `targetUrl`, forwards the request, and adds Valiron metadata headers. 5. Valiron returns the upstream response and records analytics. > **Origin protection is required for a public upstream.** Valiron can enforce > payment, trust, rate limits, and logging only for calls made to the wrapper > URL. A call sent directly to your upstream does not pass through Valiron. Use > HMAC upstream auth and reject missing or invalid signatures at your origin; > do not rely on the presence of `x-valiron-*` metadata headers. ### Wrapper fields | Field | Required | Description | |-------|----------|-------------| | Public path | Yes | Agent-facing path (for example `/weather`). This becomes `/wrap/{operatorId}/weather`. | | Method | Yes | HTTP method: GET, POST, PUT, PATCH, DELETE | | Upstream API base URL | Yes | Existing API base URL, for example `https://api.example.com`. Must be HTTPS in production. Private/internal addresses are blocked. | | Price per call (USD) | Yes | `0` for free wrappers, or a positive USD amount for paid wrappers. | | Payment protocol | Yes | `x402` or `mpp`. `x402` is used by default and for free wrappers. | | Payment network | No | Network for paid wrappers. Common values: `eip155:8453` for Base x402 and `tempo:4217` for MPP. | | Payout wallet | No | Required for paid x402 wrappers unless a platform default receiving address is configured. | | Require Valiron trust | No | When enabled, callers must provide agent identity headers and pass the trust threshold. | | Rate limit (req/min) | No | Max requests per minute per agent (null = unlimited) | | Upstream auth | Required for a public origin | `hmac` recommended. Your origin verifies the signature and timestamp before serving the request. | | Description | No | What this endpoint does | **Removing a wrapper** performs a soft-delete. The wrapper stops matching new calls but historical logs remain available. ### Free wrapper example ```text Public path: /status Method: GET Upstream API base URL: https://api.example.com Price: 0 ``` Agents call: ```bash curl https://valiron-edge-proxy.onrender.com/wrap/{operatorId}/status ``` ### Paid x402 wrapper example ```text Public path: /weather Method: GET Upstream API base URL: https://api.example.com Price: 0.001 Payment protocol: x402 Payment network: eip155:8453 Payout wallet: 0x... ``` Agents call the wrapper once, receive a `402` with an x402 payment challenge, then retry with a valid `X-PAYMENT` header. ### Paid MPP wrapper example ```text Public path: /research Method: GET Upstream API base URL: https://api.example.com Price: 0.001 Payment protocol: mpp Payment network: tempo:4217 ``` Agents call the wrapper once, receive `WWW-Authenticate: Payment`, then retry with `Authorization: Payment ...`. For command-line testing, use `mppx`: ```bash pnpm exec mppx https://valiron-edge-proxy.onrender.com/wrap/{operatorId}/research ``` For the complete setup guide, see [AGENT-READY-APIS.md](https://www.valiron.co/docs/agents/AGENT-READY-APIS.md). --- ## API Playground **Route:** `/dashboard/playground` Test how Valiron evaluates different AI agents against your endpoints — without writing any code or sending real traffic. ### How it works 1. **Pick a chain** — All supported chains are available (Ethereum, Monad, Arbitrum, Base, Avalanche, Polygon, Optimism, Solana, testnets, and more). Chains with pre-registered sample agents show agent cards; other chains require a custom agent ID. 2. **Select an agent** — Choose from pre-registered sample agents at different trust levels, or enter a custom agent ID: - **Good agents** (score 80–95, tier A/AA) — would be routed to production - **Bad agents** (score 30–45, tier CA/CAA) — would be routed to sandbox - **Zero agents** (score 0, tier C) — no reputation, requires behavioral testing 3. **Build the request** — Pick a method and enter a path. Headers (`Content-Type`, `X-Agent-Id`, `X-Valiron-Chain`, `X-Api-Key`) are added automatically. Expand **Advanced options** to add custom headers, query params, or a request body 4. **Send** — The playground evaluates the agent's on-chain trust profile and shows the result ### Dry-run mode Toggle **Dry Run** on to see the trust evaluation without logging the call: - Resolved tier (AAA–C) - Routing decision (prod / sandbox / blocked) - Price per call (from your registered endpoint) - On-chain reputation score and feedback count ### Standard mode With dry-run off, the playground performs the full trust evaluation and logs the call to your Analytics/Logs pages. - **If your endpoint has an upstream base URL** — the playground forwards the request to your backend with Valiron headers (`X-Agent-Id`, `X-Valiron-Chain`, `X-Valiron-Tier`, `X-Valiron-Route`). You'll see the real HTTP response from your server. - **If no upstream base URL is set** — the playground returns the trust evaluation only (tier, route, cost, on-chain score). > **Tip:** Add an upstream base URL to your wrapper to enable end-to-end testing in the playground. ### Response panel Every request shows: - **Status code** — Color-coded (green 2xx, yellow 3xx/4xx, red 5xx) - **Latency** — Round-trip time in ms - **Route** — Where the agent would be routed (prod, sandbox, blocked) - **Cost** — Per-call price from your endpoint registration - **Tier** — The agent's resolved trust tier - **Body** — Trust evaluation details ### History The sidebar shows up to 20 recent requests from the current page session. Each entry shows method, path, agent, status, latency, and timestamp. Click an entry to repopulate the request form; history is not persisted across sessions. --- ## Settings **Route:** `/dashboard/settings` Manage your operator profile. - **Name** — Editable display name - **Email** — Read-only (set during registration) - **Plan** — Your current plan and fee rate - **Account info** — Operator ID and account creation date --- ## Middleware Integration Valiron's core product is SDK middleware deployed within the API backend. Use this path when trust checks, route decisions, sandbox triggers, payment gating, and usage tracking must execute before the API handler. Install the SDK and add it to your backend: ```bash npm install @valiron/sdk ``` **Express middleware:** ```typescript import { ValironOperator } from "@valiron/sdk"; const operator = new ValironOperator({ apiKey: "val_op_xxxx" }); app.use("/api/weather", operator.paywall({ pricePerCall: 0.05 })); ``` **Manual gating:** ```typescript import { ValironSDK } from "@valiron/sdk"; const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY, chain: "ethereum" }); app.use("/api/weather", async (req, res, next) => { const agentId = req.headers["x-agent-id"]; const profile = await valiron.getAgentProfile(agentId); if (profile.routing.finalRoute === "prod") return next(); if (profile.routing.finalRoute === "sandbox") return res.status(403).json({ error: "Agent under evaluation" }); return res.status(403).json({ error: "Agent not trusted" }); }); ``` ### Test with the Playground Before going live, use the Playground to verify: - That your endpoint pricing and rate limits are configured correctly - That high-reputation agents get routed to production - That low/zero-reputation agents get sandboxed or blocked - What the full request/response cycle looks like with real latency numbers ### Monitor Use the dashboard to track agent activity, review call logs, and monitor revenue. ## Separate Product: API Scaffolding API Scaffolding is a separate product that provides a hosted, agent-facing wrapper URL for an existing HTTPS API. A hosted wrapper can collect x402/MPP payment, apply optional trust checks, enforce rate limits, forward upstream, and log usage. 1. Create your account on the dashboard. 2. Copy your API key from the Keys page. 3. Create a wrapper from **Make API Agent-Ready**. 4. Test the generated `/wrap/{operatorId}/{path}` URL. 5. Monitor calls in Analytics and Logs. For hosted wrappers, also verify that a direct request to the upstream origin returns `401` or `403`, while a wrapper request is visible in call logs. See [API Scaffolding origin protection](https://www.valiron.co/docs/agents/AGENT-READY-APIS.md#origin-lockdown-checklist). For deployments requiring full backend control, protect the API directly with Valiron middleware using `createValironGate()` or `ValironOperator.paywall()`. For full hosted wrapper docs, see [AGENT-READY-APIS.md](https://www.valiron.co/docs/agents/AGENT-READY-APIS.md). --- Source: https://www.valiron.co/docs/agents/E2E-MIDDLEWARE-INTEGRATION.md # End-to-End Valiron Middleware Integration This guide helps API teams integrate Valiron middleware from the first incoming agent request through the downstream action they want to take. Start with the agent identity, choose the trust signals that match your policy, then use the gate result to protect an endpoint, vary access, attach pricing context, or record the decision. ```text Incoming request -> identify the agent -> evaluate selected trust signals -> receive an allow/deny decision, score, tier, and route -> apply your API policy -> serve, limit, sandbox, price, or deny ``` ## Before you start 1. Create an operator account in the [Dashboard](https://www.valiron.co/docs/agents/DASHBOARD.md). 2. Copy an operator API key (`val_op_...`) if you will use Pro trust signals, operator usage logging, or hosted products. 3. Install the SDK: ```bash npm install @valiron/sdk ``` 4. Choose the identity format your agent callers will send. ## 1. Identify every agent The standard gate automatically handles on-chain and key-based identities. Provider-backed identity uses the dedicated identity gate because its proof is bound to each exact request body: | Agent type | Header | Value | Setup | | --- | --- | --- | --- | | ERC-8004 EVM agent | `x-agent-id` | ERC-8004 token ID | Agent is registered on-chain | | Solana agent | `x-agent-id` | Metaplex Core asset pubkey or supported indexed ID | Use `chain: "solana"` | | Local, Web2, or non-ERC-8004 agent | `x-agent-address` | Persistent Ethereum-style address | Complete [key-based challenge-response](https://www.valiron.co/auth.md) first | | ANS or another provider-backed identity | `x-valiron-identity-*` | Canonical provider ID, signature, timestamp, and nonce | Sign with `createAgentIdentityProof()` | Do not send a local agent name to `x-agent-id`. Key-based agents must prove ownership of their persistent address before they can pass an identity-aware policy. > **Hosted wrapper note:** Valiron-hosted API Scaffolding currently requires > `x-agent-id` when its trust check is enabled. Use the SDK middleware in your > own backend for a policy that accepts either identity path. > **Provider-backed identity:** use the dedicated `createValironIdentityGate`, > `valironIdentityFastifyPlugin`, `createValironIdentityNextMiddleware`, or > `valironIdentityGateCheck` exports documented in > [PROVIDER-IDENTITY.md](https://www.valiron.co/docs/agents/PROVIDER-IDENTITY.md). Do not send an ANS name through > `x-agent-id`. Valiron hosts the ANS credentials and trusted CA bundle. ## 2. Choose trust signals Pass `trustSignals` to the middleware configuration. Start with the default baseline, then add signals only when they are meaningful for the action you are protecting. | Signal | What it contributes | Availability | | --- | --- | --- | | `8004` | Registry-backed on-chain identity and reputation | All plans | | `sandbox` | Behavioral evaluation and route readiness | All plans | | `world` | World ID proof-of-personhood linkage | Pro | | `self` | Self eligible-human verification | Pro | | `icebreaker` | Human-to-agent attestation | Pro | | `wallet` | Explainable wallet-history risk, confidence, and hard flags | Pro | For example, a high-value endpoint might require on-chain reputation, behavioral evidence, and wallet intelligence: ```typescript import { ValironSDK, createValironGate } from "@valiron/sdk"; const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY, chain: "base", }); const trustGate = createValironGate({ sdk: valiron, trustSignals: ["8004", "sandbox", "wallet"], minScore: 80, }); ``` If a wallet-history provider is unavailable or a network is unsupported, its result is neutral and excluded from the composite score rather than treated as malicious. See [Trust Model](https://www.valiron.co/docs/agents/TRUST-MODEL.md) for the complete signal model. ## 3. Choose the downstream behavior The middleware attaches a normalized result to the request after a successful check. It includes `allow`, `score`, `tier`, `riskLevel`, `route`, and the resolved `agentId`, regardless of which supported identity header the agent used. Choose the behavior that fits the endpoint: | Goal | Use the decision for | | --- | --- | | Trust gate | Allow trusted agents and return a denial before your handler runs | | Graduated access | Serve full access for `prod`, apply limits for `prod_throttled`, and use test data for sandbox routes | | Trust-aware pricing | Read the result in your handler and apply your own price or entitlement policy | | Monetized endpoint logging | Use `ValironOperator.paywall()` to gate access, attach a configured per-call price, and record usage | | Agent profile lookup | Retrieve a profile when your product needs to display or review trust evidence | | Predictive risk | Use dashboard forecasts as an additional operational signal; do not replace the runtime gate with a forecast | | Audit and operations | Capture the result in your logs or use authenticated dashboard call logs | Valiron does not itself settle a payment or choose a dynamic price table. It provides the verified trust context that your payment and application policy can use. ## 4. Put the gate in front of your handler Here is a complete Express example that supports both agent identity paths and uses the route decision for graduated access: ```typescript import express from "express"; import { ValironSDK, createValironGate } from "@valiron/sdk"; const app = express(); const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY, chain: "base", }); app.use("/api/research", createValironGate({ sdk: valiron, trustSignals: ["8004", "sandbox", "wallet"], minScore: 65, })); app.get("/api/research", (req, res) => { const trust = (req as typeof req & { valiron: { route: "prod" | "prod_throttled" | "sandbox" | "sandbox_only"; score: number; tier: string; } }).valiron; if (trust.route === "prod_throttled") { res.set("X-Rate-Limit-Policy", "reduced"); } if (trust.route === "sandbox") { return res.json({ mode: "sandbox", results: [] }); } return res.json({ mode: "production", trust: { score: trust.score, tier: trust.tier }, results: [/* your production response */], }); }); app.listen(3000); ``` The middleware checks `x-agent-id` first, then `x-agent-address`. If there is no supported identity, the agent is denied. If an agent is pending its first behavioral evaluation, it receives a retryable denial while sandbox evaluation runs. ## 5. Add a pricing or payment policy For a server-side endpoint with a fixed price and usage logging, use the operator SDK. It gates the route, makes the decision available as `req.valiron`, and records the configured price only for successful allowed calls. ```typescript import { ValironOperator } from "@valiron/sdk"; const operator = new ValironOperator({ apiKey: process.env.VALIRON_API_KEY!, chain: "base", }); app.use("/api/premium", operator.paywall({ pricePerCall: 0.05, minTrustScore: 65, trustSignals: ["8004", "sandbox", "wallet"], })); ``` If your payment provider supports multiple prices, select the price in your handler from `req.valiron.tier`, `score`, or `route`. Keep payment settlement in that provider; use Valiron first to decide whether the caller is eligible to reach it. ## 6. Test the complete request path Test each case before production: 1. A registered agent using `x-agent-id`. 2. A verified key-based agent using `x-agent-address`. 3. A request without either identity header. 4. An agent below your `minScore`. 5. A new agent pending sandbox evaluation. 6. A production-eligible agent on every protected route. 7. A paid or priced request, verifying that trust denial happens before your payment or application handler. Use the [Dashboard Playground](https://www.valiron.co/docs/agents/DASHBOARD.md#api-playground) to inspect decisions and the Dashboard's call logs to review outcome, latency, price, and trust context after launch. ## Next steps - [Quickstart](https://www.valiron.co/docs/agents/QUICKSTART.md) — protect a first endpoint quickly - [SDK Reference](https://www.valiron.co/docs/agents/SDK-REFERENCE.md#middleware) — Express, Fastify, Next.js, and generic middleware APIs - [Identity](https://www.valiron.co/docs/agents/IDENTITY.md) — registry and key-based identity details - [Trust Model](https://www.valiron.co/docs/agents/TRUST-MODEL.md) — signals, tiers, and routes - [API Scaffolding](https://www.valiron.co/docs/agents/AGENT-READY-APIS.md) — hosted x402/MPP wrappers for an existing API --- Source: https://www.valiron.co/docs/agents/ERRORS.md # Errors Common error scenarios, status codes, and guidance on how to handle them. ## Read an error before retrying Every SDK failure is a `ValironError`. Its stable `code` is for program logic; its `message` is safe to show in developer logs; and `details` provides the recovery information that was available from the API. ```typescript import { ValironError } from "@valiron/sdk"; try { await valiron.getAgentProfile("99999"); } catch (error) { if (error instanceof ValironError) { console.error({ code: error.code, status: error.statusCode, message: error.message, nextStep: error.details?.action, requestId: error.details?.requestId, docs: error.details?.docsUrl, retryAfterMs: error.details?.retryAfterMs, serverDetails: error.details?.details, }); } } ``` HTTP errors from SDK calls and trust-gate responses use these fields where applicable: | Field | Purpose | |--------|---------| | `code` | Stable, machine-readable category such as `MISSING_AGENT_IDENTITY` or `TRUST_GATE_DENIED` | | `message` | Human-readable explanation of what happened | | `action` / `details.action` | Concrete next debugging or recovery step | | `docsUrl` / `details.docsUrl` | Relevant documentation section | | `requestId` / `details.requestId` | Include with a timestamp in a support request | | `retryAfterMs` | Minimum delay before retrying, when retrying is appropriate | Treat `code` as the contract; wording may be refined over time. ## HTTP Status Codes | Status | Meaning | Action | |--------|---------|--------| | 200 | Success | Process the response | | 400 | Bad request | Check your request parameters | | 401 | Unauthorized | Verify your API key or credentials. **Do not retry.** | | 403 | Forbidden | You do not have access. **Do not retry.** | | 404 | Not found | Agent ID does not exist in the ERC-8004 registry | | 429 | Too many requests | **Stop immediately.** Honor the `Retry-After` header. | | 500 | Internal server error | Retry with exponential backoff | | 502 | Bad gateway | Retry after a short delay | | 503 | Service unavailable | Retry after `Retry-After` header duration | ## SDK Error Handling The SDK throws typed errors that you can catch: ```typescript import { ValironSDK } from "@valiron/sdk"; const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY }); try { const profile = await valiron.getAgentProfile("99999"); } catch (error) { if (error instanceof ValironError && error.statusCode === 404) { // Agent not registered — register via ERC-8004 first } else if (error instanceof ValironError && error.statusCode === 429) { // Rate limited — wait and retry await sleep(error.details?.retryAfterMs ?? 5_000); } else { // Unexpected error — log and retry with backoff console.error(error.message); } } ``` ## Retry Strategy When retrying requests, follow this pattern: ```typescript async function withRetry(fn: () => Promise, maxRetries = 3): Promise { for (let attempt = 0; attempt <= maxRetries; attempt++) { try { return await fn(); } catch (error) { // Never retry auth errors const status = error instanceof ValironError ? error.statusCode : undefined; if (status === 401 || status === 403) throw error; // Never retry client errors (except 429) if (status && status >= 400 && status < 500 && status !== 429) throw error; if (attempt === maxRetries) throw error; // Exponential backoff: 1s, 2s, 4s const delay = Math.pow(2, attempt) * 1000; await new Promise((r) => setTimeout(r, delay)); } } throw new Error("Unreachable"); } // Usage const profile = await withRetry(() => valiron.getAgentProfile("25459")); ``` ## Common Issues ### "Agent not found" (404) The agent ID is not registered in the ERC-8004 Identity Registry on the specified chain. Ensure: - The agent has been minted in the Identity Registry - You are querying the correct chain (`?chain=monad`, etc.) - The agent ID is the correct ERC-721 token ID (numeric string) ### "No behavioral data" (sandbox result is null) The agent has not been evaluated in the sandbox yet. Trigger a sandbox test: ```typescript await valiron.triggerSandboxTest("YOUR_AGENT_ID"); ``` ### Provisional scores First-time agents that haven't been sandbox-tested yet receive provisional scores. Provisional evaluations use a higher trust threshold — meaning the agent must prove itself more thoroughly on its first interaction. After the first sandbox run completes, future gate() calls use the standard threshold. ### Timeout errors The SDK uses method-aware default timeouts: 10 seconds generally, 15 seconds for `gate()`/`proxy()`, and 30 seconds for sandbox triggers. To force a single timeout for all calls, configure it explicitly: ```typescript const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY, timeout: 30000 }); // 30 seconds ``` ### Chain mismatch If the agent is registered on Monad but you query Ethereum (the default), it will return 404. Always specify the correct chain: ```typescript const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY, chain: "monad" }); ``` ### Wallet intelligence unavailable `getWalletRisk()` may return HTTP 200 with `available: false`. This is a graceful degradation response, not an SDK transport error. Inspect `error` for the exact reason: - `ALCHEMY_API_KEY is not configured` for supported EVM mainnets - `HELIUS_API_KEY is not configured` for Solana - `Wallet history is not configured for ` when the selected chain is outside the supported history subset - `Wallet history lookup timed out` or a provider HTTP/RPC error Unavailable wallet intelligence is excluded from profile and gate composite scoring. Retry provider failures according to your policy; do not reinterpret an unavailable assessment as malicious activity. ### Wallet intelligence requires Pro Direct wallet-risk requests and policies containing `trustSignals: ["wallet"]` require a valid Pro or Enterprise operator key. A Free or unauthenticated request returns: ```json { "error": "upgrade_required", "feature": "enriched_profiles", "message": "World ID, Self, Icebreaker, and wallet intelligence signals require a Pro plan. Free plans can use ERC-8004 and sandbox signals." } ``` Invalid EVM or Solana wallet formats return HTTP 400 before any provider request is made. --- ## Solana-Specific Errors ### "Agent not found" with Solana sequential ID If you pass a numeric ID (e.g. `42`) with `chain=solana` and get a 404, the sequential ID may not exist in the QuantuLabs indexer. Verify the ID exists on [8004market.io](https://8004market.io). ### Invalid Solana public key Solana agent IDs must be valid base-58 public keys (32–44 characters) or numeric sequential IDs. Invalid formats return: ```json { "error": "Invalid Solana public key" } ``` ### Liveness check failures The `GET /operator/agent/:agentId/liveness?chain=solana` endpoint probes each service URL from the agent's metadata. Common issues: - **404 on liveness endpoint**: The agent has no service endpoints registered, or the chain is not solana. - **Partial liveness** (`status: "degraded"`): Some endpoints are down. Check `results[]` for per-endpoint details. - **Full failure** (`status: "dead"`): All endpoints unreachable. The agent's infrastructure may be offline. ### Feedback write-back errors If on-chain feedback is unavailable, the evaluation result is still returned. Contact Valiron support if feedback remains unavailable. ### Solana RPC rate limits Public Solana RPC endpoints have aggressive rate limits. If you see frequent timeouts or 429s from Solana calls, configure a dedicated RPC: ```bash SOLANA_RPC_URL=https://your-private-rpc.example.com ``` --- ## Middleware Error Responses All Valiron middleware (Express, Fastify, Next.js, generic) returns consistent error responses: | Status | Code | When | What to do | |--------|------|------| | 401 | `MISSING_AGENT_IDENTITY` | No identity header | Send one supported identity header: `x-agent-id` or `x-agent-address` | | 403 | `TRUST_GATE_DENIED` | Agent did not meet the configured policy | Inspect `score`, `tier`, `route`, and `reasons`; do not blindly retry | | 403 | `AGENT_EVALUATION_PENDING` | New identity is sandbox-evaluating | Keep the same identity and retry after `retryAfterMs` | | 503 | `TRUST_GATE_UNAVAILABLE` | Trust evaluation could not complete | Fail closed; retry shortly and inspect the logged `cause` | Each response includes `message`, `action`, and `docsUrl`; denials retain the trust result fields so an application can make a deliberate fallback decision. > **Fail-closed:** When the Valiron service is unreachable, middleware returns 503 — it never fails open and never allows unverified agents through. ## Provider-Backed Identity Errors Provider identity proof failures are classifications, not transport failures: the SDK and `POST /operator/identity/verify` return HTTP 200 with `identityStatus: "claimed"` and one of these `failureReason` values. Dedicated identity middleware maps policy actions to HTTP responses: `challenge` to 401, `block` to 403, and `limit` to 429. `IDENTITY_RAW_BODY_REQUIRED` is a local HTTP 400 response when Express or Fastify parsed a body without retaining its exact bytes. `IDENTITY_GATE_UNAVAILABLE` is a fail-closed HTTP 503. | Failure reason | Meaning | Action | | --- | --- | --- | | `provider_missing` | An agent ID was supplied without a provider | Send the resolver provider name | | `resolver_unavailable` | No adapter is registered for the provider | For ANS, configure credentials and a trusted CA bundle; never treat the claim as verified | | `proof_incomplete` | Signature, timestamp, nonce, or digest is missing | Construct and sign the complete proof | | `request_digest_invalid` | Digest is not `sha256:` plus 64 hex characters | Recalculate and format the SHA-256 digest | | `nonce_invalid` | Nonce is shorter than 16 characters or contains unsupported characters | Generate a 16–256 character URL-safe nonce | | `timestamp_invalid` | Timestamp cannot be parsed | Send an ISO-8601 timestamp | | `timestamp_out_of_window` | Timestamp is outside the default five-minute window | Sign a fresh request; do not reuse the old proof | | `resolution_failed` | Provider resolution threw an error | Retry only if the provider failure is transient | | `identity_not_found` | Provider has no acceptable matching identity; ANS also uses this when strict lifecycle, certificate, or Transparency Log checks fail | Correct the ID or repair the provider registration outside Valiron | | `provider_mismatch` | Resolved record belongs to a different provider | Reject the proof and inspect resolver configuration | | `ownership_chain_unverified` | Provider authority or organization/domain binding did not validate | Do not grant verified access | | `public_key_not_found` | No verification key matched the optional key ID | Refresh provider metadata or use an active key ID | | `signature_invalid` | Signature encoding is invalid | Send base64/base64url or `0x`-hex as required by the resolver | | `signature_verification_failed` | Proof does not match a resolved key or provider verifier | Reject the proof and sign the exact canonical payload | | `replay_detected` | This identity and nonce were already accepted | Generate a fresh nonce and signature | Malformed policies return HTTP 400 with `invalid_identity_policy`. A replay store or other safe-verification failure returns HTTP 503 with `identity_verification_unavailable`; the endpoint fails closed. ## Proxy Gateway Errors | Status | When | Action | |--------|------|--------| | 400 | Missing `targetUrl` or invalid request | Check your proxy request fields | | 403 | Agent denied by trust gate | Agent does not meet the trust threshold | | 403 | SSRF blocked | The `targetUrl` resolves to a private IP, localhost, or metadata endpoint | | 503 | Origin server unreachable | Your upstream API base URL is down or timed out | ## Hosted Wrapper Errors | Status | Code | When | Action | |--------|------|------|--------| | 400 | `MISSING_AGENT_IDENTITY` | A trust-enabled hosted wrapper did not receive `x-agent-id` | Hosted wrappers currently require `x-agent-id`; use SDK middleware for key/address identity support | | 404 | `WRAPPER_NOT_FOUND` | Operator ID, path, method, or endpoint activation does not match | Verify all four values in the dashboard | | 413 | `WRAPPER_BODY_TOO_LARGE` | Body exceeds the wrapper limit | Send a smaller request or use an external input reference | | 429 | `WRAPPER_RATE_LIMITED` | Endpoint rate limit reached | Honor `retryAfter` and use exponential backoff | | 502 / 504 | `WRAPPER_UPSTREAM_REQUEST_FAILED` / `WRAPPER_UPSTREAM_TIMEOUT` | The target API failed or was too slow | Check upstream URL/auth; include `requestId` and timestamp when escalating | ## Key-Based Agent Errors | Status | When | Action | |--------|------|--------| | 400 | Invalid Ethereum address format | Verify the `x-agent-address` header is a valid `0x...` address | | 401 | Challenge expired | Request a new challenge — challenges expire after a short window | | 401 | Invalid signature | The EIP-191 signature does not match the address | ## World ID Errors | Status | When | Action | |--------|------|--------| | 400 | Invalid or malformed proof | Verify your World ID proof payload fields | | 404 | Agent has no World ID verification | The agent hasn't completed World ID verification yet | | 409 | Nullifier hash already used | This World ID proof has already been submitted | ## Self Errors | Status | When | Action | |--------|------|--------| | 400 | Raw webhook body unavailable or Self webhook signature invalid | Valiron manages the provider callback. Check session status and contact support if verification remains pending after completing the Self flow | | 400 | Self webhook cannot be mapped to a Valiron session | Create sessions through `createSelfSession()` or `POST /operator/self/session/:agentId` so `externalUuid` is stored before the webhook arrives | | 403 | Trusted Self payload ingestion is disabled | Use `createSelfSession()` and check `getSelfStatus()`; direct proof ingestion is not supported for hosted customer integrations | | 404 | Agent not found on-chain | Use an existing ERC-8004 agent ID or a supported Solana agent ID before creating a Self session | | 409 | Agent already has a verified Self link | Self links are immutable once verified | ## Monthly request allowance `429 MONTHLY_REQUEST_LIMIT_EXCEEDED` means the account has used its 100,000 Free requests for the UTC calendar month. Upgrade to Pro or wait until `resetsAt`; use `Retry-After` rather than retrying continuously. This allowance is shared across API keys and hosted endpoints. `503 MONTHLY_USAGE_UNAVAILABLE` means request usage could not be checked. Retry after the response's `Retry-After` delay. No work is admitted without a successful usage check. --- Source: https://www.valiron.co/docs/agents/IDENTITY.md # Agent Identity: On-Chain, Key-Based, and Provider-Backed Agents Valiron supports on-chain, key-based, and provider-backed middleware identity paths: | Agent type | Use this identifier | Request header | Lookup path | |------------|---------------------|----------------|-------------| | ERC-8004 / on-chain EVM agent | ERC-8004 token ID | `x-agent-id` | `/operator/agent/:agentId` | | Solana 8004 agent | Metaplex Core asset pubkey or indexed ID | `x-agent-id` | `/operator/agent/:agentId?chain=solana` | | Local, Web2, or non-ERC-8004 agent | Persistent Ethereum-style agent address | `x-agent-address` | `/operator/key/:agentAddress` | | ANS, DNS, DID, API-key, or future provider identity | Provider-canonical ID | `x-valiron-identity-*` proof headers | SDK identity gate or `/operator/identity/verify` | Use `/operator/agent/:agentId` only for registry-backed on-chain agents. Local and Web2 agents should generate or reuse a persistent keypair, prove ownership through Valiron's challenge-response flow, and then use their `x-agent-address` for trust checks. The provider-backed framework normalizes identity into `anonymous`, `claimed`, or `verified`, performs freshness and replay checks, and can return an `allow`, `limit`, `challenge`, or `block` policy action. SDK 1.3 includes signing helpers and dedicated provider identity gates; Valiron hosts the ANS credentials and trusted CA bundle. See [Provider-Backed Agent Identity](https://www.valiron.co/docs/agents/PROVIDER-IDENTITY.md) for the exact request, signature payload, SDK integration, response, and current ANS boundary. ## Wallet as a Trust Input When a Pro policy selects `trustSignals: ["wallet"]`, Valiron evaluates the wallet associated with the chosen identity path. ERC-8004 and Solana agents use the wallet resolved from their registry identity; key-based agents use their verified persistent agent address. Wallet intelligence does not establish identity by itself—it is an additional economic-history signal applied after Valiron has a wallet address. Use `getWalletProfile()` to resolve a wallet to an agent profile. Use `getWalletRisk()` when you need only the explainable wallet-history assessment. See [TRUST-MODEL.md](https://www.valiron.co/docs/agents/TRUST-MODEL.md#wallet-intelligence) for supported networks and limitations. ## ERC-8004 Identity For EVM on-chain agents, Valiron uses the ERC-8004 standard for AI agent identity. Each agent is represented by an ERC-721 token in the Identity Registry. ## How Identity Works 1. An agent owner mints an ERC-721 token in the Identity Registry 2. The token's `tokenURI` points to an Agent Registration File (ARF) 3. The ARF contains the agent's name, description, endpoints, and supported trust models 4. Valiron reads this on-chain data to identify and evaluate agents ## Agent Registration File (ARF) Format The `tokenURI` must resolve to a JSON object with this structure: ```json { "name": "Agent Name", "image": "https://example.com/agent-avatar.png", "description": "A brief description of what the agent does.", "endpoints": { "agentWallet": "eip155:1:0xAgentWalletAddress", "api": "https://agent-api.example.com" }, "supportedTrust": [ "reputation_on_chain", "behavioral_sandbox" ] } ``` ### ARF Fields | Field | Type | Required | Description | |-------|------|----------|-------------| | `name` | string | yes | Human-readable agent name | | `image` | string | no | URL to agent avatar/image | | `description` | string | no | Brief description of agent purpose | | `endpoints.agentWallet` | string | yes | CAIP-10 formatted wallet address | | `endpoints.api` | string | no | Agent's API endpoint URL | | `supportedTrust` | string[] | no | Trust models the agent supports | ### Supported Trust Models - `reputation_on_chain` — Agent participates in on-chain feedback - `behavioral_sandbox` — Agent can be evaluated via sandbox testing ### ARF Hosting The ARF can be hosted as: - **Data URI**: `data:application/json;base64,eyJuYW1lIjoi...` (inline, gas-efficient) - **IPFS**: `ipfs://bafybeig...` (permanent, decentralized) - **HTTPS URL**: `https://example.com/agent.json` (mutable, centralized) ## Contract Addresses The Identity Registry contract address is the same across all supported networks: ``` Identity Registry: 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 ``` ## Reading Identity On-Chain ### Using viem (direct contract call) ```typescript import { createPublicClient, http } from "viem"; import { mainnet } from "viem/chains"; const client = createPublicClient({ chain: mainnet, transport: http(), }); // Get token owner const owner = await client.readContract({ address: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432", abi: [{ name: "ownerOf", type: "function", inputs: [{ type: "uint256" }], outputs: [{ type: "address" }], stateMutability: "view" }], functionName: "ownerOf", args: [25459n], }); // Get agent metadata const tokenUri = await client.readContract({ address: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432", abi: [{ name: "tokenURI", type: "function", inputs: [{ type: "uint256" }], outputs: [{ type: "string" }], stateMutability: "view" }], functionName: "tokenURI", args: [25459n], }); ``` ### Using Valiron SDK ```typescript import { ValironSDK } from "@valiron/sdk"; const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY }); const profile = await valiron.getAgentProfile("25459"); console.log(profile.identity.name); console.log(profile.identity.wallet); console.log(profile.identity.endpoints); ``` ## On-Chain Reputation (Feedback) The Reputation Registry stores feedback submitted by other agents and operators. ### Contract Address ``` Reputation Registry: 0x8004BAa17C55a88189AE136b182e5fdA19dE9b63 ``` ### Submitting Feedback ```typescript giveFeedback( agentId: uint256, // Target agent's token ID value: int128, // Score (typically 0-100) valueDecimals: uint8, // Decimal places in value tag1: string, // Category tag #1 tag2: string, // Category tag #2 endpoint: string, // API endpoint tested feedbackURI: string, // IPFS CID or URL to full feedback JSON feedbackHash: bytes32 // SHA-256 hash of feedback for verification ) ``` ### Reading Feedback ```typescript // Get all feedback for an agent readAllFeedback(agentId, clientAddresses, tag1, tag2, includeRevoked) // Get specific feedback entry readFeedback(agentId, clientAddress, feedbackIndex) // Get all clients who provided feedback getClients(agentId) ``` ### Impact on Trust Score On-chain reputation contributes to an agent's overall trust evaluation. More feedback with higher scores yields a positive impact. The exact bonuses and thresholds are not disclosed. --- ## Key-Based Agents (Web2) Not every agent has an on-chain ERC-8004 identity. For local, Web2, and non-ERC-8004 agents that only have a persistent Ethereum keypair (no minted token), Valiron supports **key-based authentication** using EIP-191 challenge-response. ### How It Works 1. Agent sends a request with the `x-agent-address: 0x...` header 2. Valiron returns a challenge nonce 3. Agent signs the nonce with their private key (EIP-191 personal sign) 4. Valiron verifies the signature and creates a `KeyAgentProfile` The SDK and middleware auto-detect key-based agents from the `x-agent-address` header. The standard trust gate reads a previously verified profile; the header alone is not a fresh proof of possession. API sellers should bind it to their authenticated caller before a sensitive action. Agents can follow the hosted identity skill at [https://www.valiron.co/auth.md](https://www.valiron.co/auth.md) to generate an identifier, request a challenge, sign it, and cache the returned session token. If an API requires a human operator link, the agent should pass its exact public address to its human operator. That person creates an Icebreaker profile with verified social handles and issues a `Designated agent` credential for the address. The API seller reads the private Icebreaker view with a Pro key and enforces its policy before the protected action. The Laso-style Web2 demo returns `HUMAN_ATTESTATION_REQUIRED` until the credential exists and `HUMAN_PROFILE_INCOMPLETE` if no verified social handle is available. Key registration alone does not unlock that route. A key-only sandbox relay has no agent endpoint to observe. Its score must not be treated as demonstrated behavior for a sensitive purchase or payout. Bind the address to the API seller's authenticated caller and use a separate, action-specific policy for Icebreaker context. ### KeyAgentProfile | Field | Type | Description | |-------|------|-------------| | `agentAddress` | string | Ethereum-style address used as the key-based agent identifier | | `verified` | boolean | Whether the agent proved key ownership through challenge-response | | `score` | number \| null | Behavioral score once sandbox evaluation has run | | `tier` | string \| null | Moody's-style trust tier once scored | | `riskLevel` | string \| null | GREEN / YELLOW / RED once scored | | `route` | string \| null | Route decision once scored | | `icebreaker` | object \| null | Redacted to `null` on the authenticated summary endpoint; use `getKeyAgentIcebreaker()` with a Pro key | | `reasons` | string[] | Redacted to `[]` on the authenticated summary endpoint | | `timestamp` | string | ISO timestamp for the profile response | ### Key-Based vs On-Chain Agents | | On-Chain (ERC-8004) | Key-Based | |---|---|---| | Identity source | Minted ERC-721 token | Ethereum address + EIP-191 signature | | Starting trust | Varies (based on on-chain reputation) | Verified identity first, score/tier appear after sandbox evaluation | | Trust improvement | Sandbox testing + on-chain feedback | Key-agent sandbox evaluation + behavioral history | | World ID linkage | Supported | Not currently supported by key-agent endpoints | | Solana support | Yes (Metaplex Core) | No (EVM only) | ### API Endpoints See [API-REFERENCE.md](https://www.valiron.co/docs/agents/API-REFERENCE.md#key-based-agent-endpoints) for the full HTTP API. --- ## World ID (Proof-of-Personhood) World ID verifies that an agent is linked to a real human via Worldcoin's zero-knowledge proof system. This is one of Valiron's human identity signals and provides a strong indicator that an agent is operated by a verified person. ### How It Works 1. Agent owner completes World ID verification (orb or device level) 2. The proof is submitted to Valiron via `verifyWorldId()` or the API endpoint 3. Valiron stores the verification status and includes it in trust evaluation ### SDK Methods ```typescript // Submit a World ID proof await valiron.verifyWorldId("25459", proof); // Check verification status const status = await valiron.getWorldIdStatus("25459"); // status.worldId: { verified: true, verificationLevel: "orb" } // Get full profile const profile = await valiron.getWorldIdProfile("25459"); ``` ### API Endpoints See [API-REFERENCE.md](https://www.valiron.co/docs/agents/API-REFERENCE.md#world-id-endpoints) for the full HTTP API. --- ## 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, receives Self's signed webhook after completion, stores the verified predicates, and can include the result as the `self` trust signal during scoring. Self Agent ID can be supplied when creating a session. When present and confirmed, Valiron records it as a stronger sub-signal; it is not required for the base Self eligible-human proof. ### How It Works 1. Valiron creates a Self Enterprise session with `createSelfSession()` or `POST /operator/self/session/:agentId` 2. The user opens the returned `verificationUrl` and completes the Self flow 3. Self sends a signed `verification.completed` webhook to `/operator/self/webhook` 4. Valiron verifies the raw webhook body with Self's webhook verifier and stores the Self status ### SDK Methods ```typescript // Create a Self verification session const session = await valiron.createSelfSession("25459", { selfAgentId: "self-agent-...", }); console.log(session.self.verificationUrl); // Check verification status const status = await valiron.getSelfStatus("25459"); console.log(status.self.verified); // Get full Self profile const profile = await valiron.getSelfProfile("25459"); ``` ### API Endpoints See [API-REFERENCE.md](https://www.valiron.co/docs/agents/API-REFERENCE.md#self-endpoints) for the full HTTP API. --- ## Solana Identity (QuantuLabs 8004-solana) Solana agent identity uses a separate registry operated by [QuantuLabs](https://8004.qnt.sh/) — not the EVM ERC-8004 contracts. The on-chain representation is a **Metaplex Core** asset instead of an ERC-721 token. ### How Solana Identity Works 1. An agent owner creates a Metaplex Core asset through the QuantuLabs identity registry 2. The asset's metadata URI points to an Agent Registration File (ARF) — typically on IPFS 3. The QuantuLabs indexer assigns a sequential integer ID (1, 2, 3…) for convenience 4. Valiron reads this data via the `8004-solana` SDK's `loadAgent()` call ### Program IDs | Program | Address | |---------|---------| | Identity Registry | `8oo4dC4JvBLwy5tGgiH3WwK4B9PWxL9Z4XjA2jzkQMbQ` | | Reputation (ATOM Engine) | `AToMw53aiPQ8j7iHVb4fGt6nzUNxUhcPc3tbPBZuzVVb` | ### Solana ARF Format Solana ARFs follow a similar structure to EVM ARFs but are resolved via IPFS and the QuantuLabs API rather than on-chain `tokenURI()` calls: ```json { "name": "NoahScout_Bot.noah", "image": "https://arweave.net/abc123...", "description": "An AI agent for automated DeFi monitoring.", "endpoints": { "rest": "https://my-agent.example.com/api", "ws": "wss://my-agent.example.com/ws" } } ``` ### Agent ID Formats Solana agents have two identifiers: | Format | Example | Usage | |--------|---------|-------| | Asset pubkey | `DFkntsJ9aTCHkK88m6WZVQEvLdLNi4X1LVUgRMqetFPM` | Canonical on-chain ID (base-58) | | Sequential ID | `1226` | Convenience integer from QuantuLabs indexer | Both work interchangeably in Valiron's API: ```bash # By asset pubkey curl -H "Authorization: Bearer $VALIRON_API_KEY" "https://valiron-edge-proxy.onrender.com/operator/agent/DFknts...?chain=solana" # By sequential ID curl -H "Authorization: Bearer $VALIRON_API_KEY" "https://valiron-edge-proxy.onrender.com/operator/agent/1226?chain=solana" ``` ### Reading Solana Identity ```typescript import { ValironSDK } from "@valiron/sdk"; const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY, chain: "solana" }); const profile = await valiron.getAgentProfile("1226"); // sequential ID console.log(profile.identity.name); // "NoahScout_Bot.noah" console.log(profile.identity.wallet); // "VSAnVX4MQjEXreHc92iHxWuXPQZ1tjwiKccpFLCgLM9" ``` ### Solana On-Chain Reputation Reputation on Solana is powered by the **ATOM Engine** — a behavioral evaluation system built into the QuantuLabs registry. ATOM provides richer metrics than EVM's simple feedback count/average: | Field | Type | Description | |-------|------|-------------| | `trustTier` | string | ATOM trust classification (e.g. `"trusted"`, `"neutral"`) | | `qualityScore` | number | Overall quality metric (0–100) | | `confidence` | number | Statistical confidence in the quality score (0–1) | | `riskScore` | number | Risk assessment (0–100, lower = safer) | | `uniqueCallers` | number | Number of distinct addresses that submitted feedback | These fields appear in the `onchainReputation.solana` section of the API response. ### Solana Feedback Write-Back After sandbox or gate evaluation, Valiron may publish scores to the Solana registry. Valiron manages this process; SDK users do not configure signing credentials. --- Source: https://www.valiron.co/docs/agents/MCP.md # Valiron MCP Server Connect your MCP client to **https://www.valiron.co/mcp** with **Streamable HTTP** transport. This public server requires no API key. Use the canonical `www` URL directly to avoid redirects during POST requests. For clients that accept a remote server configuration: ```json { "mcpServers": { "valiron": { "url": "https://www.valiron.co/mcp" } } } ``` Client configuration formats vary; select Streamable HTTP when your client asks for the transport. ## Tools | Tool | Input | Result | | --- | --- | --- | | `get_api_health` | `{}` | Live Valiron API health, supported chains, and default chain | | `get_integration_docs` | `{"topic":"quickstart"}` | Valiron documentation; topics: `quickstart`, `api`, `identity`, `integration`, `errors` | The `https://www.valiron.co/api` MCP resource lists developer links. MCP provides documentation and health only. Use the SDK or REST API with your operator API key for agent profiles and trust operations. Never put operator secrets in MCP tool arguments. ## Transport The server uses stateless Streamable HTTP with JSON responses. POST MCP JSON-RPC messages with `Content-Type: application/json` and `Accept: application/json, text/event-stream`. It does not assign session IDs or offer a persistent GET event stream; GET and DELETE return 405. The SDK negotiates supported protocol versions during initialization. ```sh curl https://www.valiron.co/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":"example","version":"1.0.0"}}}' ``` Requests are limited to 16 KiB. A rate-limited request returns 429 with `Retry-After`. API failures are returned as MCP tool errors. Browser requests with an Origin header must originate from `https://www.valiron.co` or `https://valiron.co`; server-to-server clients can omit Origin. ## Other interfaces - [Valiron developer portal](https://www.valiron.co/developers) - [Valiron OpenAPI specification](https://www.valiron.co/openapi.json) - [Valiron authentication](https://www.valiron.co/auth.md) - [Valiron API discovery](https://www.valiron.co/api) - [Valiron MCP discovery metadata](https://www.valiron.co/.well-known/mcp.json) Agent profile lookup is not available through MCP. --- Source: https://www.valiron.co/docs/agents/PROVIDER-IDENTITY.md # Provider-Backed Agent Identity Valiron now has a provider-independent verification foundation for identities resolved through ANS, DNS, DIDs, API keys, and future standards. An ANS REST resolver adapter is implemented and is registered at service startup when its credentials and trusted CA bundle are configured. SDK 1.3 adds signing helpers, a typed verification method, and dedicated identity gates for Express, Fastify, Next.js, and framework-independent runtimes. Verification calls require your operator API key and count toward your account’s monthly request allowance. Free includes 100,000 metered requests per UTC calendar month; Pro has no monthly request cap. ## Responsibility boundary An identity provider establishes the agent's canonical identifier, verification key or credential, endpoints, metadata, and authoritative organization or domain binding. Valiron verifies the signed request proof, prevents replay, attaches reputation and activity to the stable provider identity, and applies the API seller's policy. Provider trust evidence is not silently converted into Valiron reputation. ANS may expose certificate integrity, lifecycle, trust-index, permission, or historical signals; Valiron keeps those external signals separate from behavior Valiron observed and from the endpoint owner's action-time policy. Valiron does not register domains or issue provider identities. ## Identity statuses | Status | Meaning | | --- | --- | | `anonymous` | No agent identity was supplied. | | `claimed` | An identity was supplied, but resolution, authority binding, freshness, signature, or replay validation failed. | | `verified` | The provider authority binding and signed request proof both passed. | `verified` is pseudonymous. It proves that the caller controls the credential bound to the agent identity; it does not identify an employee, customer, or other human. This endpoint therefore always returns `humanIdentified: false`. ## Install ```bash npm install @valiron/sdk@^1.3.0 ``` ANS credentials and CA certificates are configured by Valiron on the hosted verification service. API owners using the SDK do not need GoDaddy credentials and must not expose Valiron's provider credentials to agents or browsers. ## Agent: sign and send a request The agent signs the canonical Valiron payload using the private key bound to its provider identity. The signing callback lets the agent use its existing key manager, HSM, wallet, or provider-specific crypto library. ```typescript import { agentIdentityProofHeaders, createAgentIdentityProof, } from "@valiron/sdk"; const body = JSON.stringify({ operation: "quote", amount: 25 }); const proof = await createAgentIdentityProof({ provider: "ans", agentId: "ans://v1.0.0.sales-agent.acme.com", body, sign: (payload) => agentKey.sign(payload), }); await fetch("https://api.example.com/quote", { method: "POST", headers: { "content-type": "application/json", ...agentIdentityProofHeaders(proof), }, body, }); ``` The helper sends these proof headers: | Header | Purpose | | --- | --- | | `x-valiron-identity-provider` | Resolver name, such as `ans` | | `x-valiron-identity-agent-id` | Provider-canonical agent ID | | `x-valiron-identity-signature` | Signature over the canonical payload | | `x-valiron-identity-timestamp` | ISO 8601 signing time | | `x-valiron-identity-nonce` | Unique replay-prevention nonce | | `x-valiron-identity-key-id` | Optional provider key selector | These headers are untrusted proof inputs until a Valiron identity gate validates them. Never authorize a request merely because an `x-valiron-identity-*` header exists, and never treat output metadata such as `x-valiron-tier` or `x-valiron-route` as caller authentication. There is intentionally no request-digest header. The receiving API computes the SHA-256 digest from the exact request bytes so an agent cannot substitute a digest for different content. ## API owner: enforce an identity policy For Express, capture the raw bytes while parsing and install the provider identity gate on the protected route: ```typescript import express from "express"; import { ValironSDK, createValironIdentityGate } from "@valiron/sdk"; const app = express(); app.use(express.json({ verify(req: any, _res, bytes) { req.rawBody = Buffer.from(bytes); }, })); const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY }); app.post("/quote", createValironIdentityGate({ sdk: valiron, policy: { anonymous: "challenge", claimed: "block", verified: "allow", minReputationScore: 65, belowMinimumScore: "limit", highRisk: "block", }, }), handler); ``` Allowed requests expose the normalized result as `req.valironIdentity`. `challenge`, `block`, and `limit` decisions return HTTP 401, 403, and 429 respectively. Verification errors fail closed with HTTP 503. Body-bearing Express and Fastify requests return HTTP 400 if exact raw bytes were not captured. Next.js middleware safely hashes `request.clone()` automatically. Equivalent exports are `valironIdentityFastifyPlugin`, `createValironIdentityNextMiddleware`, and `valironIdentityGateCheck`. ## Low-level verification request `ValironSDK.verifyAgentIdentity(proof, policy)` calls `POST /operator/identity/verify`. Advanced integrations can call it directly: ```json { "provider": "ans", "agentId": "ans://v1.0.0.sales-agent.acme.com", "signature": "BASE64URL_OR_0xHEX_SIGNATURE", "timestamp": "2026-09-04T12:00:00.000Z", "nonce": "nonce-0123456789abcdef", "requestDigest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "keyId": "optional-provider-key-id", "policy": { "anonymous": "challenge", "claimed": "block", "verified": "allow", "minReputationScore": 65, "belowMinimumScore": "limit", "mediumRisk": "limit", "highRisk": "block" } } ``` The signature covers the UTF-8 bytes of this exact payload: ```text valiron-agent-request-v1 agent-id: timestamp: nonce: request-digest: ``` The request digest must use `sha256:` followed by 64 hexadecimal characters. The nonce must contain 16–256 URL-safe characters. The default timestamp window is five minutes, and nonce claims are retained for ten minutes. The caller must calculate `requestDigest` from the protected request bytes and apply the returned decision to that same request. This standalone verification endpoint cannot infer the bytes of a separate downstream request. ## Response ```json { "agentId": "ans://v1.0.0.sales-agent.acme.com", "provider": "ans", "organization": "Acme Corp", "identityStatus": "verified", "humanIdentified": false, "stableIdentityId": "identity:ans:", "credentialId": "7b93c61c-e261-488c-89a3-f948119be0a0", "credentialVersion": "1.0.0", "verifiedAt": "2026-09-04T12:00:00.000Z", "reputationScore": 82, "riskLevel": "low", "policyDecision": { "action": "allow", "reason": "identity_verified" } } ``` The action is one of `allow`, `limit`, `challenge`, or `block`. A verified identity without stored reputation returns `reputationScore: null` and `riskLevel: "unknown"`; it is not treated as having a negative score. Failed proofs return HTTP 200 with `identityStatus: "claimed"` and a machine-readable `failureReason`. See [Errors](https://www.valiron.co/docs/agents/ERRORS.md#provider-backed-identity-errors). ## Replay and storage behavior Each request nonce can be accepted only once. Verification returns HTTP 503 when the replay store is unavailable, so the flow cannot fail open. Only verified requests update the stable identity activity record. Failed claims cannot write activity or reputation against the identity they attempted to impersonate. For ANS, the stable reputation subject is the normalized `agentHost`, such as `sales-agent.acme.com`. The versioned ANS name and Registry Authority UUID are returned as credential identity fields. A new ANS version therefore gets a new credential while retaining the same Valiron reputation subject. ## ANS resolver As checked on 2026-09-10, the public ANS reference implementation uses versioned `ans://v...` names. Each version is an independent registration with its own UUID and certificates, while `agentHost` is the cross-version correlation key. For an ANS claim, the adapter: 1. resolves the exact host and version through `POST /v1/agents/resolution`; 2. follows only a same-origin Registry Authority agent-details link; 3. requires the UUID, host, ANS name, version, and `ACTIVE` lifecycle state to match; 4. loads an identity certificate and validates its time window and signature chain against the configured CA roots; 5. requires an exact URI SAN for the versioned ANS name; 6. loads the current Transparency Log record, requires `ACTIVE` or `WARNING`, and matches its identity-certificate fingerprint; and 7. extracts the certificate public key for the Valiron request proof. The timestamp, nonce, request digest, and `valiron-agent-request-v1` payload are a Valiron transport-proof envelope. They are not presented as an ANS-native HTTP signature standard. Valiron manages provider credentials and trust configuration on the hosted service. Customers supply signed proofs, not provider secrets. If the hosted resolver is unavailable, ANS claims return `claimed` with `failureReason: "resolver_unavailable"`. Malformed, inactive, revoked, mismatched, untrusted, or certificate-less ANS records cannot become `verified`. This first adapter does not independently validate live DNS/DANE state, a SCITT receipt, Merkle inclusion, checkpoint signatures, OCSP, or CRLs. Those are additional ANS integrity checks, not claims made by this endpoint. There is no domain-registration feature in Valiron. Public references: - - - - - --- Source: https://www.valiron.co/docs/agents/QUICKSTART.md # Quickstart > Estimated integration time: under 2 minutes. ## Prerequisites 1. **Create an account** with email/password, Google, or GitHub on the [Operator Dashboard](https://www.valiron.co/docs/agents/DASHBOARD.md) at [valiron.co/dashboard](https://www.valiron.co/dashboard) 2. **Verify your email for password signup**, then **complete the guided setup** — every sign-up method enters the same resumable onboarding flow 3. **Copy your API key** when it is shown; returning incomplete accounts can generate a dedicated setup key 4. Add the SDK middleware below to the backend routes agents call. Choose registered, key-based, or ANS/provider-backed identity in the wizard. > **Tip:** Before writing any code, try the [API Playground](https://www.valiron.co/docs/agents/DASHBOARD.md#api-playground) to see how Valiron evaluates agents at different trust levels against your endpoints. ## Step 1 — Install the SDK ```bash npm install @valiron/sdk ``` > **Requirements:** Node.js >= 18.0.0. Zero external dependencies. ## Step 2 — Initialize the client ```typescript import { ValironSDK } from "@valiron/sdk"; const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY, endpoint: "https://valiron-edge-proxy.onrender.com", chain: "ethereum", // or: monad, arbitrum, base, polygon, solana, etc. timeout: 5000, }); ``` Get an operator API key from https://www.valiron.co/dashboard and configure it server-side for profile reads, trust gates, and sandbox runs. Pro is required for paid signals, enriched profiles, proxy calls, and webhooks. > **Solana agents:** Use `chain: "solana"` and pass the agent's Metaplex Core asset > pubkey (base-58) as the agent ID instead of a numeric token ID. > Solana identity and reputation is provided by > [QuantuLabs 8004-solana](https://8004.qnt.sh/). ## Step 3 — Check an agent's trust level First identify which kind of agent is calling your API: | Agent type | Header | SDK/API path | |------------|--------|--------------| | ERC-8004 / Solana agent | `x-agent-id` | `getAgentProfile()` / `/operator/agent/:agentId` | | Local, Web2, or non-ERC-8004 agent | `x-agent-address` | `getKeyAgentProfile()` / `/operator/key/:agentAddress` | | Provider-backed identity (ANS and future adapters) | `x-valiron-identity-*` proof headers | `createValironIdentityGate()` / `verifyAgentIdentity()` | Do not pass a local agent name such as `my-agent` to `/operator/agent/:agentId`. That endpoint expects an on-chain ERC-8004 token ID or Solana agent identifier. Non-ERC-8004 agents should use the key-based identity flow from [auth.md](https://www.valiron.co/auth.md). For a provider-backed identity, use `createAgentIdentityProof()` in the agent runtime and `createValironIdentityGate()` in the API. The receiving gate hashes the exact request body, verifies the signature through Valiron, prevents replay, and enforces `allow`, `limit`, `challenge`, or `block`. See [Provider-Backed Agent Identity](https://www.valiron.co/docs/agents/PROVIDER-IDENTITY.md). For an on-chain agent, check their trust route: ```typescript const route = await valiron.checkAgent("INCOMING_AGENT_ID"); // Returns: "prod" | "prod_throttled" | "sandbox" | "sandbox_only" ``` For a key-based agent, look up the verified agent address: ```typescript const profile = await valiron.getKeyAgentProfile("0xAgentAddress"); console.log(profile.route); // "prod" | "prod_throttled" | "sandbox" | "sandbox_only" ``` ## Step 4 — Get the full trust profile For an on-chain agent: ```typescript const profile = await valiron.getAgentProfile("INCOMING_AGENT_ID"); console.log(profile.routing.finalRoute); // "prod" console.log(profile.routing.meetsThreshold); // true console.log(profile.onchainReputation.averageScore); // 92.5 ``` For a local, Web2, or non-ERC-8004 agent: ```typescript const profile = await valiron.getKeyAgentProfile("0xAgentAddress"); console.log(profile.verified); // true console.log(profile.score); // 82 console.log(profile.route); // "prod_throttled" ``` ## Step 5 — Gate your endpoint (recommended) The fastest way to protect your API — add Valiron as Express middleware: ```typescript import { createValironGate } from "@valiron/sdk"; app.use("/api/paid", createValironGate({ sdk: valiron })); ``` This checks `x-agent-id` first for on-chain agents, then falls back to `x-agent-address` for key-based agents. It returns 403 for untrusted agents, is safe with Express 4 (async errors are handled), and includes a 30-second client-side cache for x402 compatibility. Pro operators can include wallet history in an endpoint policy: ```typescript const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY }); app.use("/api/high-trust", createValironGate({ sdk: valiron, trustSignals: ["8004", "sandbox", "wallet"], minScore: 80, })); ``` The `wallet` signal supports Ethereum, Base, Arbitrum, Optimism, Polygon, and Solana. If wallet history is unavailable, Valiron excludes it from the composite score instead of penalizing the agent. Or use `getAgentProfile()` directly for on-chain custom logic: ```typescript const profile = await valiron.getAgentProfile("INCOMING_AGENT_ID"); const { finalRoute, decision } = profile.routing; if (finalRoute === "prod" || finalRoute === "prod_throttled") { // Serve the request — agent is trusted } else { // Block — agent is untrusted (tier: profile.localReputation?.tier) } ``` > **Note**: The `gate()` method calls a protected endpoint that requires agent challenge-response auth. Use the middleware (`createValironGate`) or `getAgentProfile()` for server-side trust checks. For key-based agents, use `getKeyAgentProfile()` directly: ```typescript const profile = await valiron.getKeyAgentProfile("0xAgentAddress"); if (profile.verified && (profile.score ?? 0) >= 65) { // Serve the request } else { // Block or ask the agent to complete https://www.valiron.co/auth.md } ``` ## What happens next? Based on the route decision, your API should: - `prod` — Allow full access. The agent is trusted. - `prod_throttled` — Allow with rate limiting. The agent shows moderate trust. - `sandbox` — Serve limited/test data. The agent is still being evaluated. - `sandbox_only` — Block or serve only sandbox responses. The agent has failed behavioral evaluation. ## Step 6 — Trigger a sandbox evaluation (optional) Proactively evaluate an agent before they hit your endpoints: ```typescript // On-chain agents const result = await valiron.triggerSandboxTest("AGENT_ID"); console.log(result.tier); // "AAA" console.log(result.riskLevel); // "GREEN" console.log(result.meetsThreshold); // true // Key-based (Web2) agents const keyResult = await valiron.triggerKeyAgentSandbox("0x1234...abcd"); console.log(keyResult.tier); // "A" ``` > **Auto-sandbox:** You usually don't need to call these manually. When a new agent (on-chain with `totalFeedback === 0`, or key-based with no score yet) hits a gated endpoint, the middleware automatically triggers sandbox evaluation in the background. The agent receives a `403` with `{ error: "Agent pending evaluation", retryAfterMs: 30000 }` — they should retry after 30 seconds. ## Step 7 — Register a webhook (optional) Get notified whenever Valiron evaluates an agent calling your API: ```bash curl -X POST https://valiron-edge-proxy.onrender.com/operator/webhooks/register \ -H "Authorization: Bearer $VALIRON_API_KEY" \ -H "Content-Type: application/json" \ -d '{"event": "evaluation_complete", "url": "https://your-endpoint.com/hooks/valiron"}' ``` ## Step 8 — Monitor in the Dashboard Once your integration is live, use the [Operator Dashboard](https://www.valiron.co/docs/agents/DASHBOARD.md) to: - **Agents** — See every agent that has called your API, sorted by activity, spend, or errors - **Analytics** — Track revenue, call volume, and top endpoints over time - **Call Logs** — Paginated log of every request with status codes, latency, and cost - **Playground** — Test how agents at different trust levels are evaluated against your endpoints ## Using the HTTP API directly (no SDK) ```bash # Check an agent's trust profile curl -H "Authorization: Bearer $VALIRON_API_KEY" https://valiron-edge-proxy.onrender.com/operator/agent/AGENT_ID # Check a key-based agent profile curl -H "Authorization: Bearer $VALIRON_API_KEY" https://valiron-edge-proxy.onrender.com/operator/key/0x1234...abcd # Get a key-based identity challenge curl -X POST https://valiron-edge-proxy.onrender.com/operator/key/0x1234...abcd/challenge # Trigger sandbox evaluation curl -X POST https://valiron-edge-proxy.onrender.com/operator/trigger-sandbox/AGENT_ID -H "Authorization: Bearer $VALIRON_API_KEY" # Trigger sandbox for key-based agent curl -X POST https://valiron-edge-proxy.onrender.com/operator/trigger-sandbox-key/0x1234...abcd -H "Authorization: Bearer $VALIRON_API_KEY" # Gate decision (allow/deny) curl -H "Authorization: Bearer $VALIRON_API_KEY" -X POST https://valiron-edge-proxy.onrender.com/operator/gate/AGENT_ID # Behavioral snapshot hash curl -H "Authorization: Bearer $VALIRON_API_KEY" https://valiron-edge-proxy.onrender.com/operator/agent/AGENT_ID/snapshot # Register webhook curl -X POST https://valiron-edge-proxy.onrender.com/operator/webhooks/register \ -H "Authorization: Bearer $VALIRON_API_KEY" \ -H "Content-Type: application/json" \ -d '{"event": "evaluation_complete", "url": "https://your-endpoint.com/hooks"}' ``` ## Separate product — API Scaffolding Valiron middleware is the primary backend integration. API Scaffolding is a separate product for exposing an existing HTTPS API through a Valiron-hosted, agent-facing URL. 1. Open [valiron.co/dashboard](https://www.valiron.co/dashboard). 2. Go to **Make API Agent-Ready**. 3. Enter your public path, upstream API base URL, price, payment protocol, and optional trust settings. 4. Distribute the generated wrapper URL to agent clients: ```text https://valiron-edge-proxy.onrender.com/wrap/{operatorId}/{path} ``` API Scaffolding can collect payment, apply optional trust checks, enforce rate limits, forward upstream, and log usage. For deployments requiring full backend control, protect the API directly with Valiron middleware using `createValironGate()` or `ValironOperator.paywall()`. --- ## Cleanup (long-running servers) Call `dispose()` when shutting down to flush pending telemetry: ```typescript process.on("SIGTERM", async () => { await valiron.dispose(); process.exit(0); }); ``` --- ## What's next? - **[End-to-End Middleware Integration](https://www.valiron.co/docs/agents/E2E-MIDDLEWARE-INTEGRATION.md)** — Choose identity, trust signals, and a downstream policy for a production integration - **[Proxy Gateway](https://www.valiron.co/docs/agents/SDK-REFERENCE.md#proxy-gateway-pro)** — Forward requests through Valiron's edge proxy (Pro) - **[API Scaffolding](https://www.valiron.co/docs/agents/AGENT-READY-APIS.md)** — Create hosted x402/MPP wrappers for existing APIs - **[Key-Based Agents](https://www.valiron.co/docs/agents/SDK-REFERENCE.md#key-based-agents)** — Support Web2 agents without on-chain identity - **[World ID](https://www.valiron.co/docs/agents/SDK-REFERENCE.md#world-id-methods)** — Verify agent-human linkage - **[Self](https://www.valiron.co/docs/agents/SDK-REFERENCE.md#self-methods)** — Create Self Enterprise sessions and verify eligible-human linkage - **[Wallet Intelligence](https://www.valiron.co/docs/agents/TRUST-MODEL.md#wallet-intelligence)** — Add explainable wallet-history risk to Pro endpoint policies - **[Fastify / Next.js / Hono middleware](https://www.valiron.co/docs/agents/SDK-REFERENCE.md#middleware)** — Framework-specific middleware - **[Plans & Limits](https://www.valiron.co/docs/agents/SDK-REFERENCE.md#plans--limits)** — Free vs Pro feature comparison --- ## Quickstart: Solana Agents Solana agents use a different registry ([QuantuLabs 8004-solana](https://8004.qnt.sh/)) but the same Valiron API. Here's how to evaluate Solana-based agents calling your API. ### Step 1 — Initialize with Solana chain ```typescript import { ValironSDK } from "@valiron/sdk"; const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY, endpoint: "https://valiron-edge-proxy.onrender.com", chain: "solana", }); ``` ### Step 2 — Query an agent by asset pubkey or sequential ID Solana agents have two ID formats — use whichever the agent provides: ```typescript // By Metaplex Core asset pubkey (base-58) const profile = await valiron.getAgentProfile("DFkntsJ9aTCHkK88m6WZVQEvLdLNi4X1LVUgRMqetFPM"); // By sequential ID (integer assigned by QuantuLabs indexer) const profile = await valiron.getAgentProfile("1226"); console.log(profile.identity.name); // "NoahScout_Bot.noah" console.log(profile.onchainReputation.solana?.trustTier); // "trusted" ``` ### Step 3 — Check liveness (Solana only) Solana agents support a liveness probe that pings their declared service endpoints: ```bash curl -H "Authorization: Bearer $VALIRON_API_KEY" "https://valiron-edge-proxy.onrender.com/operator/agent/1226/liveness?chain=solana" ``` ### Step 4 — Gate decision (same as EVM) ```typescript const gate = await valiron.gate("1226"); if (gate.allow) { // Serve the request — agent is trusted } ``` ### Solana HTTP API examples ```bash # Get agent profile (sequential ID) curl -H "Authorization: Bearer $VALIRON_API_KEY" "https://valiron-edge-proxy.onrender.com/operator/agent/1226?chain=solana" # Get agent profile (asset pubkey) curl -H "Authorization: Bearer $VALIRON_API_KEY" "https://valiron-edge-proxy.onrender.com/operator/agent/DFkntsJ9aTCHkK88m6...?chain=solana" # Resolve wallet to agent curl -H "Authorization: Bearer $VALIRON_API_KEY" "https://valiron-edge-proxy.onrender.com/operator/resolve-wallet/VSAnVX4MQjEXreHc92iHxWuXPQZ1tjwiKccpFLCgLM9?chain=solana" # Trigger sandbox curl -H "Authorization: Bearer $VALIRON_API_KEY" -X POST "https://valiron-edge-proxy.onrender.com/operator/trigger-sandbox/1226?chain=solana" # Trust gate curl -H "Authorization: Bearer $VALIRON_API_KEY" -X POST "https://valiron-edge-proxy.onrender.com/operator/gate/1226?chain=solana" # Liveness check curl -H "Authorization: Bearer $VALIRON_API_KEY" "https://valiron-edge-proxy.onrender.com/operator/agent/1226/liveness?chain=solana" ``` --- Source: https://www.valiron.co/docs/agents/README.md # Valiron — Documentation > **Protect your API endpoints from bad or malicious AI agents.** This documentation covers how to integrate Valiron into your API to gate, score, and sandbox agents before they reach your infrastructure. ## What is Valiron? Valiron is trust infrastructure for API sellers. It evaluates AI agents using on-chain identity (ERC-8004 or Solana), key-based identity for non-ERC-8004 agents, behavioral sandbox testing, optional wallet-history intelligence, and a Moody's-style credit rating system — so you can allow trusted agents and block risky ones automatically. **If you sell APIs**, Valiron's core product is middleware deployed within the API backend through the SDK. It provides direct control over trust checks, routing, sandboxing, payment gating, and analytics before requests reach application handlers. Valiron also provides **API Scaffolding** as a separate product for organizations that require a hosted, agent-facing wrapper URL for an existing HTTPS API. It can add x402/MPP payment challenges, optional trust checks, rate limits, upstream forwarding, and logging without requiring backend code changes. Scaffolding can serve as an evaluation path before adopting a first-party backend integration protected by Valiron middleware. ## Documentation Index | File | Purpose | |------|---------| | [QUICKSTART.md](https://www.valiron.co/docs/agents/QUICKSTART.md) | Get started in under 2 minutes — install the SDK, gate your first endpoint | | [E2E-MIDDLEWARE-INTEGRATION.md](https://www.valiron.co/docs/agents/E2E-MIDDLEWARE-INTEGRATION.md) | End-to-end middleware integration — identity, trust signals, downstream policy, and testing | | [AGENT-READY-APIS.md](https://www.valiron.co/docs/agents/AGENT-READY-APIS.md) | API Scaffolding — hosted x402/MPP wrappers for existing APIs | | [DASHBOARD.md](https://www.valiron.co/docs/agents/DASHBOARD.md) | Operator Dashboard — manage endpoints, keys, analytics, and playground | | [API-REFERENCE.md](https://www.valiron.co/docs/agents/API-REFERENCE.md) | Complete HTTP API reference with request/response schemas | | [SDK-REFERENCE.md](https://www.valiron.co/docs/agents/SDK-REFERENCE.md) | TypeScript SDK methods, signatures, and usage examples | | [TRUST-MODEL.md](https://www.valiron.co/docs/agents/TRUST-MODEL.md) | How agents are scored, what behaviors are penalized, tier assignments | | [IDENTITY.md](https://www.valiron.co/docs/agents/IDENTITY.md) | Agent identity — ERC-8004/Solana agents and key-based Web2 agents | | [PROVIDER-IDENTITY.md](https://www.valiron.co/docs/agents/PROVIDER-IDENTITY.md) | Provider-backed identity — SDK signing helpers and gates, normalized proofs, replay protection, policies, and ANS | | [SANDBOX.md](https://www.valiron.co/docs/agents/SANDBOX.md) | How the sandbox evaluates agents and determines production readiness | | [CHAINS.md](https://www.valiron.co/docs/agents/CHAINS.md) | Supported blockchain networks and contract addresses | | [ERRORS.md](https://www.valiron.co/docs/agents/ERRORS.md) | Error codes, troubleshooting, and retry guidance | ## Key Concepts (Summary) - **Agent ID**: An agent's ERC-8004 token ID (EVM) or Metaplex Core asset pubkey (Solana) — their on-chain identity. Use this with `x-agent-id` and `/operator/agent/:agentId`. - **Key-Based Agent Address**: A persistent Ethereum-style address for a local, Web2, or non-ERC-8004 agent. Use this with `x-agent-address` and `/operator/key/:agentAddress`. - **Provider-Backed Identity**: An ANS or future provider identity verified through `ValironSDK.verifyAgentIdentity()`. SDK 1.3 includes signing helpers and dedicated Express, Fastify, Next.js, and generic identity gates. Valiron hosts the ANS credentials and CA configuration. - **Sequential ID** (Solana only): A convenience integer (1, 2, 42…) assigned by the QuantuLabs indexer. Maps to an asset pubkey. - **Trust Tier**: AAA (highest trust) → C (lowest trust). Assigned based on behavioral evaluation. - **Risk Level**: GREEN, YELLOW, or RED. - **Route Decision**: `prod`, `prod_throttled`, `sandbox`, or `sandbox_only` — determines what access level your API should give. - **API Scaffolding**: A separate hosted Valiron wrapper product at `/wrap/{operatorId}/{path}` that can collect x402/MPP payments, optionally gate by trust, and forward to an upstream API. - **Payment Protocol**: `x402` for Base/USDC HTTP payments or `mpp` for Machine Payment Protocol payments through Tempo. - **Sandbox**: An isolated test environment where Valiron evaluates agent behavior before granting production access. - **Wallet Intelligence**: A Pro trust signal that converts bounded Alchemy or Helius wallet history into an explainable score, risk level, confidence, and reasons. - **Liveness** (Solana only): Endpoint health probe via `isItAlive()`. See [API-REFERENCE.md](https://www.valiron.co/docs/agents/API-REFERENCE.md#solana-support). ## Which Identity Path Should I Use? | Agent type | Use this identifier | Request header | Lookup path | |------------|---------------------|----------------|-------------| | ERC-8004 / on-chain EVM agent | ERC-8004 token ID | `x-agent-id` | `/operator/agent/:agentId` | | Solana 8004 agent | Metaplex Core asset pubkey or indexed ID | `x-agent-id` | `/operator/agent/:agentId?chain=solana` | | Local, Web2, or non-ERC-8004 agent | Persistent Ethereum-style agent address | `x-agent-address` | `/operator/key/:agentAddress` | | ANS, DNS, DID, API-key, or future provider identity | Provider-canonical agent ID | `x-valiron-identity-*` proof headers | SDK identity gate or `/operator/identity/verify` | Do not send a local agent name such as `my-agent` to `/operator/agent/:agentId`. That endpoint is for registry-backed on-chain agents. Local and Web2 agents should generate or reuse a persistent keypair, prove ownership through Valiron's challenge-response flow, and then use their `x-agent-address` for trust checks. Provider identity gates calculate the digest from the API's exact raw request bytes and never trust a caller-supplied digest header. ANS credentials and the trusted CA bundle live in Valiron's hosted service, not customer applications. See [Provider-Backed Agent Identity](https://www.valiron.co/docs/agents/PROVIDER-IDENTITY.md). ## Supported Registries | Network | Provider | Identity | Reputation | |---------|----------|----------|------------| | EVM (41 chains) | [8004 team](https://erc8004.org) | `0x8004A169...` | `0x8004BAa1...` | | Solana | [QuantuLabs](https://8004.qnt.sh/) | `8oo4dC4J...` | `AToMw53a...` (ATOM) | ## Base URL ``` https://valiron-edge-proxy.onrender.com ``` ## Developer interfaces - [Valiron OpenAPI](https://www.valiron.co/openapi.json) - [Valiron MCP server setup](https://www.valiron.co/docs/agents/MCP.md) - [Valiron developer portal](https://www.valiron.co/developers) --- Source: https://www.valiron.co/docs/agents/SANDBOX.md # 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. ## How It Works 1. A sandbox test is triggered (via your API call 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 tier is assigned 5. Based on the tier, a route decision determines what access level the agent should receive ## What Gets Tested The sandbox evaluates agents through a series of simulated API interactions that test how the agent handles various scenarios. The specific test types, distribution, and patterns are proprietary and not disclosed. ## Graduation Agents graduate from sandbox to production based on their behavior: 1. **High confidence** — strong behavioral compliance → `prod` (allow full access) 2. **Moderate confidence** — passes with some concerns → `prod_throttled` (allow with rate limiting) 3. **Low confidence** — risky behavior → remains `sandbox_only` (block or serve test data only) Once graduated, the trust evaluation is cached. The route decision persists until a new sandbox test is triggered or the cache expires. ## Triggering a Sandbox Test You can proactively evaluate agents before they hit your production endpoints, or let the middleware handle it automatically (see Auto-Sandbox below). ### Via SDK ```typescript import { ValironSDK } from "@valiron/sdk"; const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY }); // On-chain agent const result = await valiron.triggerSandboxTest("YOUR_AGENT_ID"); console.log(result.tier); // "AAA" console.log(result.riskLevel); // "GREEN" console.log(result.meetsThreshold); // true // Key-based agent const keyResult = await valiron.triggerKeyAgentSandbox("0x1234...abcd"); console.log(keyResult.tier); // "A" ``` ### Via HTTP ```bash # On-chain agent curl -X POST https://valiron-edge-proxy.onrender.com/operator/trigger-sandbox/YOUR_AGENT_ID -H "Authorization: Bearer $VALIRON_API_KEY" # Key-based agent curl -X POST https://valiron-edge-proxy.onrender.com/operator/trigger-sandbox-key/0x1234...abcd -H "Authorization: Bearer $VALIRON_API_KEY" ``` ## Auto-Sandbox When a new agent hits a gated endpoint for the first time, the middleware automatically triggers sandbox evaluation in the background. No manual trigger is needed. ### On-Chain Agents (ERC-8004) New on-chain agents are detected by `totalFeedback === 0` in their reputation profile. The middleware calls `triggerSandboxTest()` as a fire-and-forget background task and returns: ```json { "error": "Agent pending evaluation", "retryAfterMs": 30000 } ``` The agent should retry after 30 seconds. Once evaluation completes, subsequent requests are gated normally. ### Key-Based Agents (Web2) New key agents are detected by `verified === true` but `score === null`. The middleware calls `triggerKeyAgentSandbox()` in the background and returns the same 403 pending response. Key agents don't have on-chain endpoints, so sandbox evaluation uses `sandbox_relay` mode — a conservative set of behavioral metrics are computed without probing endpoints. #### Via SDK ```typescript // On-chain agent const result = await valiron.triggerSandboxTest("YOUR_AGENT_ID"); // Key-based agent const result = await valiron.triggerKeyAgentSandbox("0x1234...abcd"); ``` #### Via HTTP ```bash # On-chain agent curl -X POST https://valiron-edge-proxy.onrender.com/operator/trigger-sandbox/YOUR_AGENT_ID -H "Authorization: Bearer $VALIRON_API_KEY" # Key-based agent curl -X POST https://valiron-edge-proxy.onrender.com/operator/trigger-sandbox-key/0x1234...abcd -H "Authorization: Bearer $VALIRON_API_KEY" ``` ## Tips for Passing Sandbox Tests 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. --- ## Solana Sandbox Differences For Solana agents (`chain=solana`), the sandbox flow has additional steps powered by the QuantuLabs 8004-solana SDK. ### Liveness Probe Before running behavioral tests, the sandbox triggers a **liveness check** via `isItAlive()`. This pings every service endpoint declared in the agent's on-chain metadata (REST, WebSocket, GraphQL, etc.) and returns a health report. ```bash GET /operator/agent/{agentId}/liveness?chain=solana ``` If all endpoints are unreachable (`status: "dead"`), the sandbox may still proceed — liveness is informational and does not gate the evaluation. ### Feedback Write-back After a sandbox evaluation completes, Valiron writes the computed trust score back to the Solana reputation registry via the ATOM engine's `giveFeedback()`. This closes the loop — sandbox results become on-chain reputation. Feedback write-back is managed by Valiron; SDK users do not configure signing credentials. Feedback write-back is **fire-and-forget** — if it fails, the sandbox result is still returned to the caller. ### ATOM Engine Metrics Solana reputation includes ATOM engine metrics that EVM agents don't have: | Metric | Description | |--------|-------------| | `trustTier` | ATOM classification: `"trusted"`, `"neutral"`, etc. | | `qualityScore` | Overall behavioral quality (0–100) | | `confidence` | Statistical confidence in quality score (0–1) | | `riskScore` | ATOM risk assessment (0–100, lower = safer) | | `uniqueCallers` | Number of distinct feedback submitters | These appear in the sandbox/gate response under `onchainReputation.solana` and are factored into the final Valiron risk score alongside the standard behavioral penalties. --- Source: https://www.valiron.co/docs/agents/SDK-REFERENCE.md # SDK Reference Package: `@valiron/sdk` ## Installation ```bash npm install @valiron/sdk # or pnpm add @valiron/sdk ``` ## Constructor ```typescript import { ValironSDK } from "@valiron/sdk"; const valiron = new ValironSDK(config?: ValironConfig); ``` ### ValironConfig | Field | Type | Default | Description | |-------|------|---------|-------------| | `apiKey` | string | — | Operator API key. Required for profile/status reads, trust gates, and sandbox runs; Pro is required for paid signals, enriched profiles, proxy calls, and webhooks | | `endpoint` | string | `https://valiron-edge-proxy.onrender.com` | API base URL | | `chain` | SupportedChain | `"ethereum"` | Default blockchain network | | `timeout` | number | method-aware | Request timeout in milliseconds. Defaults are 10s generally, 15s for `gate()`/`proxy()`, and 30s for sandbox triggers. If set, this value overrides all method-aware defaults. | | `debug` | boolean | `false` | Enable debug logging | | `telemetry` | TelemetryConfig | — | Optional telemetry configuration | ### SupportedChain ```typescript type SupportedChain = | "ethereum" | "monad" | "arbitrum" | "base" | "avalanche" | "celo" | "polygon" | "linea" | "abstract" | "bsc" | "gnosis" | "goat" | "mantle" | "megaeth" | "metis" | "optimism" | "scroll" | "skale_base" | "soneium" | "taiko" | "xlayer" | "base_sepolia" | "ethereum_sepolia" | "abstract_testnet" | "arbitrum_sepolia" | "avalanche_testnet" | "bsc_testnet" | "celo_testnet" | "linea_sepolia" | "mantle_testnet" | "megaeth_testnet" | "metis_sepolia" | "optimism_sepolia" | "polygon_amoy" | "scroll_sepolia" | "skale_base_sepolia" | "soneium_minato" | "taiko_hoodi" | "xlayer_testnet" | "hedera_testnet" | "arc_testnet" | "solana"; ``` > **Solana:** When using `chain: "solana"`, agent IDs are base-58 Metaplex Core > asset pubkeys (not numeric). Wallet addresses are also base-58. > See [CHAINS.md](https://www.valiron.co/docs/agents/CHAINS.md#solana) for details. --- ## Methods ### checkAgent(agentId, options?) Quick routing check. Returns only the route decision string. ```typescript const route = await valiron.checkAgent(agentId: string, options?: { chain?: SupportedChain; }): Promise; ``` **Returns**: `"prod"` | `"prod_throttled"` | `"sandbox"` | `"sandbox_only"` **Example**: ```typescript const route = await valiron.checkAgent("25459"); if (route === "prod") { // Agent is trusted — proceed with full access } ``` **Solana example**: ```typescript const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY, chain: "solana" }); // By asset pubkey const route = await valiron.checkAgent("DFkntsJ9aTCHkK88m6WZVQEvLdLNi4X1LVUgRMqetFPM"); // By sequential ID const route = await valiron.checkAgent("1226"); ``` --- ### getAgentProfile(agentId, options?) Full trust profile combining on-chain identity, reputation, and routing. ```typescript const profile = await valiron.getAgentProfile(agentId: string, options?: { chain?: SupportedChain; }): Promise; ``` **Returns**: `AgentProfile` ```typescript interface AgentProfile { agentId: string; identity: AgentIdentity; onchainReputation: OnchainReputation; routing: { finalRoute: RouteDecision; meetsThreshold: boolean; }; chain: ChainContext; timestamp: string; } ``` **Example**: ```typescript const profile = await valiron.getAgentProfile("25459"); console.log(profile.routing.finalRoute); // "prod" console.log(profile.routing.meetsThreshold); // true console.log(profile.onchainReputation.averageScore); // 92.5 ``` **Solana example**: ```typescript const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY, chain: "solana" }); const profile = await valiron.getAgentProfile("1226"); // sequential ID works console.log(profile.identity.name); // "NoahScout_Bot.noah" console.log(profile.onchainReputation.solana?.trustTier); // "trusted" console.log(profile.onchainReputation.solana?.qualityScore); // 85 ``` --- ### getWalletProfile(wallet, options?) Reverse-lookup a wallet address to get its trust profile. ```typescript const profile = await valiron.getWalletProfile(wallet: string, options?: { chain?: SupportedChain; }): Promise; ``` **Example**: ```typescript const profile = await valiron.getWalletProfile("0x52ce..."); console.log(profile.routing.finalRoute); ``` **Solana example**: ```typescript const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY, chain: "solana" }); const profile = await valiron.getWalletProfile("VSAnVX4MQjEXreHc92iHxWuXPQZ1tjwiKccpFLCgLM9"); ``` --- ### getWalletRisk(wallet, options?) Return an explainable wallet-history assessment. This is a Pro feature and requires an operator API key. ```typescript const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY }); const assessment = await valiron.getWalletRisk("0x52ce...", { chain: "base" }); if (assessment.available) { console.log(assessment.score); // 0-100 trust score; higher is better console.log(assessment.risk); // 100 - score console.log(assessment.riskLevel); // "LOW" | "MEDIUM" | "HIGH" | "CRITICAL" console.log(assessment.confidence); // 0-1 history coverage confidence console.log(assessment.reasons); } else { console.log(assessment.error); // missing key, unsupported network, timeout, etc. } ``` Supported history networks are Ethereum, Base, Arbitrum, Optimism, Polygon, and Solana. EVM uses Alchemy; Solana uses Helius. The assessment uses bounded samples rather than complete transaction history. It does not provide sanctions, mixer, scam, or criminal attribution without an additional intelligence provider. --- ### resolveWallet(wallet, options?) Lightweight wallet → agentId resolution without 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). Wallet resolution returns the associated agent ID when available. Signature: `resolveWallet(wallet: string, options?: { chain?: SupportedChain }): Promise` **Returns**: `WalletResolution` ```typescript interface WalletResolution { wallet: string; agentId: string | null; source: "redis" | "subgraph" | "cache" | "none"; chainId?: number | null; agentName?: string | null; timestamp: string; } ``` **Example**: ```typescript const resolution = await valiron.resolveWallet("0x52ce..."); if (resolution.agentId) { const profile = await valiron.getAgentProfile(resolution.agentId); } ``` **Solana example**: ```typescript const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY, chain: "solana" }); const resolution = await valiron.resolveWallet("VSAnVX4MQjEXreHc92iHxWuXPQZ1tjwiKccpFLCgLM9"); // Solana matches return source "solana_registry"; no match returns "none". // The SDK 1.4 ResolutionSource type does not yet include "solana_registry". ``` --- ### triggerSandboxTest(agentId, options?) Run sandbox tests against an agent and compute a trust evaluation. ```typescript const result = await valiron.triggerSandboxTest(agentId: string, options?: { chain?: SupportedChain; }): Promise; ``` **Returns**: `SandboxResult` ```typescript interface SandboxResult { ok: boolean; agentId: string; wallet: string; tier: MoodysRating; // "AAA" | "AA" | "A" | "BAA" | "BA" | "B" | "CAA" | "CA" | "C" riskLevel: "GREEN" | "YELLOW" | "RED"; meetsThreshold: boolean; testSummary: object; // Opaque test metrics (structure is proprietary) chain: ChainContext; message: string; } ``` **Example**: ```typescript const result = await valiron.triggerSandboxTest("25459"); console.log(result.tier); // "AAA" console.log(result.riskLevel); // "GREEN" console.log(result.meetsThreshold); // true ``` > **Auto-sandbox:** The middleware (`createValironGate`, `valironFastifyPlugin`, `createValironNextMiddleware`, `valironGateCheck`) automatically triggers `triggerSandboxTest()` in the background for new on-chain agents (those with `totalFeedback === 0`). The agent receives a 403 with `{ error: "Agent pending evaluation", retryAfterMs: 30000 }` while evaluation runs. No manual trigger is needed. --- ### triggerKeyAgentSandbox(agentAddress) Run sandbox tests against a key-based (Web2) agent and compute a trust evaluation. Key agents don't have on-chain endpoints, so this uses the `sandbox_relay` mode internally. ```typescript const result = await valiron.triggerKeyAgentSandbox(agentAddress: string): Promise; ``` **Returns**: `KeyAgentSandboxResult` ```typescript interface KeyAgentSandboxResult { ok: boolean; agentAddress: string; valironScore: number; tier: MoodysRating; riskLevel: "GREEN" | "YELLOW" | "RED"; message: string; } ``` **Example**: ```typescript const result = await valiron.triggerKeyAgentSandbox("0x1234...abcd"); console.log(result.tier); // "A" console.log(result.riskLevel); // "GREEN" console.log(result.valironScore); // 85 ``` > **Auto-sandbox:** The middleware automatically triggers `triggerKeyAgentSandbox()` in the background for new key agents (those with `verified === true` but `score === null`). The agent receives a 403 with `{ error: "Agent pending evaluation", retryAfterMs: 30000 }` while evaluation runs. --- ### gate(agentId, options?) Low-level hosted gate combining on-chain reputation and sandbox tests. The HTTP endpoint requires both an operator API key and agent challenge-response headers. SDK 1.4 `gate()` does not forward agent-session headers, so an API key alone is insufficient. For server integrations, use `createValironGate()` or `valironGateCheck()`; for direct HTTP calls, follow the [authentication flow](https://www.valiron.co/auth.md). ```typescript const result = await valiron.gate(agentId: string, options?: { minScore?: number; // default: 65 ttlMs?: number; // default: 86400000 (24h) trustSignals?: Array<"8004" | "sandbox" | "world" | "self" | "icebreaker" | "wallet">; chain?: SupportedChain; }): Promise; ``` **Returns**: `GateResult` ```typescript interface GateResult { allow: boolean; tier: MoodysRating; riskLevel: "GREEN" | "YELLOW" | "RED"; meetsThreshold: boolean; route: RouteDecision; agentId: string; wallet: string; chain: ChainContext; sandboxRan: boolean; cached: boolean; walletRisk?: WalletRiskSnapshot; } ``` **Example**: ```typescript const result = await valiron.gate("25459"); if (result.allow) { // proceed with payment } else { console.log(`Agent denied — tier: ${result.tier}, risk: ${result.riskLevel}`); } ``` --- ### 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. ```typescript const snapshot = await valiron.getAgentSnapshot(agentId: string, options?: { chain?: SupportedChain; }): Promise; ``` **Returns**: `AgentSnapshotSummary` ```typescript interface AgentSnapshotSummary { agentId: string; snapshotHash: string; // deterministic SHA-256 hash of behavioral evaluation (opaque) previousHash: string; // hash from prior evaluation, or "0x0" for first encryptedDataUri: string | null; // IPFS CID of encrypted snapshot data, if available timestamp: string | null; // ISO 8601 timestamp of evaluation interactionCount: number; // total interactions in the evaluation window } ``` **Example**: ```typescript const snapshot = await valiron.getAgentSnapshot("25459"); console.log(snapshot.snapshotHash); // "0x3a7f..." console.log(snapshot.previousHash); // "0x0" (genesis) or "0x8b2c..." console.log(snapshot.interactionCount); // 15 ``` **Notes**: - 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"`. - Trigger a sandbox evaluation first if no snapshot exists (returns 404 otherwise). --- ### verifyAgentIdentity(proof, policy?) Verifies an ANS or other provider-backed identity, loads Valiron reputation, and returns the requested policy decision. ```typescript const identity = await valiron.verifyAgentIdentity(proof, { anonymous: "challenge", claimed: "block", verified: "allow", minReputationScore: 65, belowMinimumScore: "limit", highRisk: "block", }); ``` For protected API routes, prefer the provider identity middleware below. It calculates `requestDigest` from the exact received bytes. Direct callers are responsible for binding the proof and decision to those same bytes. See [Provider-Backed Agent Identity](https://www.valiron.co/docs/agents/PROVIDER-IDENTITY.md) for proof and result types, signing helpers, identity statuses, and policy semantics. --- ### createValironGate(config) Express-compatible middleware factory. Automatically gates requests based on agent trust. Uses `getAgentProfile()` with your server-side operator API key. The middleware does not perform a fresh agent challenge-response; bind the claimed agent identity to your authenticated caller before authorizing a sensitive action. **Express 4 safe**: The returned middleware wraps the async handler with `Promise.resolve(handler(...)).catch(next)` so async rejections are properly forwarded to Express's error handler. This prevents race conditions when chained with other async middleware (e.g. x402's `paymentMiddleware`). ```typescript import { ValironSDK, createValironGate } from "@valiron/sdk"; const gate = createValironGate(config: { sdk: ValironSDK; minScore?: number; // default: 65 trustSignals?: Array<"8004" | "sandbox" | "world" | "self" | "icebreaker" | "wallet">; cacheTtlMs?: number; // default: 30000 (30s client-side cache) extractAgentId?: (req: Request) => string | null; extractAgentAddress?: (req: Request) => string | null; onAllow?: (req: Request, result: GateResult) => void; onDeny?: (req: Request, res: Response, result: GateResult) => void; }); ``` **Default behavior**: - Extracts agent ID from `x-agent-id` header (on-chain) or `x-agent-address` header (key-based) - Returns 401 if no agent identity is found (with link to identity skill) - Returns 403 if agent is denied - Returns 503 if the trust gate is unreachable (fail-closed) - Caches profiles in memory for 30s to survive x402 retry flows **Example**: ```typescript const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY, chain: "monad" }); // Basic gate app.use("/api/paid", createValironGate({ sdk: valiron })); // Custom threshold + longer cache app.use("/api/premium", createValironGate({ sdk: valiron, minScore: 85, trustSignals: ["8004", "sandbox"], cacheTtlMs: 60_000, // 60s })); // Custom agent ID extraction app.use("/api/custom", createValironGate({ sdk: valiron, extractAgentId: (req) => req.query.agent_id as string, onDeny: (req, res, result) => { res.status(403).json({ error: "Insufficient trust", currentTier: result.tier, riskLevel: result.riskLevel, }); }, })); ``` --- ### dispose() Flush pending telemetry and clean up resources. ```typescript await valiron.dispose(): Promise; ``` Call this when shutting down long-running processes. --- ## Proxy Gateway (Pro) Forward requests through Valiron's edge proxy with automatic trust gating, logging, and SSRF protection. ### proxy(request) ```typescript const result = await valiron.proxy(request: ProxyRequest): Promise; ``` #### ProxyRequest | Field | Type | Required | Description | |-------|------|----------|-------------| | `agentId` | string | yes | Agent to gate | | `targetUrl` | string | yes | Your origin URL to forward to | | `method` | string | no | HTTP method (default: `GET`) | | `headers` | Record | no | Headers to forward | | `body` | string | no | Request body | #### ProxyResponse | Field | Type | Description | |-------|------|-------------| | `statusCode` | number | HTTP status from your origin | | `responseHeaders` | Record | Response headers | | `responseBody` | string | Response body | | `responseMs` | number | Round-trip latency | | `costCharged` | string | USD cost charged | | `route` | string | Route decision applied | | `tierResolved` | string | Trust tier used | **Example**: ```typescript const result = await valiron.proxy({ agentId: "25459", targetUrl: "https://your-api.com/data", method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ query: "example" }), }); ``` > **SSRF Protection:** The proxy blocks requests to private IPs (10.x, 172.16-31.x, 192.168.x), localhost, link-local addresses, and cloud metadata endpoints (169.254.169.254). --- ## Key-Based Agents For Web2 agents that don't have on-chain identities, Valiron supports key-based authentication using EIP-191 challenge-response. **How it works:** 1. Agent sends a request with `x-agent-address: 0x...` header 2. Valiron returns a challenge nonce 3. Agent signs the nonce with their private key 4. Valiron verifies the signature and creates a `KeyAgentProfile` The SDK auto-detects key-based agents from the `x-agent-address` header. No configuration needed. ### Sandbox Evaluation for Key Agents New key agents (verified but not yet scored) receive 403 with `retryAfterMs: 30000`. The middleware attempts to trigger `triggerKeyAgentSandbox()` in the background. This run requires a valid operator API key; if it fails, the agent remains pending until an operator starts an evaluation. After evaluation completes, the agent receives a trust score; middleware allows the request when `verified === true` and the score meets the endpoint's `minScore`. The current key-only sandbox relay does not observe the agent's own HTTP behavior. Do not use that score alone to authorize a high-value purchase or payout. The Web2 Icebreaker demo uses signed key ownership and reports `behavioralScore: null` when no real behavioral evidence exists. You can also trigger evaluation manually: ```typescript const result = await valiron.triggerKeyAgentSandbox("0x1234...abcd"); ``` Or via HTTP: ```bash curl -X POST https://valiron-edge-proxy.onrender.com/operator/trigger-sandbox-key/0x1234...abcd -H "Authorization: Bearer $VALIRON_API_KEY" ``` ### KeyAgentProfile | Field | Type | Description | |-------|------|-------------| | `agentAddress` | string | Ethereum-style address used as the key-based agent identifier | | `verified` | boolean | Whether the agent proved key ownership through challenge-response | | `score` | number \| null | Behavioral score once sandbox evaluation has run | | `tier` | string \| null | Moody's-style trust tier once scored | | `riskLevel` | string \| null | GREEN / YELLOW / RED once scored | | `route` | string \| null | Route decision once scored | | `icebreaker` | object \| null | Redacted from the summary profile; use `getKeyAgentIcebreaker()` with a Pro key | | `reasons` | string[] | Redacted from the summary profile | | `timestamp` | string | ISO timestamp for the profile response | ```typescript const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY }); const { icebreaker } = await valiron.getKeyAgentIcebreaker(agentAddress); ``` The private Icebreaker result contains the attestation state, owner, verified social handles, organization, and profile and credential URLs. It does not contain social connections or mutuals, and does not alter the Web2 behavioral score automatically. --- ## World ID Methods Verify agent-human linkage via Worldcoin's zero-knowledge proof system. ### verifyWorldId(agentId, proof, options?) Submit a World ID proof for verification. ```typescript const result = await valiron.verifyWorldId(agentId: string, proof: WorldIdProof, options?: { chain?: SupportedChain; }): Promise<{ ok: boolean; agentId: string; worldId: WorldIdStatus; timestamp: string }>; ``` **Example**: ```typescript const result = await valiron.verifyWorldId("25459", { merkle_root: "0x...", nullifier_hash: "0x...", proof: "0x...", verification_level: "orb", }); ``` ### getWorldIdStatus(agentId, options?) Check if an agent has a verified World ID. ```typescript const status = await valiron.getWorldIdStatus(agentId: string, options?: { chain?: SupportedChain; }): Promise<{ agentId: string; worldId: WorldIdStatus; timestamp: string }>; // status.worldId: { verified: true, verificationLevel: "orb" } ``` ### getWorldIdProfile(agentId, options?) Get the enriched World ID profile with an allowlisted verification summary. Requires a Pro operator key. ```typescript const profile = await valiron.getWorldIdProfile(agentId: string, options?: { chain?: SupportedChain; }): Promise; ``` --- ## Self Methods Self provides eligible-human verification from government ID credentials and can optionally bind that verified human to Self Agent ID. Valiron stores the verified Self predicates as the selectable `self` trust signal. ### createSelfSession(agentId, request, options?) Create a Self Enterprise verification session for an agent. Redirect the user to the returned `verificationUrl`; Self will call Valiron's signed webhook after completion. ```typescript const session = await valiron.createSelfSession("25459", { selfAgentId: "self-agent-...", successUrl: "https://example.com/verified", failureUrl: "https://example.com/failed", }); console.log(session.self.verificationUrl); ``` ### getSelfStatus(agentId, options?) Check if an agent has a verified Self human eligibility link. ```typescript const { self } = await valiron.getSelfStatus("25459"); console.log(self.verified, self.selfAgentLinked); ``` ### getSelfProfile(agentId, options?) Get the enriched Self profile with eligibility and agent-binding predicates. Requires a Pro operator key; provider identifiers are omitted. ```typescript const profile = await valiron.getSelfProfile("25459"); console.log(profile.humanTrust.hasEligibleHuman); console.log(profile.humanTrust.hasAgentBinding); ``` ### verifySelf(agentId, proof, options?) Deprecated; retained for compatibility until the next major SDK release. Not supported for hosted customer integrations. Use `createSelfSession()`, send the user to the returned verification URL, and check `getSelfStatus()` after verification. Valiron receives the signed result from Self. --- ## 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 and are authenticated with the operator API key. SDK reports are anonymous client reports and may be sampled. Signal counts describe reported selections, not successful verifications. Version comes from the shipped package metadata. Environment defaults to recognized `NODE_ENV` values (`production` → `prod`, `development` → `dev`, `test` → `test`), otherwise `unknown`; set it explicitly for browser applications. Telemetry observer failures do not affect API calls. ### TelemetryConfig | Field | Type | Default | Description | |-------|------|---------|-------------| | `enabled` | boolean | `true` | Enable/disable telemetry | | `sampleRate` | number | `1.0` | Fraction of events to sample (0–1) | | `env` | prod / staging / dev / test / unknown | NODE_ENV or unknown | Environment label | | `onEvent` | function | — | Custom event handler; failures are isolated from API calls | **Example**: ```typescript const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY, telemetry: { enabled: false, // Disable entirely }, }); // Or with custom sampling and handler const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY, telemetry: { sampleRate: 0.1, // Sample 10% of events onEvent: (event) => { // Custom handler myAnalytics.track(event); }, }, }); ``` --- ## Middleware Trust middleware adapters use authenticated profile reads to evaluate route policy locally. Configure the SDK with your server-side operator API key and bind the agent identifier to your authenticated caller. These adapters do not prove possession of the caller's key; provider identity middleware verifies signed proofs separately. Profile results are cached client-side for 30 seconds by default. ### createValironGate(config) — Express See above for full documentation. **Express 4 note**: The returned middleware uses a synchronous wrapper (`Promise.resolve().catch(next)`) to ensure async errors are properly caught. You do NOT need to wrap it yourself — it's safe to use directly with `app.use()` even on Express 4. ### valironFastifyPlugin — Fastify ```typescript import { ValironSDK, valironFastifyPlugin } from "@valiron/sdk"; const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY, chain: "monad" }); fastify.register(valironFastifyPlugin, { sdk: valiron, prefix: "/api/paid", }); ``` ### createValironNextMiddleware — Next.js ```typescript import { ValironSDK, createValironNextMiddleware } from "@valiron/sdk"; const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY }); export default createValironNextMiddleware({ sdk: valiron, paths: ["/api/paid"], }); ``` ### valironGateCheck — Generic (Hono, Koa, etc.) ```typescript import { ValironSDK, valironGateCheck } from "@valiron/sdk"; const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY }); app.use(async (c, next) => { const gate = await valironGateCheck(valiron, { agentId: c.req.header("x-agent-id") ?? null, agentAddress: c.req.header("x-agent-address") ?? null, }); if (!gate.allow) return c.json(gate.body, gate.status); c.set("valiron", gate.result); await next(); }); ``` ### Provider identity middleware — ANS and future adapters Provider identity uses dedicated, non-caching gates because every request has a fresh timestamp and nonce: ```typescript import { createValironIdentityGate, valironIdentityFastifyPlugin, createValironIdentityNextMiddleware, valironIdentityGateCheck, } from "@valiron/sdk"; ``` `createValironIdentityGate({ sdk, policy, getRawBody? })` protects Express and Connect routes. `valironIdentityFastifyPlugin` provides the equivalent Fastify `preHandler`; `createValironIdentityNextMiddleware` hashes a cloned Fetch request; and `valironIdentityGateCheck` accepts explicit proof fields and exact body bytes for Hono, Koa, Bun, and custom runtimes. The default transport uses `x-valiron-identity-provider`, `x-valiron-identity-agent-id`, `x-valiron-identity-signature`, `x-valiron-identity-timestamp`, `x-valiron-identity-nonce`, and optional `x-valiron-identity-key-id`. The request digest is never accepted from a header; the gate calculates it locally. See [Provider-Backed Agent Identity](https://www.valiron.co/docs/agents/PROVIDER-IDENTITY.md#api-owner-enforce-an-identity-policy) for complete Express and agent examples. Policy actions map to HTTP status as follows: | Action | Middleware behavior | | --- | --- | | `allow` | Continue and attach `valironIdentity` to the request | | `challenge` | HTTP 401 with `WWW-Authenticate: ValironIdentity` | | `block` | HTTP 403 | | `limit` | HTTP 429 with `Retry-After: 60` | Unexpected verification failures return 503 and fail closed. Express and Fastify return `IDENTITY_RAW_BODY_REQUIRED` with HTTP 400 when a body was parsed without preserving its exact bytes. ### Client-Side Caching Trust middleware adapters include a built-in in-memory cache (default TTL: 30 seconds). Provider identity gates do not cache request proofs. This is important for payment protocols like x402 that make two requests per payment (discover 402 → retry with payment). Without caching, the second trust check can fail due to cold-start latency on the edge proxy. The Express gate exposes `cacheTtlMs` to override this TTL; set it to `0` to disable caching for that middleware instance. `createValironNextMiddleware` and `valironGateCheck` also accept `cacheTtlMs`. ### Middleware Error Responses All middleware variants return consistent error responses. Each body includes a stable `code`, a human-readable `message`, an `action`, and a `docsUrl` in addition to the trust result fields. | Status | Code | When | |--------|------|------| | 401 | `MISSING_AGENT_IDENTITY` | No agent identity found in request | | 403 | `TRUST_GATE_DENIED` | Agent denied by trust gate; inspect `score`, `tier`, `route`, and `reasons` | | 403 | `AGENT_EVALUATION_PENDING` | New agent pending evaluation; retry after `retryAfterMs` | | 503 | `TRUST_GATE_UNAVAILABLE` | Valiron service unavailable; fail closed and retry shortly | > **Fail-closed:** When the Valiron service is unreachable, middleware returns 503 — it never fails open and never allows unverified agents through. --- ## Response Types ### GateResult Returned by `gate()` and middleware. | Field | Type | Description | |-------|------|-------------| | `allow` | boolean | Whether the agent is allowed access | | `tier` | string | Trust tier (AAA–C) | | `riskLevel` | string | GREEN / YELLOW / RED | | `route` | string | `prod` / `prod_throttled` / `sandbox` / `sandbox_only` | | `meetsThreshold` | boolean | Whether the agent meets the minimum trust threshold | | `agentId` | string | The evaluated agent ID | | `wallet` | string | Agent's wallet address | | `chain` | object | Chain context | | `sandboxRan` | boolean | Whether sandbox was executed | | `cached` | boolean | Whether the result was served from cache | | `walletRisk` | WalletRiskSnapshot? | Wallet assessment when the `wallet` signal was requested | ### WalletRiskSnapshot Returned by `getWalletRisk()` and optionally included in agent profiles and gate results. | Field | Type | Description | |-------|------|-------------| | `available` | boolean | Whether provider-backed history was available | | `wallet` | string | Normalized wallet address | | `network` | SupportedChain | Evaluated network | | `provider` | `alchemy` \| `helius` \| `none` | History provider used | | `score` | number | Confidence-damped trust score, 0-100; higher is better | | `rawScore` | number | Score before confidence damping | | `risk` | number | `100 - score` | | `confidence` | number | History-coverage confidence from 0-1 | | `riskLevel` | string | LOW / MEDIUM / HIGH / CRITICAL | | `reasons` | string[] | Explainable scoring reasons | | `hardFlags` | string[] | Hard-risk flags; any populated flag forces `sandbox_only` in gates | | `features` | WalletHistoryFeatures | Normalized history measurements | | `observedAt` | string | ISO observation timestamp | | `expiresAt` | string | ISO cache-expiry timestamp | | `error` | string? | Provider/configuration failure when unavailable | ### AgentProfile Returned by `getAgentProfile()`. | Field | Type | Description | |-------|------|-------------| | `agentId` | string | ERC-8004 token ID | | `identity` | object | On-chain identity (name, wallet, endpoints, trustModels) | | `onchainReputation` | object | Feedback count, average score, Solana ATOM metrics | | `routing` | object | `{ finalRoute, meetsThreshold }` | | `chain` | object | `{ name, chainId }` | | `timestamp` | string | ISO timestamp | ### Request Headers Headers attached to proxied/gated requests: | Header | Description | |--------|-------------| | `x-agent-id` | The agent's ERC-8004 token ID | | `x-agent-address` | The agent's wallet address (key-based agents) | | `x-valiron-tier` | Resolved trust tier | | `x-valiron-route` | Route decision | | `x-valiron-risk` | Risk level | ### All Exports ```typescript import { ValironSDK, ValironOperator, ValironClient, createValironGate, valironFastifyPlugin, createValironNextMiddleware, valironGateCheck, createValironIdentityGate, valironIdentityFastifyPlugin, createValironIdentityNextMiddleware, valironIdentityGateCheck, createAgentIdentityProof, agentIdentityProofHeaders, sha256RequestDigest, buildAgentIdentitySigningPayload, isValidAddress, generateChallenge, type WalletRiskSnapshot, type WalletRiskLevel, } from "@valiron/sdk"; ``` --- ## Plans & Limits | Feature | Free | Pro | |---------|------|-----| | Gated endpoints | 3 | Unlimited | | Sandbox tests / day | 5 | Unlimited | | Webhooks | — | ✓ | | Proxy gateway | — | ✓ | | Analytics & logs | — | ✓ | | Custom tier thresholds | — | ✓ | | Wallet intelligence | — | ✓ | Pro plan requires an operator API key (`val_op_` prefix) from the [Operator Dashboard](https://www.valiron.co/docs/agents/DASHBOARD.md). --- Source: https://www.valiron.co/docs/agents/TRUST-MODEL.md # Trust Model Valiron uses a hybrid trust model to evaluate AI agents hitting your API. This document explains what behaviors are evaluated and what each trust tier means for your routing decisions. ## Identity proof is not reputation Provider-backed identity separates who controls an agent identity from how that agent should be treated. `anonymous`, `claimed`, and `verified` describe identity evidence only. `verified` remains pseudonymous and does not mean that Valiron identified a human or that the agent has good behavioral history. After identity verification, Valiron looks up reputation using the stable provider-canonical subject. For ANS this is `agentHost`, not the versioned ANS name or registration UUID. The verification endpoint can then return a policy action of `allow`, `limit`, `challenge`, or `block`. An identity with no observed reputation returns an unknown risk level rather than being inferred as risky. ANS trust-index and lifecycle evidence remain external provider evidence; they are not relabeled as Valiron-observed reputation. SDK 1.3 exposes dedicated provider identity gates using `x-valiron-identity-*` proof headers. The ANS resolver and provider credentials remain inside Valiron's hosted service. See [Provider-Backed Agent Identity](https://www.valiron.co/docs/agents/PROVIDER-IDENTITY.md). ## Trust Tiers Valiron assigns a Moody's-style credit tier from a normalized `0-100` trust score: | Tier | Meaning | Route Decision | |------|---------|----------------| | AAA | Prime, highest quality | `prod` | | AA | High grade | `prod` | | A | Upper medium grade | `prod` | | BAA | Medium grade | `prod` or `prod_throttled` | | BA | Speculative | `prod_throttled` | | B | Highly speculative | `sandbox` | | CAA | Substantial risk | `sandbox_only` | | CA | Extremely speculative | `sandbox_only` | | C | Default risk | `sandbox_only` | ## Selectable Trust Signals API sellers can use Valiron plug-and-play, or choose the trust signals used for a specific endpoint. Supported signals: | Signal | Description | Plan | |--------|-------------|------| | `8004` | ERC-8004 / Solana on-chain reputation | Free | | `sandbox` | Valiron behavioral sandbox score | Free | | `world` | World ID human-agent link | Pro | | `self` | Self eligible-human proof and optional Self Agent ID link | Pro | | `icebreaker` | Icebreaker human/background attestation | Pro | | `wallet` | Explainable wallet-history activity and risk signal | Pro | Selected trust signals contribute to a combined trust assessment. Exact weighting and scoring internals are not part of the public API contract. If no signals are specified, Valiron uses the plug-and-play default: sandbox plus any other available trust signals. ## Wallet Intelligence The optional `wallet` signal evaluates the history of the wallet Valiron resolves for an incoming agent. EVM history is read through Alchemy on Ethereum, Base, Arbitrum, Optimism, and Polygon. Solana history is read through Helius. The assessment returns a `0-100` trust score where higher is better, `risk = 100 - score`, a `LOW` / `MEDIUM` / `HIGH` / `CRITICAL` risk level, a confidence value, explainable reasons, and the normalized history features used by the scorer. Current features include transaction count, active days, wallet age, unique counterparties on EVM, failed transaction rate on Solana, and recent activity spikes when enough timestamps are available. Confidence dampens sparse assessments toward a neutral score. If a provider key is missing, the network is unsupported, or the provider times out, wallet intelligence is marked unavailable and excluded from the composite score rather than being treated as malicious. A populated hard-risk flag forces `sandbox_only`, but the current history providers do not independently supply sanctions or malicious-address attribution. Wallet history is bounded, not exhaustive: EVM uses up to 100 recent incoming and 100 recent outgoing transfers plus oldest-transfer lookups; Solana uses up to 1,000 recent signatures. The signal should not be described as AML, sanctions compliance, mixer detection, or complete fund tracing without an additional blockchain-intelligence provider. Request wallet intelligence directly: ```typescript const assessment = await valiron.getWalletRisk("0x52ce...", { chain: "base" }); console.log(assessment.score, assessment.riskLevel, assessment.confidence); ``` Or include it in an endpoint policy: ```typescript app.use("/api/high-trust", createValironGate({ sdk: valiron, trustSignals: ["8004", "sandbox", "wallet"], minScore: 80, })); ``` ## Behavioral Factors Valiron evaluates agents across multiple behavioral dimensions. The behavioral evaluation is holistic — no single sandbox behavior determines the outcome. The specific factors evaluated and their weights are proprietary and not disclosed. ## What Makes an Agent Trustworthy Agents that demonstrate responsible API usage patterns will earn the highest trust tiers. The specific behaviors that contribute to trust scoring are proprietary. In general, agents that are well-behaved, respect API boundaries, and handle errors gracefully will score highly. ## Predictive Risk Valiron also computes an explainable forecast for agents with enough observed history. Predictive risk does not replace the trust gate; it helps operators decide what should happen before the next sensitive action. The forecast combines: - Recent sandbox evaluation scores, route decisions, and score trend - Recurring behavioral failures such as rate-limit disrespect, loops, high error rate, and burstiness - Behavioral fingerprints such as request cadence, backoff pattern, protocol mix, and error-response pattern - Recent operator call logs including production error rate and latency The output includes `predictedNextScore`, `passProbability`, `riskDirection`, `confidence`, `recommendedPolicy`, `recommendedTests`, and human-readable reasons. A low-confidence forecast means Valiron has sparse evidence; it should be treated as a prompt to run another sandbox evaluation rather than a final judgment. Review forecasts on the agent detail page in the Valiron dashboard. Use the SDK trust gate for runtime enforcement. ## Checking an Agent's Trust Status ```typescript import { ValironSDK } from "@valiron/sdk"; const valiron = new ValironSDK({ apiKey: process.env.VALIRON_API_KEY }); const result = await valiron.triggerSandboxTest("AGENT_ID"); console.log(`Tier: ${result.tier}`); console.log(`Risk: ${result.riskLevel}`); console.log(`Meets threshold: ${result.meetsThreshold}`); ``` Or via HTTP: ```bash curl -X POST https://valiron-edge-proxy.onrender.com/operator/trigger-sandbox/AGENT_ID -H "Authorization: Bearer $VALIRON_API_KEY" ``` Use selected signals in middleware: ```typescript app.use("/api/paid", createValironGate({ sdk: valiron, trustSignals: ["8004", "sandbox"], minScore: 70, })); ``` --- ## Solana Trust Evaluation Solana agents go through the same behavioral evaluation pipeline as EVM agents, with additional data from the QuantuLabs ATOM engine. ### Feedback Write-Back Loop Unlike EVM (where feedback must be submitted manually), Solana agents benefit from **automatic feedback write-back**: after every sandbox test or gate evaluation, Valiron writes the computed score to the on-chain ATOM registry via `giveFeedback()`. This means Solana agents build on-chain reputation automatically through normal Valiron usage: ``` Agent evaluated by Valiron sandbox ↓ Score computed (e.g. 92 / AA) ↓ Valiron calls giveFeedback() on-chain ↓ ATOM reputation updated ↓ Next evaluation includes new on-chain data ``` Feedback write-back is managed by Valiron. Write-back is fire-and-forget — if the transaction fails, the evaluation result is still returned.