Skip to main content

Prerequisites

Use Node.js 20 or later. Set SILMARIL_API_KEY and SILMARIL_API_URL from your deployment access.

Install

Classify your first request

Create one client per protected system and reuse it. Label each call with the boundary it checks.
For tool output, pass the tool name as well.

Expected result

A benign request logs BENIGN, its score, and allow. Direct classify calls return a result in every mode. They do not throw on a block. Treat the request as blocked when prediction is MALICIOUS or governance.action is block, then route it with firewall outcomes. A rejected promise means the call did not produce a verdict. That includes SilmarilApiError for a non-2xx API response, and a network, timeout, or abort error. With native fetch, a redirect refused by the SDK is a TypeError transport failure, not a SilmarilApiError; custom fetch implementations can differ. Decide whether that boundary fails open or closed. Vercel, LangChain, and LangGraph integrations that wrap this client are documented in Framework SDKs.

Concurrent requests

Reuse one client for concurrent calls in a JavaScript runtime when those calls are independent events or different conversations. Ordered events that share one metadata.conversationId wait for each classify() call before the next event is sent. Pass signal to classify or classifyBatch to cancel one request and its retry wait. Create a client in each worker thread.
request.signal is the caller’s AbortSignal. classifyBatch() cancels as one request. Its items stay independent of one another.

Batch calls and conversation history

Starting with SDK 0.7.1, a batch response must contain a predictions array with exactly one result per sent input. A missing array or mismatched count rejects the call with an Error; it is not a classification verdict. The SDK validates against the original request snapshot, including during retries. classifyBatch() preserves per-item metadata, including metadata.conversationId. The current batch classifier treats each input independently and neither reads nor updates conversation history for that batch. Giving items the same conversationId does not connect them into a sequence or attach them to previously cached history. For conversation-aware checks, send each complete event through an ordered classify() call with the same metadata.conversationId. Pass metadata: { conversationId } on each individual classify() call. Wait for each call to finish before sending the next event for that conversation. Concurrent calls are appropriate for independent events or different conversations. Keep every returned verdict, including a Warn or Shadow tool-output result, and inspect its prediction and optional governance action before the event is consumed or the next event for that conversation is sent. Direct classify() calls return a result in every mode. A rejected promise, including SilmarilApiError or a network error, means that call did not produce a verdict. Use the effective mode when routing a malicious prediction or explicit governance block: in Block mode, stop the event; in Warn mode, report the would-block finding and continue; in Shadow mode, record the would-block finding and continue. Inspecting a Warn or Shadow verdict does not mean enforcing it. See the outcome taxonomy for verdict categories.

Shadow mode

Shadow mode reports would-block decisions with the same thresholds while traffic continues. Framework adapters inherit the client setting and can override it when a surface is ready to enforce.

Errors

Framework adapters throw FirewallBlockedException when a malicious or governance-block decision is enforced. The exception carries score and threshold.
generateText and model come from the Vercel integration. Rethrow any error that is not a firewall block.