Skip to content

Developers

SDKs and client libraries

Typed client libraries for connecting AI systems, evaluating actions, reading traces and managing policies from your own code.

What it is

A typed wrapper over the HTTP API, plus webhook verification. Nothing in the SDK is required — every operation is available over curl, and the wire format is the contract.

If a behaviour exists only in the SDK, that is a bug in the API.

Getting it

A typed wrapper, and nothing you are obliged to use.

The SDK exists to save you writing request builders and to give you types for the responses. The HTTP API is the contract, and anything the SDK can do that the API cannot would be a defect rather than a feature.

Install
npm install @opsai/sdk

Both libraries are thin by design: request signing, typed responses, cursor pagination, and webhook signature verification. There is no framework adapter, because governance attaches at the boundary rather than inside your control flow — why there is no framework SDK.

The four things you will call

Evaluate, read the trace, list the refusals, verify a webhook.

Most integrations use exactly these. Everything else in the API is administrative and is more often done in the console than in code.

TypeScript
import { OpsAI, verifyWebhook } from '@opsai/sdk';

const opsai = new OpsAI({ apiKey: process.env.OPSAI_API_KEY });

// 1. Decide.
const decision = await opsai.actions.evaluate({
  agent: 'refund-resolver',
  action: 'issue.refund',
  subject: 'ORD-40122',
  amount: { currency: 'INR', value: 18400 },
  idempotencyKey: 'ACT-7512',
});

// 2. Read the trace — exists for refusals too.
const trace = await opsai.actions.trace('ACT-7512');
trace.stages.length; // 6

// 3. The refusals. The half worth looking at.
const denied = await opsai.actions.list({ decision: 'denied' });
Python
from opsai import OpsAI

opsai = OpsAI()  # reads OPSAI_API_KEY

decision = opsai.actions.evaluate(
    agent="refund-resolver",
    action="issue.refund",
    subject="ORD-40122",
    amount={"currency": "INR", "value": 18400},
    idempotency_key="ACT-7512",
)

trace = opsai.actions.trace("ACT-7512")
len(trace.stages)  # 6

denied = opsai.actions.list(decision="denied")

Webhook verification is the one thing worth taking from the SDK.

It throws on a bad signature rather than returning a falsy value, so a forgotten check fails loudly instead of silently accepting forged events. That distinction is the reason to use the helper rather than write it yourself.

app/api/opsai/route.ts
export async function POST(request: Request) {
  const body = await request.text();

  // Throws on a bad signature. Never returns null.
  const event = verifyWebhook({
    body,
    signature: request.headers.get('opsai-signature'),
    secret: process.env.OPSAI_WEBHOOK_SECRET,
  });

  if (event.type === 'action.expired') {
    // A decision nobody made. The event most likely to be invisible otherwise.
    await recordExpiry(event.data);
  }

  return new Response(null, { status: 204 });
}

What it deliberately will not do

Three absences, each preventing a specific failure.

These are the things a convenience layer gets wrong precisely because it is trying to be convenient. Every one of them would make the SDK feel nicer and the system less trustworthy.

It will not retry a mutating call without an idempotency key
A transparent retry of an evaluation is how one refund becomes two. The SDK retries reads freely and refuses to retry a write unless you supplied a key that makes the second attempt provably the same as the first.
It does not evaluate policy on the client
A client-side cache of a rule is a rule that can be stale at the moment it matters, and a decision made locally produces no evidence record. Every evaluation is a round trip, which is why the latency budget is single-digit milliseconds.
It does not cache credentials or grants
A grant is scoped to one authorized action and expires in seconds. Holding one for reuse would turn a single-use authorization into a standing capability, which is the whole thing the design avoids.

Where to go

The conventions are worth ten minutes before you write the client.

Idempotency, pagination, versioning and the shape of an error. All four are decisions you inherit rather than make, and knowing them saves rediscovering them in production.