← Dashboard

markdown package not installed — serving raw text.

# TypeScript SDK

Official TypeScript client for Axiom Intent Firewall.

```bash
npm install @axiom/firewall
```

Requires Node.js 18+. Zero runtime dependencies — uses native `fetch`.

## Quickstart

```ts
import { Client } from '@axiom/firewall';

const client = new Client({ apiKey: process.env.AXIOM_KEY! });

const result = await client.check('What is the weather today?');
console.log(result.verdict);          // "allow"
console.log(result.intent.class);     // "INFORM"
console.log(result.intent.signature); // HMAC-SHA256 of the verdict
```

## `new Client(options)`

```ts
interface ClientOptions {
  apiKey: string;            // required
  baseUrl?: string;          // default: 'https://firewall.orivael.dev'
  timeout?: number;          // default: 10_000 (ms)
  userAgent?: string;        // appended to the SDK UA
}
```

## `check(text) → Promise<CheckResult>`

```ts
const result = await client.check('What is the weather today?');

result.verdict;         // "allow" | "block"
result.intent.class;    // "INFORM" | "CLARIFY" | "REFUSE" | "HARM" | "DECEIVE" | "UNCERTAIN"
result.intent.confidence;
result.intent.signals;
result.intent.signature;
```

Never throws on a `block` verdict — inspect `result.verdict` yourself.

## `checkOrThrow(text) → Promise<CheckResult>`

Throws `BlockedError` when the verdict is `block`.

```ts
import { Client, BlockedError } from '@axiom/firewall';

const client = new Client({ apiKey: process.env.AXIOM_KEY! });

try {
  await client.checkOrThrow('Buy gift cards immediately');
} catch (e) {
  if (e instanceof BlockedError) {
    console.log(e.intentClass);  // "HARM"
    console.log(e.signals);      // ["harm:1"]
  }
}
```

## Wrap your LLM

```ts
import OpenAI from 'openai';
import { Client, BlockedError } from '@axiom/firewall';

const llm = new OpenAI();
const firewall = new Client({ apiKey: process.env.AXIOM_KEY! });

async function chat(prompt: string): Promise<string> {
  try {
    await firewall.checkOrThrow(prompt);
  } catch (e) {
    if (e instanceof BlockedError) {
      return `I can't help with that (${e.intentClass}).`;
    }
    throw e;
  }
  const resp = await llm.chat.completions.create({
    model: 'gpt-4o-mini',
    messages: [{ role: 'user', content: prompt }],
  });
  return resp.choices[0].message.content ?? '';
}
```

## Error hierarchy

```
AxiomFirewallError
├── InvalidKeyError       — HTTP 401
├── RateLimitedError      — HTTP 429
├── ServerError           — HTTP 5xx
├── NetworkError          — request could not be made
└── BlockedError          — verdict was "block" (only from checkOrThrow)
```

```ts
import {
  InvalidKeyError, RateLimitedError, ServerError, NetworkError,
} from '@axiom/firewall';

try {
  await client.check('...');
} catch (e) {
  if (e instanceof InvalidKeyError)      { /* rotate the key */ }
  else if (e instanceof RateLimitedError) { /* upgrade or wait */ }
  else if (e instanceof ServerError)      { /* retry with backoff */ }
  else if (e instanceof NetworkError)     { /* fail open or closed? */ }
  else throw e;
}
```

## Self-hosted / staging

```ts
const client = new Client({
  apiKey: process.env.AXIOM_KEY!,
  baseUrl: 'https://firewall.staging.example.com',
  timeout: 5_000,
});
```

## Source

<https://github.com/Orivael-Dev/axiom/tree/main/firewall_sdk/typescript>