Skip to main content

Prerequisites

Use Go 1.22 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, and check each call’s error before making the next one.
In a service, pass the request context instead of context.Background(). For tool output, pass the tool name as well, and handle its error the same way.

Expected result

A benign request logs prediction=BENIGN and its score. When the effective mode is Block, a malicious request returns *firewall.FirewallBlockedError. Its Result field holds the full verdict. In Shadow or Warn mode the call returns the result instead, so route on result.Prediction. See confidence scores for score meaning and threshold behavior. A per-call mode option wins the client setting. Either local choice is sent with the request and preserved in result.Mode. Without a local override, current classify responses omit mode. result.Mode remains empty, and the SDK uses Block as its enforcement fallback. Choose Shadow or Warn explicitly on the client or call when that boundary should be observational. OnClassify callbacks inherit the same effective behavior. Outcome meanings and recommended actions are in the outcome taxonomy. Any other error means the call did not produce a verdict. That includes *firewall.APIError for a non-2xx API response, and a network, timeout, or context error. Decide whether that boundary fails open or closed. For agent governance, WithGovernance adds typed agent and resource context to one Classify call. WithBatchGovernance supplies one optional context per ClassifyBatch item. The SDK sends these fields under metadata.silmaril.governance. The server returns an optional BlockResult.Governance decision with action, policy version, and rule ID. An explicit governance block is enforced in Block mode even with a benign prediction. Older responses can omit the decision. ClassifyBatch preserves each item’s metadata, including metadata.conversationId. The current batch classifier treats each input independently and neither reads nor updates conversation history for that batch. See Batch calls and conversation history. Go uses direct classification calls and has no Deep Agents graph adapter.

Concurrent requests

Reuse one client across goroutines for independent events or different conversations. Ordered events that share one metadata.conversationId wait for each Classify call before the next event is sent. Each Classify or ClassifyBatch call takes a context, so canceling one call also stops its retry wait. Caller-owned metadata, callbacks, and custom transports must be safe for concurrent access.

Batch calls and conversation history

Pass firewall.WithMetadata(firewall.ClassificationMetadata{"conversationId": conversationID}) on each ordered Classify call. Wait for and handle its verdict or error before sending the next event. ClassifyBatch preserves per-item metadata and treats items independently of conversation history. See events and conversations for sequencing and modes and enforcement for returned verdicts in Warn and Shadow.

Classify in parallel

Protect runs your call while its input is classified instead of waiting for the verdict first. In effective Block mode it withholds your call’s result until the verdict arrives, and returns a blocking error for a would-block decision. In Shadow or Warn mode it returns your result immediately and the classification finishes in the background. Use Protect for calls whose effect can be discarded, such as a model call. Classify the arguments of a tool that writes with Classify before running it. Classifications that share one metadata.conversationId are sent in the order they started, so Protect keeps the conversation sequence without waiting between events.
callModel, safeResponse, prompt, and conversationID belong to your application. A block cancels the context passed to your call, and Protect returns the blocking error after your call returns, so pass that context to the model client. ProtectWithOutput takes one more function that extracts the generated text and classifies it as model output before the result is returned. Options.MaxConcurrent bounds classifications in flight and defaults to 32. Options.MaxQueued bounds background classifications waiting in one conversation and defaults to 64. Background classifications are also capped at MaxConcurrent times MaxQueued across all conversations, and one beyond either limit is skipped without a log entry, because the package has no logger. A background classification retries once. Metadata is copied when Protect starts; a value that cannot be encoded as JSON returns an error before your call runs. Call fw.Flush(ctx) to wait for background classifications, for example before a serverless handler returns.

Shadow mode

An explicit local Shadow mode returns results instead of blocking errors, so you can measure would-block decisions while traffic continues. Per-call options can enforce one boundary before you change the client setting.

Enforce one boundary

Handle err before consuming the event. This call overrides Shadow mode and enforces its verdict. OnClassify can run on overlapping calls for independent events or different conversations. Synchronize any shared state it touches. Ordered events in one conversation stay on the sequential Classify path above.

Errors

Enforced blocks return *firewall.FirewallBlockedError, which carries Score, Threshold, and Result.
Read blocked.Result for the verdict, or use shadow mode when you need the result without a blocking error. Outcome meanings and recommended actions are in the outcome taxonomy.

HTTP 408 handling

Go retries HTTP 408 by default, including the direct runtime request-body timeout before classification. Use the call context to cancel retries or bound them with a deadline. This timeout closes the connection and produces no verdict. It does not establish replay safety for model or tool operations.

Review depth

See review depth for minimum SDK versions and selection behavior. Use the public ReviewLevel constants ReviewStandard and ReviewDeep. Set Options.Review for an explicit client default, WithReview for one Classify call, or WithBatchReview for one ClassifyBatch call. Resolution is explicit per-call option, then explicit client default, then omission of the wire field. An empty client option omits review. An explicitly passed empty or invalid per-call value is an error, not a request to reset server authority.
Use ReviewStandard or ReviewDeep. An empty client setting omits review. An explicit empty per-call selection is invalid. Missing or mismatched backend acknowledgement produces ReviewCompatibilityError. See review depth for runtime requirements and response handling.

Next steps

Verify your integration, then review modes and enforcement.