TypeScript SDK
`@auto-nomos/sdk` — the same client every Nomos-aware agent uses. Fail-closed by default, hand-rollable for advanced use.
@auto-nomos/sdk is the canonical client. If you're writing your agent in TypeScript /
JavaScript and not going through an MCP host, this is what you import.
Install
pnpm add @auto-nomos/sdk
# or: npm i @auto-nomos/sdk
Requires Node 22+. Browser usage is not supported — the SDK signs UCANs locally and that path uses Node crypto APIs.
Five-line example
import { createIntentClient } from '@auto-nomos/sdk';
const client = createIntentClient({
controlPlaneUrl: process.env.NOMOS_CONTROL_URL!,
apiKey: process.env.NOMOS_API_KEY!,
});
const grant = await client.authorize({
command: '/github/issue/list',
resource: { provider: 'github', owner: 'acme', repo: 'app' },
ttlSeconds: 300,
});
grant.ucan is the JWT you put in the Authorization: Bearer … header for the PDP
call. grant.decision is 'allow', 'deny', or 'requires_step_up'.
Real-world example — call GitHub through the PDP
import { createIntentClient } from '@auto-nomos/sdk';
const client = createIntentClient({
controlPlaneUrl: process.env.NOMOS_CONTROL_URL!,
apiKey: process.env.NOMOS_API_KEY!,
});
async function listOpenIssues(owner: string, repo: string) {
const grant = await client.authorize({
command: '/github/issue/list',
resource: { provider: 'github', owner, repo },
ttlSeconds: 300,
purpose: 'triage open issues for the standup',
});
if (grant.decision !== 'allow') {
throw new Error(`Nomos denied: ${grant.reason ?? grant.decision}`);
}
const res = await fetch(
`${process.env.NOMOS_PDP_URL}/github/issue/list?owner=${owner}&repo=${repo}&state=open`,
{ headers: { authorization: `Bearer ${grant.ucan}` } },
);
if (!res.ok) throw new Error(`PDP error ${res.status}`);
return (await res.json()) as { issues: { number: number; title: string }[] };
}
The SDK gives you the UCAN — you do the upstream call. This is intentional: your agent decides retry, parsing, caching.
Failure modes (and the fail-closed default)
The SDK defaults to fail-closed: if the control plane is unreachable or returns 5xx,
authorize() throws. Your agent does not get a "we couldn't decide so we'll allow."
If you want the opposite (graceful degradation behind a feature flag), opt in:
const client = createIntentClient({
controlPlaneUrl: process.env.NOMOS_CONTROL_URL!,
apiKey: process.env.NOMOS_API_KEY!,
failureMode: 'open', // ⚠️ never do this for write actions
});
Opening the gate is a real risk.
failureMode: 'open' should only ever wrap read actions, and only behind a kill
switch. The whole point of the platform is that "the broker is down" means "the
agent doesn't act."
Step-up handling
When the policy returns requires_step_up, the SDK doesn't throw — it returns a grant
with decision: 'requires_step_up' and an approvalEnvelopeId. You decide:
const grant = await client.authorize({ command: '/github/pr/create', /* … */ });
if (grant.decision === 'requires_step_up') {
await notifyHumanToApprove(grant.approvalEnvelopeId);
// poll or wait for webhook, then retry:
const retried = await client.authorize({
command: '/github/pr/create',
cosignerEnvelopeId: grant.approvalEnvelopeId,
/* … */
});
return retried;
}
In MCP hosts (Cursor, Claude, Codex) this is handled for you. In a backend agent loop, you implement the wait — usually a webhook from the dashboard's approval flow.
Customizing the transport
Wrap or replace fetch:
import { createIntentClient } from '@auto-nomos/sdk';
import { traceFetch } from './my-otel-fetch';
const client = createIntentClient({
controlPlaneUrl: process.env.NOMOS_CONTROL_URL!,
apiKey: process.env.NOMOS_API_KEY!,
fetch: traceFetch, // observability, retries, mTLS
});
API surface
| Method | What |
|---|---|
| authorize(req) | Mint a UCAN. Returns { decision, ucan?, reason?, approvalEnvelopeId? }. |
| intent(req) | Dynamic-mode only. Mint a constraint-shaped envelope without committing to one command. |
| revoke(cidOrEnvelopeId) | Kill an envelope. Push fans out to live UCANs within ~5s. |
| verifyReceipt(receipt) | Local check that a receipt's hash + signature are valid. |
| forkChild({ parentChain, … }) | Build a child UCAN chain for swarm sub-agents. |
Full API ref: npmjs.com/package/@auto-nomos/sdk.