> ## Documentation Index
> Fetch the complete documentation index at: https://silmaril.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Java SDK

> Install the Java SDK, classify user input and tool output, and handle typed block exceptions.

## Prerequisites

Set `SILMARIL_API_KEY` and `SILMARIL_API_URL` from your [deployment access](/docs/start/quickstart#get-access).

## Install

Confirm Java package availability and repository configuration with Silmaril before adding this dependency.

```kotlin Gradle theme={"theme":"github-light-default"}
dependencies {
    implementation("com.silmaril.security:silmaril-security-sdk:0.5.0")
}
```

<a id="initialize" />

<a id="classify" />

## Classify your first request

Create one client per protected system and reuse it. Label each call with the boundary it checks.

```java theme={"theme":"github-light-default"}
import dev.silmaril.security.BlockResult;
import dev.silmaril.security.ClassifyOptions;
import dev.silmaril.security.Firewall;
import dev.silmaril.security.FirewallBlockedException;
import dev.silmaril.security.HookLabel;

public class FirstClassification {
    public static void main(String[] args) throws Exception {
        Firewall fw = Firewall.builder()
            .apiKey(System.getenv("SILMARIL_API_KEY"))
            .apiUrl(System.getenv("SILMARIL_API_URL"))
            .build();

        try {
            BlockResult result = fw.classify(
                "Summarize this release note.",
                ClassifyOptions.builder()
                    .hook(HookLabel.USER_INPUT)
                    .build()
            );
            System.out.println("prediction=" + result.prediction());
        } catch (FirewallBlockedException blocked) {
            System.err.println("block score=" + blocked.score() + " threshold=" + blocked.threshold());
        }
    }
}
```

For tool output, pass the tool name as well.

```java theme={"theme":"github-light-default"}
fw.classify(
    toolOutput,
    ClassifyOptions.builder()
        .hook(HookLabel.TOOL_RESPONSE)
        .toolName("read_file")
        .build()
);
```

### Expected result

A benign request prints `prediction=BENIGN`. In enforcement mode, a block throws `FirewallBlockedException`. Any other exception means the call did not produce a verdict. Decide whether that boundary fails open or closed. Outcome meanings and recommended actions are in the [outcome taxonomy](/docs/sdk/outcomes#outcome-taxonomy).

## Shadow mode

Shadow mode returns results instead of throwing block exceptions, so you can measure would-block decisions while traffic continues. Per-call options can enforce one boundary before you change the client default.

```java theme={"theme":"github-light-default"}
Firewall fw = Firewall.builder()
    .apiKey(System.getenv("SILMARIL_API_KEY"))
    .apiUrl(System.getenv("SILMARIL_API_URL"))
    .shadowMode(true)
    .onClassify(event -> {
        if (event.blocked() && event.shadowMode()) {
            System.err.println("would block " + event.hook() + " score=" + event.result().score());
        }
    })
    .build();

fw.classify(
    text,
    ClassifyOptions.builder()
        .hook(HookLabel.TOOL_RESPONSE)
        .shadowMode(false)
        .build()
);
```

The classify call passes `shadowMode(false)`, so that call enforces.

## Errors

Enforced blocks throw `FirewallBlockedException`, which exposes `score()` and `threshold()`.

```java theme={"theme":"github-light-default"}
try {
    fw.classify(userInput, options);
} catch (FirewallBlockedException blocked) {
    System.err.println("blocked score=" + blocked.score() + " threshold=" + blocked.threshold());
    return;
}
```

`options` is the `ClassifyOptions` value for that boundary. Outcome meanings and recommended actions are in the [outcome taxonomy](/docs/sdk/outcomes#outcome-taxonomy).
