Skip to content

Quickstart

Get meshulash-guard installed and running your first scan in under five minutes.

Installation

Install the SDK using pip. Python 3.10 or higher is required.

pip install meshulash-guard

You will need an API key and a tenant ID from your Meshulash dashboard. Every scan call authenticates with these credentials.


Your First Scan

The example below scans a message for PII — an email address and a phone number — and replaces them with safe placeholders before the text ever reaches your LLM or logs.

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

# Initialize the Guard with your credentials
guard = Guard(
    api_key="your-api-key",
    tenant_id="your-tenant-id",
)

# Configure a PII scanner: detect emails and phone numbers, replace them
pii = PIIScanner(
    labels=[PIILabel.EMAIL_ADDRESS, PIILabel.PHONE_NUMBER],
    action=Action.REPLACE,
)

# Scan the text
result = guard.scan_input(
    text="Contact me at sarah@company.com or call 555-0123",
    scanners=[pii],
)

print(result.status)          # "secured"
print(result.processed_text)  # "Contact me at [EMAIL_ADDRESS-A1B2] or call [PHONE_NUMBER-C3D4]"

Expected output:

secured
Contact me at [EMAIL_ADDRESS-A1B2] or call [PHONE_NUMBER-C3D4]

What each part does:

  • Guard — the main client. It holds your credentials and manages the placeholder vault used by the deanonymize workflow.
  • PIIScanner — tells the server what to detect (labels) and what to do when it finds it (action).
  • Action.REPLACE — detected text is swapped for [LABEL-HASH] placeholders. The result status becomes "secured".
  • guard.scan_input() — sends the text to the Meshulash security server and returns a ScanResult.

Understanding the Result

Every scan returns a ScanResult object with these key fields:

Field Type Description
status str "clean" — nothing detected. "secured" — PII replaced. "blocked" — content rejected.
processed_text str The text after actions were applied (may contain placeholders).
placeholders dict[str, str] Maps each placeholder back to the original value.
scanners dict[str, ScannerResult] Per-scanner breakdown of what triggered.
level int Severity score 0–5.

You can inspect the per-scanner breakdown to see exactly what was found:

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="Contact me at sarah@company.com or call 555-0123",
    scanners=[pii],
)

# Inspect the PII scanner result
scanner_result = list(result.scanners.values())[0]
print(scanner_result.triggered)   # True
print(scanner_result.score)       # e.g. 0.97

for detection in scanner_result.detections:
    print(detection.label, detection.text, detection.confidence)

Expected output:

True
0.97
EMAIL_ADDRESS sarah@company.com 0.99
PHONE_NUMBER 555-0123 0.95

See Concepts for a full field-by-field reference and a deep dive on Actions and Conditions.


Blocking Dangerous Content

When you want to reject harmful text outright — rather than redact it — use Action.BLOCK. The following example uses ToxicityScanner to block abusive messages:

from meshulash_guard import Guard, Action
from meshulash_guard.scanners import ToxicityScanner, ToxicityLabel

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

toxicity = ToxicityScanner(
    labels=[ToxicityLabel.TOXICITY, ToxicityLabel.HATE_SPEECH],
    action=Action.BLOCK,
)

result = guard.scan_input(
    text="You're an idiot and I hate everything about your service",
    scanners=[toxicity],
)

print(result.status)          # "blocked"
print(result.processed_text)  # original text, unchanged

Expected output:

blocked
You're an idiot and I hate everything about your service

With Action.BLOCK, meshulash-guard signals that the content should be rejected (status="blocked") and returns the original text unmodified. Your application decides what to do — show an error, log the attempt, or drop the message. Nothing is sent to your LLM.

Action.REPLACE (used in the PII example) redacts the specific detected spans in place, producing status="secured". See Concepts → Actions for a full comparison.


Next Steps