Skip to content

Concepts

This page is the single reference for the core building blocks of meshulash-guard: how the SDK works under the hood, what Actions and Conditions do, the full ScanResult structure, and the exceptions the SDK raises. Scanner reference pages link here so these concepts are defined once.


How It Works

The meshulash-guard SDK is a client library that sends your text to a Meshulash security server for analysis. The server runs NER models, regex patterns, text classifiers, and validators — all the heavy computation happens server-side. The SDK translates your scanner configuration into a format the server understands, sends it over HTTPS, and returns structured results.

This means:

  • You need a running security server — Meshulash provides a hosted cloud server, or you can run the server on-premises.
  • Scan calls involve a network round-trip — plan for roughly 100–500ms latency depending on text length and scanner count.
  • An API key and tenant ID authenticate your requests — obtain these from the Meshulash dashboard.
  • The deanonymize step is the one exceptionguard.deanonymize() runs entirely client-side with no server call. See the Deanonymize workflow for details.

Actions

An Action tells the scanner what to do when it detects matching content. You set the action when constructing a scanner.

Action What Happens Result Status
Action.REPLACE Detected spans are replaced with [LABEL-HASH] placeholders in processed_text. The original values are stored in result.placeholders for later restoration via deanonymize(). "secured"
Action.BLOCK The original text is returned unchanged. No redaction occurs. The scan is marked as blocked. "blocked"
Action.LOG The original text is returned unchanged. Detection is recorded server-side for audit purposes. "clean"
from meshulash_guard import Guard, Action
from meshulash_guard.scanners import PIIScanner, PIILabel

guard = Guard(api_key="your-api-key", tenant_id="your-tenant-id")

# REPLACE: redact PII and continue processing
pii = PIIScanner(labels=[PIILabel.EMAIL_ADDRESS], action=Action.REPLACE)
result = guard.scan_input("Email me at alice@example.com", scanners=[pii])

print(result.status)          # "secured"
print(result.processed_text)  # "Email me at [EMAIL_ADDRESS-A1B2]"

# BLOCK: reject the text entirely
from meshulash_guard.scanners import ToxicityScanner, ToxicityLabel

toxicity = ToxicityScanner(labels=[ToxicityLabel.TOXICITY], action=Action.BLOCK)
result = guard.scan_input("You are completely useless", scanners=[toxicity])

print(result.status)          # "blocked"
print(result.processed_text)  # "You are completely useless"

Expected output:

secured
Email me at [EMAIL_ADDRESS-A1B2]
blocked
You are completely useless

Choosing an action:

  • Use Action.REPLACE when you want to continue processing but need PII removed (e.g., before sending to an LLM).
  • Use Action.BLOCK when the content should be rejected entirely (e.g., toxic prompts, jailbreak attempts).
  • Use Action.LOG when you want to track content without altering the flow (e.g., monitoring only).

Conditions

A Condition controls when the scanner fires its action. All conditions apply to the detections made by that scanner's labels.

Condition When It Triggers
Condition.ANY At least one detection from any of the configured labels. This is the default and covers most use cases.
Condition.ALL Every configured label must produce at least one detection.
Condition.K_OF The total number of detections across all labels must reach the configured threshold k.
Condition.CONTEXTUAL The text classifier (TC) head must trigger and at least one NER or regex detection must also be present. Useful for reducing false positives.

The most common condition is Condition.ANY — it fires as soon as any single label is detected. You rarely need to set it explicitly because it is the default.

from meshulash_guard import Guard, Action, Condition
from meshulash_guard.scanners import PIIScanner, PIILabel

guard = Guard(api_key="your-api-key", tenant_id="your-tenant-id")

# Only trigger if BOTH email AND phone number are present
pii = PIIScanner(
    labels=[PIILabel.EMAIL_ADDRESS, PIILabel.PHONE_NUMBER],
    action=Action.REPLACE,
    condition=Condition.ALL,
)

result = guard.scan_input(
    text="Call me at 555-0123",  # Only phone, no email
    scanners=[pii],
)

print(result.status)  # "clean" — Condition.ALL not met (no email detected)

Expected output:

clean

ScanResult

Every call to guard.scan_input() or guard.scan_output() returns a ScanResult object.

Top-level fields

Field Type Description
status str Overall outcome: "clean" (nothing triggered), "secured" (content redacted), or "blocked" (content rejected).
processed_text str The text after all actions have been applied. For Action.REPLACE, this contains placeholders. For Action.BLOCK and Action.LOG, this is the original text.
placeholders dict[str, str] Maps placeholder tokens to the original detected values. Example: {"[EMAIL_ADDRESS-A1B2]": "alice@example.com"}. Empty if no replacements were made.
level int Severity of the highest-risk detection, from 0 (none) to 5 (critical).
scanners dict[str, ScannerResult] Per-scanner breakdown keyed by internal scanner ID. Iterate .values() to inspect each scanner.
risk_categories list[str] High-level risk categories that triggered, e.g. ["PII", "SECRETS"].

ScannerResult fields

Each value in result.scanners is a ScannerResult:

Field Type Description
triggered bool Whether this scanner's condition was met and its action fired.
score float Overall confidence score for this scanner's detections (0.0–1.0).
detections list[Detection] Individual spans detected by this scanner.

Detection fields

Each item in scanner_result.detections is a Detection:

Field Type Description
label str The label that matched, e.g. "EMAIL_ADDRESS".
text str The exact text that was detected.
start int Start character offset in the original text.
end int End character offset (exclusive).
confidence float Detection confidence (0.0–1.0).
action Action The action applied to this specific detection.
from meshulash_guard import Guard, Action
from meshulash_guard.scanners import PIIScanner, PIILabel

guard = Guard(api_key="your-api-key", tenant_id="your-tenant-id")
pii = PIIScanner(labels=[PIILabel.EMAIL_ADDRESS, PIILabel.PHONE_NUMBER], action=Action.REPLACE)

result = guard.scan_input(
    text="Reach me at bob@example.com or 555-9876",
    scanners=[pii],
)

print(result.status)           # "secured"
print(result.risk_categories)  # ["PII"]

for scanner_result in result.scanners.values():
    for d in scanner_result.detections:
        print(f"{d.label}: '{d.text}' at [{d.start}:{d.end}] confidence={d.confidence:.2f}")

Expected output:

secured
['PII']
EMAIL_ADDRESS: 'bob@example.com' at [12:27] confidence=0.99
PHONE_NUMBER: '555-9876' at [31:39] confidence=0.96

Exceptions

meshulash-guard uses a structured exception hierarchy so you can handle specific failure modes precisely.

Exception When Raised
MeshulashError Base class for all SDK exceptions. Catch this to handle any SDK error.
AuthError API key is invalid, expired, or missing. Check your credentials.
ServerError The Meshulash server returned a 5xx response. Has a .status_code attribute.
ConnectionError The SDK could not reach the server (DNS failure, timeout, network unreachable).
ValidationError The request payload failed server-side validation. Usually indicates a misconfigured scanner.
from meshulash_guard import Guard, Action, MeshulashError, AuthError, ServerError, ConnectionError, ValidationError
from meshulash_guard.scanners import PIIScanner, PIILabel

guard = Guard(api_key="your-api-key", tenant_id="your-tenant-id")
pii = PIIScanner(labels=[PIILabel.EMAIL_ADDRESS], action=Action.REPLACE)

try:
    result = guard.scan_input("Contact alice@example.com", scanners=[pii])
    print(result.status)

except AuthError:
    print("Invalid or expired API key — check your credentials")

except ServerError as e:
    print(f"Server error {e.status_code} — retry or contact support")

except ConnectionError:
    print("Could not reach the Meshulash server — check your network")

except ValidationError as e:
    print(f"Bad request — check scanner configuration: {e}")

except MeshulashError as e:
    print(f"Unexpected SDK error: {e}")

Expected output (when credentials are valid):

secured