Skip to main content

Prerequisites

Use Python 3.10 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 prediction=BENIGN and its score. When the effective mode is block, a malicious request raises FirewallBlockedException. Its result holds the full verdict. In shadow or warn mode the call returns the result instead, so route on result.prediction. Your deployment sets the mode unless the client or call sets mode. Outcome meanings and recommended actions are in the outcome taxonomy. SilmarilApiError means the API returned a non-2xx response after retries. Network failures raise the underlying requests exception. Neither is a verdict, so decide whether that boundary fails open or closed. LangChain and LangGraph handlers for this client are documented in Framework SDKs.

Caller-owned HTTP sessions

Starting with SDK 0.7.1, a supplied requests.Session keeps its default headers. The SDK attaches its API key to each Firewall request, so unrelated calls through that session do not inherit the key. Reuse a client for repeated classifications.

Governance context

Pass the agent and resource for a direct classification when policy depends on who is acting or which tool is used. A malicious prediction or an explicit governance block raises FirewallBlockedException in Block mode.
For classify_batch(), pass one optional governance context per input using governance=[context, None, ...]. Each item also keeps its own metadata, including metadata.conversationId. That value is carried with the item. The current batch classifier treats each input independently and neither reads nor updates conversation history for that batch. See Batch calls and conversation history. In Warn or Shadow mode, inspect result.prediction and, only when result.governance is not None, result.governance.action because the SDK returns the verdict instead of raising. Older backends may omit result.governance.

Batch calls and conversation history

classify_batch() 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": conversation_id} on each synchronous or asynchronous 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. In Block mode, FirewallBlockedException is the blocking error. In Warn or Shadow mode the call returns the verdict, which still requires that inspection. SilmarilApiError or a network failure means the 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.

Async classify

Install async support before using AsyncFirewall.
Share one AsyncFirewall across tasks on one event loop for the service lifetime and close it at shutdown. The gathered 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. Cancellation stops the calling task’s request. Async calls raise the same block exceptions as the synchronous client. For a synchronous off-thread fallback, create one Firewall per worker thread.

Shadow mode

Shadow mode returns results instead of raising block exceptions, so you can measure would-block decisions while traffic continues. Per-call overrides let one boundary enforce before you change the client default.
The last call passes shadow_mode=False, so that call enforces.

Errors

Direct calls raise FirewallBlockedException when a block is enforced. It carries score, threshold, and the full result.
Read exc.result for the verdict, or use shadow mode when you need the result without a block exception. Outcome meanings and recommended actions are in the outcome taxonomy.