API Reference

Every public type and function in the SDK family. Mirrors the TypeScript declarations shipped alongside each package on npm.


@avanor/sdk (core)

init(config) — namespace + named export

Initialize the singleton client. Idempotent — subsequent calls with the same config return the same client; subsequent calls with diverging config throw AvanorConfigError. The Quickstart uses the namespace form; the named export is identical.

ts
import { Avanor } from '@avanor/sdk';

const avanor = Avanor.init({
  apiKey: process.env.AVANOR_API_KEY!,
  environment: 'prod',
  service: 'broker-portal',
});
ts
import { init } from '@avanor/sdk';

const avanor = init({
  apiKey: process.env.AVANOR_API_KEY!,
  environment: 'prod',
  service: 'broker-portal',
});

getClient()

Returns the initialized client. Throws AvanorConfigError if init() has not been called.

AvanorConfig

ts
interface AvanorConfig {
  apiKey: string;
  environment: 'dev' | 'staging' | 'prod' | string;
  service: string;
  endpoint?: string;            // default: https://api.avanor.ai/v1/ingest
  failureMode?: FailureMode;    // default: 'fail-soft'
  sampleRate?: number;          // 0..1, applies only to track(); default 1.0
  batchSize?: number;           // default 256
  flushInterval?: number;       // ms; default 5000
  maxQueueSize?: number;        // default 2048
  disableAutoInstrumentation?: AutoInstrumentationName[];
  tls?: { caBundle?: string; certFingerprint?: string };
  logger?: AvanorLogger;
  fetchImpl?: typeof fetch;
  ingestTimeoutMs?: number;     // default 30_000
}

AvanorClient

ts
interface AvanorClient {
  track(event: string, attrs?: Attributes, opts?: CallOpts): void;
  allow(action: string, attrs?: Attributes, opts?: CallOpts): Promise<Decision>;
  attest(action: string, payload: AttestPayload, opts?: CallOpts): Promise<Attestation>;
  withSpan<T>(name: string, fn: (span: Span) => Promise<T> | T, attrs?: Attributes): Promise<T>;
  middleware(): RequestHandler;             // Express/Fastify-compatible
  flush(timeoutMs?: number): Promise<void>;
  shutdown(timeoutMs?: number): Promise<void>;
  onKillSwitch(handler: (reason: string) => void): Unsubscribe;
}
  • track — passive event capture, fire-and-forget.
  • allow — pre-action policy gate; server evaluates against tenant-authored policies.
  • attest — post-action attestation; writes a hash-chained audit row.
  • withSpan — wrap a function in an OTel span; Sentry-style fork-on-write scope.
  • middleware — Express/Fastify-compatible request handler.
  • flush — drain the in-memory queue.
  • shutdown — gracefully terminate: flush, stop timers, release the singleton.
  • onKillSwitch — subscribe to kill-switch transitions; returns an unsubscribe handle.

Result shapes — Decision, Attestation, FailureMode

ts
type FailureMode = 'fail-open' | 'fail-closed' | 'fail-soft';

type AutoInstrumentationName =
  | 'openai'
  | 'anthropic'
  | 'vercel-ai'
  | 'express'
  | 'fastify';

interface Decision {
  allow: boolean;
  reason?: string;
  policyId?: string;
  approvalId?: string;           // present when HITL escalation triggered (v0.5+)
  expiresAt?: number;            // epoch ms; for cached decisions
}

interface AttestPayload {
  input?: unknown;
  output?: unknown;
  status: 'ok' | 'error';
  error?: { code: string; message: string };
}

interface Attestation {
  attestId: string;              // server-issued
  hashChainPosition: number;
  sha256: string;
}

Helper types — Attributes, CallOpts, Span

ts
type AttributeValue =
  | string | number | boolean
  | string[] | number[] | boolean[]
  | null;

type Attributes = Record<string, AttributeValue>;

interface CallOpts {
  failureMode?: FailureMode;     // per-call override
  timeoutMs?: number;
  parentSpan?: Span;
  idempotencyKey?: string;
}

interface Span {
  setAttribute(key: string, value: AttributeValue): void;
  setStatus(status: 'ok' | 'error', message?: string): void;
  addEvent(name: string, attrs?: Attributes): void;
  end(): void;
  readonly traceId: string;
  readonly spanId: string;
  readonly parentSpanId?: string;
}

interface AvanorLogger {
  debug(msg: string, attrs?: Attributes): void;
  info(msg: string, attrs?: Attributes): void;
  warn(msg: string, attrs?: Attributes): void;
  error(msg: string, attrs?: Attributes): void;
}

type Unsubscribe = () => void;
type RequestHandler = (req: unknown, res: unknown, next: () => void) => void;

Errors

ts
class AvanorError extends Error {
  code: string;                  // 'avanor.error' (subclasses narrow)
}

class AvanorUnreachable extends AvanorError {
  // code = 'avanor.unreachable'
  // Thrown only when failureMode='fail-closed'.
}

class AvanorConfigError extends AvanorError {
  // code = 'avanor.config_error'
  // Synchronous; misconfigured init().
}

class AvanorPolicyDenied extends AvanorError {
  // code = 'avanor.policy_denied'
  // Not thrown by the SDK — supplied for customer try/catch flow control.
  decision: Decision;
}

class AvanorMalformedResponse extends AvanorError {
  // code = 'avanor.malformed_response'
  // Server reachable but response body didn't match schema.
}

Subpath exports — @avanor/sdk/attributes, @avanor/sdk/spans

Canonical attribute keys and span names. Customers writing their own custom instrumentations should use these constants so attributes line up with what Avanor's own first-party adapters emit.

ts
import {
  AVANOR_PUBLIC_ATTRIBUTE_KEYS,
  // GenAI semconv subset (re-exported from @avanor/sdk for stability)
  GEN_AI_REQUEST_MODEL,
  GEN_AI_USAGE_INPUT_TOKENS,
  GEN_AI_USAGE_OUTPUT_TOKENS,
} from '@avanor/sdk/attributes';

import { SPAN_NAMES } from '@avanor/sdk/spans';
// SPAN_NAMES = { LLM_CALL, POLICY_DENY, MCP_CALL, AGENT_RUN, KILL_SWITCH_HIT }

@avanor/sdk-express

Express and Fastify factories that turn avanor.middleware()into the framework's native shape. peerDeps: express@^4.0.0 || ^5.0.0 and fastify@^4.0.0 || ^5.0.0 (both optional).

ts
import { expressMiddleware, fastifyPlugin } from '@avanor/sdk-express';

interface ExpressMiddlewareOptions {
  client?: AvanorClient;         // defaults to getClient()
}

function expressMiddleware(opts?: ExpressMiddlewareOptions): RequestHandler;

interface FastifyPluginOptions {
  client?: AvanorClient;
}

const fastifyPlugin: (instance, opts: FastifyPluginOptions, done) => void;

@avanor/sdk-openai

Monkey-patches OpenAI and Anthropic SDK clients in place. Returns the SAME instance back for chaining. Idempotent — calling twice is a no-op on the second call. peerDeps: openai@^4.x and @anthropic-ai/sdk@^0.x (both optional). Spans carry gen_ai.* semconv attributes per OTel GenAI v1.37.

ts
import { instrumentOpenAI, instrumentAnthropic } from '@avanor/sdk-openai';

interface InstrumentOpenAIOptions {
  client?: AvanorClient;         // defaults to getClient()
}

// Monkey-patches in place; returns the SAME instance back.
function instrumentOpenAI<T extends object>(
  openai: T,
  opts?: InstrumentOpenAIOptions,
): T;

interface InstrumentAnthropicOptions {
  client?: AvanorClient;
}

function instrumentAnthropic<T extends object>(
  anthropic: T,
  opts?: InstrumentAnthropicOptions,
): T;

@avanor/sdk-vercel-ai

Returns an object exposing wrapped generateText, streamText, and generateObject from the Vercel AI SDK. peerDep: ai@^4.x (optional).

ts
import { instrumentVercelAI } from '@avanor/sdk-vercel-ai';

interface InstrumentVercelAIOptions {
  client?: AvanorClient;
}

interface InstrumentedVercelAI {
  generateText: typeof import('ai').generateText;
  streamText: typeof import('ai').streamText;
  generateObject: typeof import('ai').generateObject;
}

function instrumentVercelAI(opts?: InstrumentVercelAIOptions): InstrumentedVercelAI;

SemVer and stability

Strict MAJOR.MINOR.PATCH per Stripe SDK policy. Breaking changes to a method at 1.x+ require a major bump and a 12-month deprecation window with @deprecated JSDoc tags, console warnings, and dashboard banners. v0.x is pre-GA — minor versions may carry breaking changes until 1.0.0.

License

FSL-1.1-ALv2 (Functional Source License v1.1, Apache 2.0 Future License). Source-available, free for any Avanor customer, no use in a competing commercial product. Each version converts to Apache 2.0 on the second anniversary of its publication. Binary distribution on npm is unrestricted.

Next