Prerequisites
Use Node.js 20 or later. SetSILMARIL_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.Expected result
A benign request logsBENIGN, 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 onemetadata.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 apredictions 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 throwFirewallBlockedException 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.