Reliable LLM calls,
by default.

A lightweight resilience layer for OpenAI-compatible chat completions: retries, timeouts, caching, and circuit breaking, dependency-light and typed from the start.

$ npm install vern-llm
example.ts
import OpenAI from 'openai';
import { VernLLM } from 'vern-llm';

export const llm = new VernLLM({
  client: new OpenAI({ apiKey: process.env.OPENAI_API_KEY }),
  model: 'gpt-4o',

  maxRetries: 3,
  timeoutMs: 10_000,
  circuitBreaker: true,

  onUsage: ({ totalTokens }) => {
    console.log(`Used ${totalTokens} tokens`);
  },
});

export const summary = await llm.cachedLLMCall({
  cacheKey: `resume:${resumeId}`,
  ttl: 3600,
  call: {
    systemPrompt: 'Analyze this resume and return structured hiring insights.',
    userContent: resumeText,
    schema: HiringSummarySchema, // Zod schema
  },
});

One config. Every failure mode covered.

  • maxRetries: 33 attempts with exponential backoff
  • timeoutMs: 10_00010s hard timeout per attempt
  • circuitBreaker: truetrips after repeated failures
  • onUsagetoken usage reported per call
  • cachedLLMCallidentical calls skip the network
  • schemaresponse validated and typed via Zod
maxRetries: 3

Retry with backoff

Retries a failed call up to N times with exponential backoff and jitter between attempts.

timeoutMs: 10_000

Per-attempt timeout

Each attempt is raced against a hard timeout, so no single request can hang the call.

circuitBreaker: true

Circuit breaker

Trips after repeated failures and rejects immediately while open, call getCircuitState() to inspect it.

nonRetryableStatus: [400, 401, 403]

Fail-fast status codes

Status codes you mark as non-retryable skip the retry loop entirely, no point retrying a 401.

llm.cachedLLMCall({ cacheKey, ttl, call })

Caching

Wraps call() with a pluggable cache adapter, identical calls return without hitting the network.

schema: HiringSummarySchema

Structured output

Pass a Zod schema inside call params, get back parsed, validated, typed JSON or a validation error.

onUsage: ({ totalTokens }) => {}

Usage tracking

Reports prompt, completion, and total tokens per call, only fires when the provider returns usage data.

logger: myLogger

Pluggable logger

Bring your own Logger implementation, or fall back to the built-in console logger gated by debug.

Works with
OpenAI-compatible APIsAnthropicGeminiAWS BedrockCustom APIs

Why vern-llm?

Every project calling an LLM API ends up writing the same defensive code; retry logic, timeouts, a circuit breaker, a cache layer, usually copied between projects and slightly wrong each time.

vern-llm is a thin, dependency-light wrapper that gives you these primitives with sensible defaults out of the box, and lets you override exactly what you need. It works with any OpenAI-compatible client, plus Anthropic, Gemini, and Bedrock adapters. No vendor lock-in.

Stop reinventing the resilience layer.

npm install vern-llm