For developers

Trust rails in an afternoon.

One API call, one verdict, with reasons. The bureau is live at suila-bureau-vercel.vercel.app — hit /healthz right now.

The eve three-rail kit

Three integration points, all shipped in the open reference demos. Works with Vercel eve / Passport.

Rail 1 · Outbound gate

The approval policy IS the verdict

Attach trustRankApproval or mutualHandshakeApproval to any eve tool. The bureau check runs before dispatch; REFUSE never executes, ESCALATE parks for a human.

import { defineTool } from "eve/tools";
import { mutualHandshakeApproval } from "../lib/suila";

export default defineTool({
  description: "Place an order with the merchant agent",
  inputSchema: input,
  // the handshake IS the approval decision
  approval: mutualHandshakeApproval({
    stakes: (i) => i?.amountUsd ?? 1,
  }),
  async execute({ item, amountUsd }) { /* ... */ },
});
Rail 2 · Inbound gate

suilaGate at your door

Wrap your existing route auth — jwtHmac, vercelOidc, anything in the walk. The inner authenticator proves identity; the gate scores it. Fails closed.

import { suilaGate } from "./lib/suila";

// inner auth verifies WHO the caller is;
// the gate asks the bureau whether to TRUST it
export const auth = suilaGate(
  jwtHmac(process.env.DEMO_JWT_SECRET),
);
// Vercel-to-Vercel: suilaGate(vercelOidc())
// refusal -> HTTP 403 with the scored reason
Rail 3 · Write rail

Signed outcomes, as a side effect

An observe-only hook reports settled outcomes to POST /v1/outcomes. Evidence accrues from normal use — no separate instrumentation project.

// observe-only hook: evidence is a side
// effect of simply using the agent
await reportOutcome({
  subject: MERCHANT_ID,
  reporter: BUYER_ID,
  outcome: 1,        // 1 success, 0 failure
  stakes: amountUsd,
  grade: "counterparty",
});

The fourth piece runs itself: a weekly Kaizen schedule calls POST /v1/kaizen/run to re-fit weights against the newest signed outcomes and promote a new config only through statistical gates.

The handshake, on the wire

One O(1) call scores both directions and returns a combined decision — the most restrictive leg wins.

Request
POST /v1/handshake
{
  "initiator":    "agent://suila-demo/buyer",
  "counterparty": "agent://suila-demo/merchant",
  "stakes": 1500
}
Response — both legs + combined decision
{
  "initiator": "agent://suila-demo/buyer",
  "counterparty": "agent://suila-demo/merchant",
  "stakes": 1500,
  "a_to_b": { "subject": "agent://suila-demo/merchant",
              "effective_score": 575, "tier": "B",
              "regime": "stable",
              "decision": "connect_with_verification", "reasons": [] },
  "b_to_a": { "subject": "agent://suila-demo/buyer",
              "effective_score": 437.5, "tier": "REVIEW",
              "decision": "escalate", "reasons": ["..."] },
  "decision": "escalate",
  "connected": false,
  "reasons": ["..."]
}
CONNECT

Both legs clear the stakes — the connection opens autonomously.

CONNECT + VERIFY

Proceed, with additional verification on the weaker leg.

ESCALATE

A human approves before the connection opens — eve parks the session durably.

REFUSE

No connection: 403 with the scored reason, auditable on both sides.

Two SDKs, one bureau

TypeScript client

TrustRankClient for eve, edge functions, and Node: check() returns a CheckVerdict, handshake() a HandshakeVerdict with the typed ConnectDecision ladder. Never throws on a low score — inspect the verdict.

import { TrustRankClient } from "@suila/trustrank";

const tr = new TrustRankClient({
  baseUrl: "https://suila-bureau-vercel.vercel.app",
});

const v = await tr.check("agent://acme/checkout", { stakes: 250 });
if (!v.allowed) refuse(v.reasons);

const hs = await tr.handshake(buyer, merchant, { stakes: 1500 });
// hs.decision: ConnectDecision =
//   "connect" | "connect_with_verification"
//   | "escalate" | "refuse"
Get it — installable today
# install straight from this site — works today
npm install https://suilaai.com/sdk/suila-trustrank-0.1.0.tgz

# enforce a gate in one line (throws TrustGateError on refuse)
await tr.require("agent://acme/checkout", { stakes: 250 });

# or wrap any function with a trust gate, eve-style
const transferSafely = tr.withTrustRank(doTransfer, {
  agentId: (to) => to,               // e.g. a Passport agent id
  stakes: (_to, amountUsd) => amountUsd,
});

npm registry publication ships with the enrollment beta — the tarball above is the same package, installable now against the live bureau.

Python engine

The scoring engine and FastAPI bureau behind the endpoints: /v1/check, /v1/handshake, /v1/outcomes, /v1/kaizen/run. A 102-test reference implementation with a formal convergence proof for the fixed-point solve — the same engine that serves the live bureau.

Being scored is free. The economy pays to read the score.