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.


Normalizing Text Before Scanning

Normalizers pre-process text to defeat evasion techniques before scanning. For example, Unicode tricks and invisible characters that would bypass PII detection are neutralized first.

from meshulash_guard import Guard, Action
from meshulash_guard import InvisibleTextNormalizer, UnicodeNormalizer
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)

result = guard.scan_input(
    text="Contact me at s\u200barah@company.com",  # zero-width space injected
    scanners=[pii],
    normalizers=[InvisibleTextNormalizer(), UnicodeNormalizer()],
)

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

Expected output:

secured
Contact me at [EMAIL_ADDRESS-A1B2]

The invisible character is stripped, the scanner sees clean text, and the email address is detected and replaced. You can also pass normalizers="all" to apply all 8 normalizers in one go.

See Normalizers for the full reference, individual normalizer details, and the auto_order option.


Scanning Files

Extract text from files and scan it in two lines — no parsing libraries needed in your application.

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)

parsed_text = guard.file_parser.parse("report.pdf")
result = guard.scan_input(parsed_text, scanners=[pii])

print(result.status)          # "secured" if PII found
print(result.processed_text)  # text with PII replaced

Expected output:

secured
Report prepared by [EMAIL_ADDRESS-A1B2]. For inquiries call [PHONE_NUMBER-C3D4].

guard.file_parser.parse() supports PDF, TXT, CSV, JSON, and DOCX files. All parsing runs server-side — no dependencies needed in your app.

See File Parsing for supported formats, error handling, and size limits.


Next Steps