@nomosprotocol/sdk
v1.2.1
Published
Official TypeScript SDK for the NOMOS governance runtime
Maintainers
Readme
@nomosprotocol/sdk
Official TypeScript SDK for NOMOS — ask a public authority a question from your code and get back a deterministic, cryptographically verifiable verdict.
npm install @nomosprotocol/sdknomos.can() — the keyless primitive
Every public authority on the NOMOS Exchange is queryable with one call. No API key, no setup — this is the front door.
import { nomos } from "@nomosprotocol/sdk";
const verdict = await nomos.can({
authority: "eu-ai-act.nomos",
ai_categorises_biometric_data_for_sensitive_attributes: true,
});
if (!verdict.allowed) {
console.log(verdict.verdict); // "DENIED"
console.log(verdict.reason); // why
console.log(verdict.query_id); // permanent transcript id
}Facts can be spread flat alongside authority (as above), or passed explicitly:
const verdict = await nomos.can({
authority: "eu-ai-act.nomos",
inputs: { ai_categorises_biometric_data_for_sensitive_attributes: true },
action: "screen a new feature before launch", // optional, recorded in the transcript
});The verdict
nomos.can() always returns the authority's own verdict, verbatim — nothing invented, nothing paraphrased:
| Field | Type | Meaning |
|---|---|---|
| allowed | boolean | true only when verdict === "AUTHORIZED" |
| verdict | "AUTHORIZED" \| "DENIED" \| "ESCALATED" | The authority's own answer |
| reason | string | Human-readable explanation |
| rule | string \| null | The rule id that decided it, if any |
| query_id | string | Permanent, addressable transcript id |
| url | string | Path to the transcript's permalink page |
| authority | { id, title, standing } | Which authority answered, and its standing |
| missing_inputs | string[] | Fields the authority needed but didn't get — present on ESCALATED |
ESCALATED means the authority needs more facts to decide — not a flat no. Check missing_inputs for what to supply.
Every call mints a permanent, cryptographically sealed transcript — open query_id any time at nomosprotocol.com/queries/<query_id> to replay exactly what was asked and answered, bound to the exact authority version that responded.
Error handling
A failed call (unknown authority, network issue, upstream error) rejects with a typed NomosError subclass — never a bare Error — so you can branch on instanceof or the stable .code string:
import { nomos, NomosNotFoundError, NomosNetworkError } from "@nomosprotocol/sdk";
try {
const verdict = await nomos.can({ authority: "eu-ai-act.nomos", ...facts });
} catch (err) {
if (err instanceof NomosNotFoundError) {
// authority slug/id doesn't exist — err.code === 'not_found'
} else if (err instanceof NomosNetworkError) {
// request timed out or the network failed
} else {
throw err;
}
}Options
await nomos.can(
{ authority: "...", ...facts },
{
baseUrl: "https://www.nomosprotocol.com", // override for local/staging use
signal: abortController.signal, // cancel the request
},
);Nomos — authenticated client
For private/custom artifacts, governance generation, and webhook verification, use the authenticated client:
import { Nomos } from "@nomosprotocol/sdk";
const client = new Nomos("nms_live_..."); // or "nms_test_..." for test mode
const result = await client.decisions.verify({
artifact_id: "your_artifact_id",
decision_context: { /* facts */ },
});
for await (const artifact of client.artifacts.listAutoPaging()) {
console.log(artifact.id);
}
const event = await client.webhooks.constructEvent(payload, signatureHeader, webhookSecret);See nomosprotocol.com/docs for full API reference, error types, and webhook event shapes.
Requirements
Node.js 18+. Ships as dual ESM/CJS with full TypeScript types.
License
MIT
