Every log event SAW processes ends with one of three decisions: EXECUTE (apply mitigations automatically), OBSERVE (create an analyst task for human review), or IGNORE (log and discard). The boundary between these outcomes is controlled by two environment variables —Documentation Index
Fetch the complete documentation index at: https://mintlify.com/samkit511/SAW---Security-Analyst-Workspace/llms.txt
Use this file to discover all available pages before exploring further.
ASA_EXECUTE_THRESHOLD and ASA_OBSERVE_THRESHOLD — which act as cutpoints on a continuous risk score. Understanding how that score is computed lets you calibrate the decision engine precisely for your threat environment.
The risk score formula
The base risk score is the product of two factors:confidence is a float in [0.0, 1.0] representing the system’s certainty about the classification. After raw detection, confidence values are snapped to one of four named buckets:
| Bucket | Calibrated value | Typical source |
|---|---|---|
VERY_HIGH | 0.90 | Heuristic match with raw confidence ≥ 0.9 |
HIGH | 0.78 | Heuristic match with raw confidence < 0.9, or LLM with raw ≥ 0.8 |
MEDIUM | 0.58 | LLM with raw confidence 0.55–0.79 |
LOW | 0.35 | LLM with raw confidence < 0.55, or any fallback path |
severity_weight converts the categorical severity label to a numeric multiplier:
| Severity | Weight |
|---|---|
LOW | 1 |
MEDIUM | 2 |
HIGH | 3 |
0.9 × 3 = 2.7, which occurs for a VERY_HIGH confidence, HIGH severity classification (a confident heuristic hit on SQL Injection, XSS, or Path Traversal).
The decision engine logic
The decision engine inapp/tools/decision_engine.py applies the following logic in order:
base_risk— the rawconfidence × severity_weightscore from the detection pipeline.behavior_adjustment— adds0.5to the risk score when the classificationbehaviorfield is"Aggressive Attacker". The RiskAgent sets this when escalation is active (burst or sustained attack pattern detected). This means an escalated event with a base risk score as low as 2.0 can still reach the EXECUTE threshold.escalated— a boolean passed by the RiskAgent whenevaluate_escalationreturnsstatus: true. IfescalatedisTrue, the decision is immediately EXECUTE regardless of the numeric risk score.
Default thresholds and score examples
With defaults (ASA_EXECUTE_THRESHOLD=2.5, ASA_OBSERVE_THRESHOLD=1.5):
Scores that reach EXECUTE
Scores that reach EXECUTE
| Scenario | Confidence | Severity | Base risk | Adjustment | Final risk | Decision |
|---|---|---|---|---|---|---|
| SQL Injection (heuristic) | VERY_HIGH (0.90) | HIGH | 2.70 | 0.0 | 2.70 | EXECUTE |
| XSS (heuristic) | VERY_HIGH (0.90) | HIGH | 2.70 | 0.0 | 2.70 | EXECUTE |
| Any threat, escalation active | any | any | any | +0.5 | ≥ 3.0 | EXECUTE |
| Any escalated event | — | — | — | — | — | EXECUTE (forced) |
Scores that reach OBSERVE
Scores that reach OBSERVE
| Scenario | Confidence | Severity | Base risk | Decision |
|---|---|---|---|---|
| SQL Injection (LLM, high confidence) | HIGH (0.78) | HIGH | 2.34 | OBSERVE |
| XSS (LLM, high confidence) | HIGH (0.78) | HIGH | 2.34 | OBSERVE |
| Any HIGH severity, MEDIUM confidence LLM | MEDIUM (0.58) | HIGH | 1.74 | OBSERVE |
| MEDIUM severity, HIGH confidence LLM | HIGH (0.78) | MEDIUM | 1.56 | OBSERVE |
Scores that reach IGNORE
Scores that reach IGNORE
| Scenario | Confidence | Severity | Base risk | Decision |
|---|---|---|---|---|
| Brute Force (heuristic) | HIGH (0.78) | MEDIUM | 1.56 | OBSERVE* |
| LOW severity, any confidence | LOW–VERY_HIGH (0.35–0.90) | LOW | 0.35–0.90 | IGNORE |
| Unknown / fallback | LOW (0.35) | LOW | 0.35 | IGNORE |
| SAFE mode event | 0.0 | LOW | 0.0 | IGNORE |
ASA_OBSERVE_THRESHOLD to 1.6 to push isolated brute-force events to IGNORE.Events in IGNORE are persisted to the incident store and appear in the /latest and /tasks responses, but no blocking actions or follow-up tasks are created.Behavior adjustment: Aggressive Attacker
WhenASA_ENABLE_ESCALATION=true and the RiskAgent detects a burst or sustained attack pattern, it sets behavior: "Aggressive Attacker" on the classification. The decision engine then adds 0.5 to the computed risk score before comparing against thresholds:
0.58 × 2 = 1.16 (IGNORE) reaches 1.66 (OBSERVE) once the attacker profile is established. Combined with the escalated=True flag that also fires in the same code path, the practical effect is that any IP identified as an aggressive attacker produces an EXECUTE decision on the next event regardless of that event’s individual classification.
Tuning for your environment
Different deployment contexts call for different threshold positions:Strict SOC: minimize missed threats
Strict SOC: minimize missed threats
Lower At these settings, any LLM HIGH-confidence detection of a HIGH-severity threat (
ASA_OBSERVE_THRESHOLD to catch more borderline events. Lower ASA_EXECUTE_THRESHOLD to automate mitigations for a wider range of confirmed threats.0.78 × 3 = 2.34) reaches EXECUTE. MEDIUM-severity events at MEDIUM confidence (0.58 × 2 = 1.16) are now flagged for OBSERVE instead of IGNORE.Monitoring-only: reduce alert noise
Monitoring-only: reduce alert noise
Raise At these settings, only VERY_HIGH confidence / HIGH severity events (score 2.70) reach EXECUTE. Everything else is either OBSERVE (score 2.0–2.59) or IGNORE (below 2.0). This reduces automated blocking actions while preserving visibility.
ASA_OBSERVE_THRESHOLD to reduce the volume of analyst tasks created for low-confidence detections. Set ASA_EXECUTE_THRESHOLD high enough that automated mitigations only fire on definitive heuristic hits.SAFE mode: no automated decisions
SAFE mode: no automated decisions
Set No event can score above 3.0, so EXECUTE is unreachable. All detected threats produce OBSERVE (analyst tasks) and IGNORE only.
ASA_MODE=SAFE to disable LLM calls entirely. Combined with the default thresholds, heuristic-matched HIGH-severity events still reach EXECUTE. If you want no automated mitigations at all in SAFE mode, raise ASA_EXECUTE_THRESHOLD above the maximum possible score:Checking the active thresholds
The current threshold values are embedded in every triage response underagent_results.RiskAgent.output.decision.decision_thresholds: