← klaro.services
SentinelConsentraKlaroShieldBundlesPricing

Recipes

Copy-paste ready. Every snippet here is checked against the shipped @klaroshield/sdk API -- not written from memory, not aspirational.

← Back to KlaroShield

Providers

OpenAI + exponential backoff
Wrap chat.completions.create with retries({ max: 3, backoff: "exponential" }) so transient 429s never bubble up to your users.
View recipe →
Anthropic Claude with retries + secret masking
Same pattern as OpenAI -- klaro.wrap() doesn't care which provider's method it's wrapping.
View recipe →
Claude fallback when GPT-5 is rate limited
Wrap each provider in its own Klaro instance, then catch a retry-exhausted OpenAI call and fail over to Claude.
View recipe →
Google Gemini
Wrap @google/generative-ai's generateContent the same way -- retries and redaction apply before the request ever reaches Google.
View recipe →
OpenRouter (OpenAI-compatible endpoint)
OpenRouter uses the OpenAI SDK shape with a different baseURL and key -- the wrap is identical to the direct OpenAI recipe.
View recipe →
Vercel AI SDK's generateText
generateText is a plain function, not a method -- wrap it directly, no .bind() needed.
View recipe →

Agent frameworks

LangChain agent
createAgent()'s .invoke() is a plain async function like everything else here -- wrap it the same way.
View recipe →
LlamaIndex LLM
@llamaindex/openai's llm.chat() is an instance method like OpenAI's own SDK -- bind it the same way.
View recipe →

Frameworks

Express route handler
klaro.wrap() works on any async function -- it doesn't care whether the caller is a server action, a route handler, or a plain script.
View recipe →
Fastify route handler
Same wrap, Fastify's handler signature instead of Express's.
View recipe →
NestJS injectable service
Construct the Klaro instance once as a private field on the service -- every method on the class shares the same retry/redaction/budget config.
View recipe →
Next.js App Router API route
The same klaro instance can be shared across every route in your app -- construct it once, import it everywhere.
View recipe →
Mask PII in a Next.js server action
Wrap a server action's model call with pii({ mode: "mask" }) so request logs never contain a real email or phone number.
View recipe →
Cloudflare Workers fetch handler
Klaro is pure JS with no Node-only APIs in its call path other than local storage (which reads/writes relative to process.cwd() -- skip logging()'s file persistence on Workers and use format: "silent" or "json" piped to your own sink instead.
View recipe →

Validation & structured output

Force structured JSON output with Zod
validation() re-runs the whole call (not just re-parsing) when the model's output fails your schema -- LLM non-determinism is often fixed by a fresh attempt.
View recipe →
Validate without Zod
validation() only needs a safeParse() method matching Zod's shape -- write your own if you don't want the dependency.
View recipe →
Retries and validation together
Put validation() closest to the call (last .use()) so a transient network error retries via retries() first, and a schema failure retries separately via validation()'s own maxRetries.
View recipe →

Budgeting & cost

Handle a budget cap without crashing
budget() throws once the monthly cap is hit by default -- pass onExceeded to decide what happens instead (log it, alert, degrade gracefully).
View recipe →
Separate budgets for staging vs production
budget() tracks spend from .klaro/budget.jsonl in the current working directory -- run staging and prod as separate processes/deployments and each gets its own independent cap.
View recipe →

Secrets & PII

Block a call outright if it contains a secret
secrets({ mode: "block" }) throws instead of masking -- for pipelines where a leaked key means the call should never go out at all.
View recipe →
Only scan for the PII types you actually handle
pii({ types }) lets you skip categories that don't apply -- a support bot that never touches payments doesn't need the credit_card regex running on every call.
View recipe →

Retries & reliability

Custom retry predicate
The default only retries 429/5xx and a few network error codes -- pass isRetryable to match a provider's own non-standard error shape.
View recipe →
Fixed backoff for a strict internal SLA
Exponential backoff is the default -- switch to fixed delay when you need predictable retry timing instead of growing gaps.
View recipe →

Logging & observability

Ship structured logs to your own observability stack
logging({ format: "json" }) prints one JSON object per call instead of the pretty-printed default -- pipe it straight into your log aggregator.
View recipe →
Silence console output but keep local history
format: "silent" still writes every call to .klaro/logs.jsonl for klaro stats/explain -- it just doesn't print to stdout.
View recipe →

Streaming

Wrapping a streaming completion
klaro.wrap() awaits the promise your function returns -- for a stream, that means retries cover the initial request that opens the stream, not failures mid-stream.
View recipe →

The full pipeline

The production-grade default
All five middlewares composed in the recommended order -- this is the exact pipeline the README leads with.
View recipe →