Skip to content

Configuration reference

Every knob that changes gateway behavior, in one place. For the full method signatures see the generated Python API and Rust API; for concepts see Architecture and Layered scanning.

Constructor options

Set at gateway construction:

Option Type Meaning Rust
categories list of category names Which categories to scan. constructor
max_level "l1" | "l2" | "l3" Hard ceiling on escalation (default "l2"). constructor
download_files bool Whether missing assets may be downloaded on warmup. constructor
download_categories list Restrict automatic downloads to these categories. constructor
model_dir path Custom asset cache location (default: platform cache dir). constructor
cache_storage_location path or None Explicit persistent cache database; None keeps the cache memory-only. cache constructor
cache_encryption_key_hex 64 hex chars or None Encrypt persistent cache values and keyed similarity bucket indexes. PersistentCacheConfig.encryption
cache_entry_ttl_seconds positive integer Shared hot/persistent TTL; defaults to 30 days (2_592_000). ExactCacheConfig.entry_ttl
cache_memory_max_entries non-negative integer Per-hot-tier entry bound; 0 disables hot retention. ExactCacheConfig.memory.max_entries
cache_memory_max_bytes non-negative integer Per-hot-tier byte bound; 0 disables hot retention. ExactCacheConfig.memory.max_bytes
l3_strategy "dedicated" | "multi" One model per category, or one coalesced multi-head model. setter
execution_gates dict / matrix Initial execution gates. setter
dynamic_pii_config dict Configuration for the dynamic-pii pipeline. setter
execution_backend str ONNX execution backend (default "auto"). setter
onnx_batch_mode str ONNX batch mode; default "backend_default" follows whatever the backend implies. setter
ntdb_operating_point str Initial final-decision threshold profile, default "best_f1". setter

In Python, all of these are keyword arguments to SecurityGateway(...). In Rust the constructor-marked options are positional: with_max_level(categories, max_level, model_dir, download_files) takes four arguments (it always downloads for every configured category), and with_download_categories(...) adds the fifth, download_categories. Every other option is applied after construction with its setter (set_l3_strategy, set_execution_gates, set_dynamic_pii_config, set_execution_backend, set_onnx_runtime_options, set_onnx_batch_mode). Rust persistent caching uses try_with_download_categories_and_cache(...) with ExactCacheConfig; the path is fixed for the gateway lifecycle and cannot be overridden per request.

Python persistent writes are asynchronous. Call flush_cache() when shutdown or a durability boundary must wait for all queued writes. See Configure and understand caching for storage variants, cache-hit behavior, Dynamic PII events, metadata, and measured latencies.

Runtime setters

Change behavior on a live gateway (Python names; Rust has equivalents):

Setter Values Effect
set_execution_gates(dict \| None) see below Enable/disable levels and detectors; None resets to all-enabled.
set_l3_strategy(str) dedicated, multi Switch the L3 strategy.
set_ntdb_operating_point(str) see below Pick the final-decision threshold profile.
set_onnx_batch_mode(str) lazy_batches, tensor_batch How L3 fallback batches execute.
set_execution_backend(str) see below ONNX execution provider.
set_onnx_runtime_options(...) constrained CPU Configure ONNX Runtime intra/inter threads and spin-wait behavior.
set_dynamic_pii_config(dict) see dynamic PII Reconfigure the GLiNER pipeline.

Levels

Value Layers used
l1 Native L1 only.
l2 L1 + L2 (NTDB), when assets are cached.
l3 L1 + L2 + L3 (transformer, on promotion), when assets are cached.

max_level is a ceiling; execution gates can disable levels below it per request.

Execution gates

Gates decide which levels and which model/native scanners are active for subsequent scans. Unspecified gates stay enabled; max_level remains the hard upper bound.

scanner.set_execution_gates({
    "levels": {"l1": True, "l2": False, "l3": False},
    "models": {"native:mcp_runtime_risk": False, "external:internal_token": False},
})
  • levels — per-level on/off (l1, l2, l3).
  • models — per-detector on/off, keyed by public model name: native:<name> for native detectors, external:<id> for external L1 detectors.
  • conditional — conditional gates (see below).
  • l3 — optional worker policy (see below).

Per-request gates passed to enqueue() are snapshotted at enqueue time and do not change the gateway defaults. In Rust, build a ScanGateMatrix:

scanner.set_execution_gates(
    ScanGateMatrix::levels(true, false, false)
        .with_model("native:mcp_runtime_risk", false),
);

L3 worker policy

The optional execution_gates.l3 policy tunes the shared L3 worker. Initial costs are bootstrap values; the worker updates them with an EWMA of observed execution time.

execution_gates = {
    "l3": {
        "enabled": True,                # master switch for the L3 worker policy
        "priority": ["injection", "dynamic-pii"],
        "estimated_cost_ms": {"injection": 200, "dynamic-pii": 240},
        "fairness_quantum_ms": 50,
        "max_wait_ms": 2_000,
        "degraded_factor": 0.75,        # confidence multiplier applied to degraded fallbacks
        "ttl_ms": {"injection": 15_000, "dynamic-pii": 12_000},
        # Request-wide defaults:
        "execution": "rank_only",
        "early_exit": "class_stable",   # request-wide master switch: "disabled" | "class_stable"
        "progress": "disabled",         # "disabled" | "progress" | "provisional" (both dedicated-only)
        "representatives_per_cluster": 1,
        "verify_representatives_per_cluster": 1,
        "min_cluster_similarity": 0.90,
        "max_cluster_size": 8,
        # Category/model-specific overrides:
        "pipelines": {
            "injection": {
                "execution": "representative",
                "representatives_per_cluster": 1,
                "min_cluster_similarity": 0.96,
                "aggregation": {
                    "type": "any_positive_or_highest",
                    "positive_class": "attack",
                    "threshold": 0.93,
                },
                "early_exit": "request_wide_positive",
            },
            "tool_class": {
                "execution": "verify_representative",
                "verify_representatives_per_cluster": 1,
                "aggregation": {"type": "majority_vote_or_highest"},
                "early_exit": "head_stable",
            },
        },
    }
}

execution accepts disabled, rank_only, representative, and verify_representative; clustering remains a compatible alias. Pipeline overrides are resolved by category first and model name second. They are part of the enqueue-time gate snapshot, so two requests on the same gateway can use different policies.

representative first infers the configured number of highest-priority members from every cluster in global L2-priority order, then propagates each aggregated representative decision to the remaining cluster. verify_representative runs a second global wave containing the configured number of least-similar members. A class mismatch opens only that cluster and schedules its remaining members in global priority order. rank_only never propagates.

aggregation.type selects how the per-chunk L3 outputs combine into the category verdict: any_positive_or_highest (fields positive_class, threshold), highest_risk_above_threshold_or_confidence (field threshold), or majority_vote_or_highest. When omitted it defaults per pipeline — any_positive_or_highest for injection, majority_vote_or_highest for routing/tool_class/tool_action/sensitive_document, and highest_risk_above_threshold_or_confidence (threshold 0.93) for every other pipeline.

There are two early_exit fields with different value sets. The request-wide execution_gates.l3.early_exit (shown in the defaults block above) is the master switch — disabled or class_stable (default class_stable); it turns early exit on or off and resolves each pipeline's default scope. The per-pipeline early_exit inside pipelines.<name> overrides that pipeline's scope explicitly:

  • disabled: do not stop from a stable head decision.
  • head_stable: stop only the current head when its result can no longer change.
  • request_wide_positive: a thresholded positive result stops lower-priority heads for the request. This is the default behavior for Injection and Threat.

Independently of the per-pipeline early_exit scope above, a fixed cross-pipeline guard cancels the rest of a request's queued (or coalesced) L3 jobs once any Injection or Threat result crosses 0.93 confidence on a non-safe class. That threshold is not configurable.

progress controls streaming status while L3 resolves: disabled (default), progress (non-terminal progress events carrying chunk counters), or provisional (also emits interim provisional result previews). It takes effect only under l3_strategy="dedicated" — the unified multi strategy never emits progress or provisional events. See Result schema for the event shapes.

Dedicated and unified L3 use the same cluster planner, representative/verify state machine, aggregation rules, and early-exit state. Unified keeps the full output of every physical chunk and reuses it when a later head requests the same chunk.

Runnable examples:

  • rust/examples/08_l3_pipeline_policies.rs
  • python/examples/08_l3_pipeline_policies.py

Conditional gates

Beyond flat on/off gates, conditional gates suppress L2 or L3 work for a pipeline unless a predicate holds. The predicate (when) is evaluated against caller-supplied request metadata (arbitrary JSON passed to enqueue) and the results of pipelines that already ran earlier in the same request. This lets you, for example, run the expensive dynamic-pii L3 pass only when injection flagged the text.

scanner.set_execution_gates({
    "conditional": [
        {
            "level": "l3",
            "pipeline": "dynamic-pii",
            "when": {"result": {"pipeline": "injection", "classes": ["attack"], "min_confidence": 0.8}},
        }
    ]
})

An L3 conditional may instead carry l3_policy. When its predicate matches, the specified execution, clustering, aggregation, and early-exit fields override that pipeline's request-local policy. A policy conditional does not suppress the pipeline when its predicate does not match:

scanner.set_execution_gates({
    "conditional": [{
        "level": "l3",
        "pipeline": "injection",
        "when": {
            "result": {
                "pipeline": "routing",
                "classes": ["code_development_request"],
                "min_confidence": 0.8,
            }
        },
        "l3_policy": {
            "execution": "representative",
            "representatives_per_cluster": 1,
            "min_cluster_similarity": 0.96,
            "early_exit": "disabled",
        },
    }]
})

Predicate forms: all / any / not (combinators), metadata ({path, equals|in|exists}), and result ({pipeline, classes, min_confidence}). A runnable example is rust/examples/07_contextual_gates.rs.

L3 strategy

Value Behavior
dedicated (default) One transformer per category (Wolf Defender, Orca Sonar, Husky, …). Best per-category tuning.
multi One coalesced multi-head model (Lion Warden) serves several categories per inference. Best throughput when several model-backed categories are active.

See Models & the NTDB format.

NTDB operating point

Selects the precomputed final-decision threshold profile used after L2/L3 scoring. The profile controls the L2 acceptance threshold, L3 acceptance threshold, and L2/L3 union threshold/weights for supported classifier pipelines. It does not change the L2 promote-router threshold; L3 promotion still uses the package's promote operating point. When no candidate is accepted, the pipeline returns its default class and preserves the model's default-class confidence when one is available.

Value Optimizes
best_f1 (default) Balanced final-decision F1.
best_promote Uses the bundled final-decision profile named best_promote; promotion itself remains separate.
best_fpr_in_f1 Low false-positive rate within an F1 band.
best_fnr_in_f1 Low false-negative rate within an F1 band.
best_latency_in_f1 Lowest latency within an F1 band.

For queued scans, Python callers can override the profile per request with enqueue(..., ntdb_operating_point="best_fpr_in_f1").

Execution backend

ONNX execution provider for L3 (and model-backed L2 where applicable):

auto · cpu · gpu · coreml · cuda · directml · tensorrt

auto selects a provider based on the platform; cpu is the portable default. Availability of GPU providers depends on the ONNX Runtime build.

Setting the backend also resets onnx_batch_mode: auto/cpulazy_batches, and the GPU providers (gpu/coreml/cuda/directml/tensorrt) → tensor_batch. If you need a non-default batch mode, call set_onnx_batch_mode(...) after set_execution_backend(...).

ONNX batch mode

Value Behavior
lazy_batches Execute L3 fallback texts as they arrive.
tensor_batch Coalesce L3 fallback texts into one ONNX tensor batch where possible.

Dynamic PII

The dynamic-pii pipeline is configured with a dict (constructor dynamic_pii_config or set_dynamic_pii_config):

dynamic_pii_config = {
    "labels": ["organization", "location", "date"],
    "threshold": 0.5,
    "label_thresholds": {"organization": 0.6},
    "execution_gate": {
        "type": "if_result_in",
        "pipeline": "injection",
        "results": ["attack", "instruction_override"],
    },
    "conditional_labels": [
        {"labels": ["account identifier"],
         "when": {"pipeline": "injection", "results": ["attack"]}},
    ],
    "chunk_size_words": 256,
    "chunk_overlap_words": 32,
    "max_text_bytes": 1_048_576,
    "timeout_ms": 5_000,
    "queue_timeout_ms": 5_000,
    "timeout_per_chunk_ms": 500,
    "max_timeout_ms": 120_000,
}
Key Meaning
labels GLiNER entity labels to extract.
threshold / label_thresholds Global and per-label score thresholds.
execution_gate When the pipeline runs (always, if_result_in, if_no_result).
conditional_labels Extra labels enabled only when a source pipeline returns given results.
chunk_size_words / chunk_overlap_words Windowing for long text.
max_text_bytes Hard input size limit.
timeout_ms Minimum inference timeout for the pipeline.
queue_timeout_ms Maximum wait after the L2 gate resolves and before inference starts.
timeout_per_chunk_ms Inference budget contributed by each planned chunk.
max_timeout_ms Upper bound for the adaptive inference timeout.

Only labels with measured exact-span F1 ≥ 0.6 are mapped; deterministic identifiers (email, IP, IBAN, SWIFT/BIC, phone, card) stay native L1 heuristics. See gliner_category_map.py.

The first detected Dynamic PII entity—whether from the persistent entity cache or fresh inference—is emitted immediately as a partial result queue event. It contains details.partial_result = true and one evidence span. The authoritative complete result follows after the remaining chunks finish.

Environment variables

Variable Default Purpose
HF_TOKEN Authenticated / rate-limited Hugging Face access for asset downloads. Falls back to HUGGINGFACE_HUB_TOKEN, then HUGGING_FACE_HUB_TOKEN, then the cached huggingface-cli login token file.
HF_HOME HF default Hugging Face cache location.
PATRONUS_DOWNLOAD_OPTIONAL_ASSETS unset 1 also downloads non-required asset files (currently tokenizer_config.json for the legacy L3 manifest).
PATRONUS_L3_TTL_SECS 300 Idle seconds before an L3 session is evicted.
PATRONUS_L3_TRACE_CHUNKS unset 1 logs per-chunk L3 execution traces (diagnostic).
PATRONUS_NTDB_INJECTION_DIR Local NTDB override for injection.
PATRONUS_NTDB_ROUTING_DIR Local NTDB override for routing.
PATRONUS_NTDB_SENSITIVE_DOCUMENTS_DIR Local NTDB override for sensitive_document.
PATRONUS_NTDB_THREAT_DIR Local NTDB override for threat.
PATRONUS_NTDB_TOOL_CLASS_DIR Local NTDB override for tool_class.
PATRONUS_NTDB_TOOL_ACTION_DIR Local NTDB override for tool_action.
PATRONUS_NTDB_TOOL_TAGS_DIR Local NTDB override for tool_tags.

Local NTDB override directories are treated as canonical and are never rewritten by the asset manager. (PATRONUS_TEST_* variables exist for the test suite only and are not part of the public runtime configuration.)