---
name: valiron-trust-gate
version: 1.0.0
description: Add Valiron trust enforcement in front of an API route so agent requests are allowed, denied, throttled, or sent to evaluation before the application handler runs.
homepage: https://www.valiron.co
---

# Valiron Trust Gate Skill

Use this skill when the user wants to protect an API route with Valiron trust enforcement.

## Goal

Add a trust gate before a sensitive API action. The gate must identify the calling agent, evaluate the agent with Valiron, and only allow the action when the result passes the operator's policy.

Valiron supports two incoming identity headers:

- `x-agent-id`: only for agents registered in ERC-8004 or Solana 8004.
- `x-agent-address`: for every agent that is not registered in ERC-8004 or Solana 8004, including Web2 agents and unregistered Web3 agents.

## Step 1: Create a Valiron Operator Account

1. Open `https://www.valiron.co/dashboard`.
2. Create an operator account.
3. Copy the generated API key. It starts with `val_op_` and is only shown once.
4. Store it in the server environment:

```bash
VALIRON_OPERATOR_API_KEY=val_op_...
```

Do not expose this key to frontend/browser code.

## Step 2: Install the SDK

```bash
npm install @valiron/sdk
```

or:

```bash
pnpm add @valiron/sdk
```

## Step 3: Configure Valiron

Create one server-side Valiron client. Choose the default chain that matches the agents expected to call this API.

```ts
import { ValironSDK } from "@valiron/sdk";

export const valiron = new ValironSDK({
  apiKey: process.env.VALIRON_OPERATOR_API_KEY,
  chain: "ethereum",
});
```

Use `chain: "base"`, `chain: "monad"`, `chain: "polygon"`, or `chain: "solana"` when that is the primary agent network. Individual calls can still override the chain.

## Step 4: Require Agent Identity

Before the protected handler runs, require one of these headers:

For registered ERC-8004 or Solana 8004 agents:

```http
x-agent-id: 25459
```

For Web2 agents or unregistered Web3 agents:

```http
x-agent-address: 0xAgentAddress
```

If the agent is not registered in ERC-8004 or Solana 8004 and does not have a persistent keypair yet, send it to:

```text
https://www.valiron.co/auth.md
```

That hosted identity skill creates a persistent key-based agent identity and teaches the agent how to sign Valiron challenges.

## When To Use This

Use this skill when:

- An API route should block risky agents.
- A route should require a minimum Valiron trust score.
- The app needs a single allow/deny decision before executing a paid, privileged, or expensive action.
- The route should support selected trust signals such as `8004`, `sandbox`, `world`, `self`, or `icebreaker`.

Use the hosted API wrapper skill instead when Valiron should host the public agent-facing URL and forward to an existing upstream API.

## Step 5: Implement the Trust Gate

```ts
import express from "express";
import { ValironSDK, createValironGate } from "@valiron/sdk";

const app = express();
const valiron = new ValironSDK({
  apiKey: process.env.VALIRON_OPERATOR_API_KEY,
  chain: "ethereum",
});

app.use(
  "/api/protected",
  createValironGate({
    sdk: valiron,
    minScore: 70,
    trustSignals: ["8004", "sandbox"],
    onDeny: (_req, res, result) => {
      res.status(403).json({
        error: "valiron_trust_gate_denied",
        allow: result.allow,
        score: result.score,
        tier: result.tier,
        riskLevel: result.riskLevel,
        route: result.route,
        agentId: result.agentId,
      });
    },
  })
);

app.post("/api/protected/action", async (req, res) => {
  res.json({
    ok: true,
    valiron: req.valiron,
  });
});
```

## Alternative: Direct SDK Gate Implementation

Use this when the framework does not use Express-style middleware.

```ts
import { ValironSDK } from "@valiron/sdk";

const valiron = new ValironSDK({
  apiKey: process.env.VALIRON_OPERATOR_API_KEY,
  chain: "base",
});

export async function handleRequest(request: Request) {
  const agentId = request.headers.get("x-agent-id");
  const agentAddress = request.headers.get("x-agent-address");
  if (!agentId && !agentAddress) {
    return Response.json(
      {
        error: "missing_agent_identity",
        requiredHeaders: ["x-agent-id for registered 8004 agents", "x-agent-address for unregistered Web2/Web3 agents"],
      },
      { status: 401 }
    );
  }

  if (agentAddress && !agentId) {
    const profile = await valiron.getKeyAgentProfile(agentAddress);
    if (!profile.verified || profile.score === null || profile.route === "sandbox_only") {
      return Response.json(
        {
          error: "valiron_key_agent_denied",
          score: profile.score,
          tier: profile.tier,
          riskLevel: profile.riskLevel,
          route: profile.route,
        },
        { status: 403 }
      );
    }

    return Response.json({ ok: true });
  }

  const gate = await valiron.gate(agentId, {
    minScore: 70,
    trustSignals: ["8004", "sandbox"],
    ttlMs: 30 * 60 * 1000,
  });

  if (!gate.allow) {
    return Response.json(
      {
        error: "valiron_trust_gate_denied",
        score: gate.score,
        tier: gate.tier,
        riskLevel: gate.riskLevel,
        route: gate.route,
        provisional: gate.provisional ?? false,
      },
      { status: 403 }
    );
  }

  return Response.json({ ok: true });
}
```

## Trust Signals

Start with the free default:

```ts
trustSignals: ["8004", "sandbox"]
```

Use enriched scoring when the operator has access to Pro or Enterprise trust signals:

```ts
trustSignals: ["8004", "sandbox", "world", "self", "icebreaker"]
```

Signal meanings:

- `8004`: ERC-8004 or Solana on-chain reputation.
- `sandbox`: Valiron behavioral sandbox score.
- `world`: World ID human-agent link.
- `self`: Self eligible-human proof and optional Self Agent ID link.
- `icebreaker`: Icebreaker human/background attestation.

## Response Handling

Handle these cases:

- Missing identity: return `401` and tell the caller to send `x-agent-id` only if it is registered in ERC-8004 or Solana 8004; otherwise send `x-agent-address`.
- Pending evaluation: return or preserve Valiron's retry payload, usually `retryAfterMs`.
- Denied agent: return `403` with score, tier, route, and risk level.
- Allowed agent: continue to the application handler.
- Provisional result: treat conservatively because a full sandbox run may still be running.

## Test Checklist

1. Call the route without `x-agent-id` or `x-agent-address`; expect `401` or Valiron missing identity response.
2. Call with a known trusted registered `x-agent-id`; expect the route handler to run.
3. Call with a verified key-based `x-agent-address`; expect the key-agent path to run.
4. Call with a low-trust agent; expect `403`.
5. Verify the app does not execute the protected action before the gate passes.
6. Verify the route never exposes the operator API key.

## Acceptance Criteria

- Protected routes run Valiron before application logic.
- Agent identity is read from request headers.
- Denied agents receive a clear JSON error.
- Allowed requests include Valiron gate metadata in server-side request context or logs.
- Trust signal selection is explicit and matches the operator's plan.
