Nirmos
TypeScript SDKExamples

Production usage

A practical server integration with managed prompts, cancellation, and observability.

Create one shared client in a server-only module:

// lib/nirmos.ts
import { Nirmos } from "@nirmos/sdk";

function required(name: string): string {
  const value = process.env[name];
  if (!value) throw new Error(`Missing ${name}`);
  return value;
}

export const nirmos = new Nirmos({
  apiKey: required("NIRMOS_API_KEY"),
  baseUrl: process.env.NIRMOS_BASE_URL,
  timeoutMs: 30_000,
  maxRetries: 2,
  promptCache: {
    ttlMs: 60_000,
    maxEntries: 200,
  },
});

Then use it from a service boundary:

// services/support-reply.ts
import { APIError, PromptRenderError } from "@nirmos/sdk";
import { nirmos } from "../lib/nirmos.js";

type SupportReplyInput = {
  customerName: string;
  message: string;
  signal?: AbortSignal;
};

export async function createSupportReply(input: SupportReplyInput) {
  try {
    const completion = await nirmos.gateway.chat.create(
      {
        model: "anthropic/claude-sonnet-4",
        prompt: {
          id: "support-reply",
          variables: {
            customerName: input.customerName,
            policyVersion: "2026-07",
          },
        },
        messages: [{ role: "user", content: input.message }],
        temperature: 0.2,
        maxOutputTokens: 500,
        routingStrategy: "auto",
        fallbackModels: ["openai/gpt-4.1"],
        metadata: {
          feature: "support-reply",
        },
      },
      {
        signal: input.signal,
        timeoutMs: 15_000,
      },
    );

    logger.info({
      event: "nirmos.chat.completed",
      requestId: completion.metadata.requestId,
      traceId: completion.metadata.traceId,
      provider: completion.metadata.provider,
      model: completion.model,
      latencyMs: completion.metadata.latencyMs,
      inputTokens: completion.usage.inputTokens,
      outputTokens: completion.usage.outputTokens,
    });

    return completion.outputText;
  } catch (error) {
    if (error instanceof PromptRenderError) {
      logger.error({
        event: "nirmos.prompt.invalid",
        missingVariables: error.missingVariables,
      });
    } else if (error instanceof APIError) {
      logger.error({
        event: "nirmos.api.failed",
        status: error.status,
        code: error.code,
        requestId: error.requestId,
        retryable: error.retryable,
      });
    }
    throw error;
  }
}

Stream from an HTTP handler

This framework-neutral example writes text deltas to a web ReadableStream:

export async function POST(request: Request): Promise<Response> {
  const { message } = await request.json();
  const encoder = new TextEncoder();

  const output = new ReadableStream({
    async start(controller) {
      try {
        const stream = await nirmos.gateway.chat.stream(
          {
            model: "openai/gpt-4.1-mini",
            prompt: {
              id: "assistant",
              variables: { locale: "en-IN" },
            },
            messages: [{ role: "user", content: message }],
          },
          { signal: request.signal },
        );

        for await (const event of stream) {
          if (event.type === "content.delta" && event.delta) {
            controller.enqueue(encoder.encode(event.delta));
          }
        }
        controller.close();
      } catch (error) {
        controller.error(error);
      }
    },
  });

  return new Response(output, {
    headers: { "content-type": "text/plain; charset=utf-8" },
  });
}

Propagate caller cancellation so model work stops when the downstream connection closes.

On this page