Impraint

Content safety

Detect and mask PII and unsafe content.

Content safety scans the text going into and out of your agent, detects personally identifiable information (PII), secrets and prompt injection, and masks sensitive values before they are stored.

Report by default

By default Guard only reports findings to the dashboard. Text is hidden only if you ask for redact, and a call is stopped only if you ask for block. You are never surprised by a stopped agent.

What it finds

KindExampleDefault handling
Prompt injection"Ignore your previous instructions", also in Hindi and HinglishReported. Stops a call only in block mode.
Cross-prompt injectionA hidden instruction planted in a web page, document or tool resultReported. Stops a call only in block mode.
SecretsAWS keys, GitHub tokens, JWTs, private-key blocks, passwords next to a key nameMasked before storage
Personal data (PII)Aadhaar, PAN, phone numbers, UPI IDs, card numbers, emailMasked before storage

PII detection is built as country packs, and India is covered first: Aadhaar, PAN, GSTIN, IFSC, UPI ID, bank account, passport, voter ID, driving licence, vehicle registration, PIN code, UAN and ABHA. Two packs exist today, india and us. An organisation with no country chosen defaults to India.

To keep false alarms low, weak formats such as a bare 10-digit number are reported only next to a context word like "phone". Card numbers must pass the Luhn check and Aadhaar must pass the Verhoeff check. Digits written in Devanagari and other scripts are read as normal digits, and obvious placeholder values are ignored.

What is stored

  • Raw personal data is never stored. Every finding is saved with the value already masked.
  • Secrets in a trace are masked before the trace is written, so a raw key never reaches storage.
  • The dashboard shows the masked text, the pattern, the severity, whether it was in the input or the output, and the trace it came from.

Check text yourself

Two methods on Guard check any text directly.

incidents = guard.check_content(user_message, direction="input")
if any(i["severity"] in ("high", "critical") for i in incidents):
    return {"error": "This message could not be processed."}

check_content reports findings and never changes the text. direction is "input" for text going into the model and "output" for text coming out.

result = guard.redact_content(user_message, direction="input")
reply = llm.generate(result.text)  # never the original
if not result.complete:
    ...  # masked locally, or too many values: take care

redact_content returns text with every secret and PII value hidden.

FieldMeaning
textThe safe text
completeFalse means it was not fully checked. Do not treat it as certified clean.
incidentsThe findings
source"server", or "local" if Guard could not be reached

If Guard is unreachable, the SDK masks with its own local rules. That hides secrets and PII but cannot see prompt injection. These methods never raise on a network problem and never return the original text as if it were redacted.

Tools: arguments and results

@guard.tool checks both what goes into a tool and what comes back.

from impraint_guard.core.tool import ImpraintGuardUnsafeResult

@guard.tool(on_sensitive="redact", on_result="block")
def fetch_page(url: str) -> str:
    return requests.get(url).text

try:
    page = fetch_page("https://example.com/offer")
except ImpraintGuardUnsafeResult as e:
    print(e.categories)  # for example ['cross_prompt_injection']
ModeWhat happens
offNothing is checked
report (default)Checked in the background, so the agent never waits. Findings go to the dashboard.
redactChecked first. The agent gets a copy with secrets and PII hidden.
blockChecked first. The agent gets an exception instead of the unsafe value.
  • on_sensitive covers the arguments. A value under a key named like a secret (password, token, Authorization) is hidden by name.
  • on_result covers what the tool returns. In block mode, a result containing customer data is stopped too, so use redact for tools that return customer data on purpose.
  • Exceptions carry paths and categories, never the values.

Text going into the model

Prompt injection is most dangerous on the way in: a web page, document or tool result carries a hidden instruction into the next model call. Input screening is already on in report mode. Choose how it behaves with on_input:

from impraint_guard.integrations.gemini import patch_gemini

patch_gemini(guard, on_input="block")   # whole process
# or: guard.wrap_gemini(client, on_input="block")
# or: ImpraintGuardCallbackHandler(guard, on_input="block")
ModeWhat happens
report (default)Checked in the background. The call is never delayed.
blockChecked first. High or critical prompt injection, or any hidden instruction planted in content, raises ImpraintGuardUnsafeInput.
offNothing is checked
  • With fail_open=False, a call is also stopped when Guard cannot be reached.
  • A secret or PII value in the user's own message does not stop the call in block mode. Use redact_content on it first.
  • Not read: your system prompt, the model's earlier replies, and images, audio or files. Retrieved documents are checked where they enter your agent.
  • The same text is not checked twice within a trace, so resent chat history adds no extra requests.
  • At most 200 text values and 100,000 characters are checked per call.

Known limits in beta

  • Detection is a pattern library. It catches known wordings well and unknown wordings poorly. Names and street addresses in free text are not detected yet.
  • Only india and us country packs exist.
  • Input screening and the options above are supported for Gemini, LangChain and LangGraph. Anthropic and OpenAI come after beta.
  • Custom rules, the allowlist and the country choice are changed by admins through the API. The dashboard has no screens for them yet.
  • Secrets and PII found in a tool result are hidden, blocked or logged, but not yet saved as dashboard incidents.

On this page