Documentation
Everything you need to integrate Reglint's Layer 2 Agent Monitor into your AI pipeline, and how employees and admins use the Chrome Extension and Command Center.
We measured the deployed engine on 305 Arabic test cases across the four major dialects (MSA, Gulf, Egyptian, Levantine) and all 24 base categories of the engine's 29-category taxonomy, balanced with 50 hard negatives. Every number comes straight from the run — no rounding up, no cherry-picking. The 5 extended categories (AML_STRUCTURING, KYC_BYPASS, UNAUTHORIZED_FINANCIAL_ACTION, UNAUTHORIZED_DISCLOSURE, UNSOLICITED_MARKETING) are detected by the engine but not yet stratified in this benchmark — coming in the next revision.
205 violations caught, 0 missed, 1 false positive of 95 clean cases (a masked card with Eastern-Arabic digits). Single full-mode run on the deployed engine.
Full methodology, per-category and per-dialect tables, and honest limitations →Getting Started
Get your API key and send your first compliance scan in minutes.
Get your API Key
Send your first request
const response = await fetch(
'https://reglint.ai/api/monitor/scan',
{
method: 'POST',
headers: {
'x-api-key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
agent_output: "Your agent's response here",
agent_name: "my-agent",
industry: "healthcare",
mode: "fast"
})
}
);
const result = await response.json();
if (!result.safe_to_deliver) {
return "Request blocked due to compliance violation.";
}
return result.redacted_output || result.original_output;Step 3 — Handle the response
The monitor returns a structured JSON object with the decision and all violations found:
{
"scan_id": "uuid",
"final_decision": "BLOCK | REDACT | ALERT | PASS",
"safe_to_deliver": false,
"violations_count": 1,
"violations": [
{
"violation_id": "SSN_EXPOSURE",
"law": "HIPAA § 164.514",
"description": "SSN detected in agent output",
"violating_text": "123-45-6789",
"action": "BLOCK",
"severity": "critical",
"fine_range": "up to $50,000 per violation"
}
],
"original_output": "Your SSN is 123-45-6789...",
"redacted_output": "Your SSN is [REDACTED: SSN_EXPOSURE]...",
"processing_time_ms": 340
}Monitor Endpoint
https://reglint.ai/api/monitor/scanx-api-key: YOUR_API_KEYHow It Works
Understand the Layer 2 Agent Monitor and the scan lifecycle.
What is Layer 2 Agent Monitor?
Traditional compliance tools scan inputs (documents, code, forms). The Layer 2 Agent Monitor sits downstream of your AI agent and inspects the agent's output before it reaches the end user. It acts as a real-time compliance filter — catching PII, protected health information, and regulatory violations that a language model may inadvertently expose.
Scan Lifecycle
Agent Response
Your AI agent generates a text response
Reglint Scans
Regex rules run against the output in milliseconds
Decision
User Sees Result
Safe or redacted response delivered; violations logged
Agent Response
Your AI agent generates a text response
Reglint Scans
Regex rules run against the output in milliseconds
Decision
BLOCK · REDACT · ALERT · PASS
User Sees Result
Safe or redacted response delivered; violations logged
The agent output is never delivered. The most severe violations (e.g. bare SSNs, credit card numbers) trigger this.
Matched substrings are replaced with [REDACTED] and the sanitised response is delivered instead.
The response is delivered unchanged, but a compliance alert is emailed to your configured receivers and logged in your Agents dashboard.
A variant of ALERT: instead of being finalized automatically, the item is routed to a pending Review Queue for a person to approve, reject, or edit. Whether an item becomes ALERT_HITL is determined by the engine.
The output is clean. The scan completes in milliseconds and the response is forwarded immediately.
When the engine assigns ALERT_HITL, the item is held for human review rather than being finalized automatically. It appears in the pending Review Queue at /dashboard/agents/queue (linked from the Violations Hub). A reviewer resolves each pending item with one of three actions:
- Approve — accept the pending item.
- Reject — decline the pending item.
- Edit — revise the item, optionally with a note, before resolving.
Industries
Pass industry in your API call to focus Reglint on the regulations that matter most to you.
The industry field is optional but recommended. When set, Reglint prioritises the rule sets most relevant to your sector, improving signal quality and reducing noise.
Supported values and their primary regulation coverage:
healthcare→fintech→privacy→hr→general→Usage
Add the industry field to your request payload:
{
"agent_output": "...",
"agent_name": "MedicalAdvisorBot",
"industry": "healthcare",
"mode": "full"
}Scan Mode
Choose between instant regex scanning or deep RAG + Claude analysis.
- ✓Regex pattern matching only
- ✓Milliseconds latency
- ✓Fully deterministic
- –No legal citations or context
- ✓Rules Engine → RAG → Claude
- ✓2–8 seconds
- ✓Contextual + legal citations
- ✓Fine ranges per violation
// Fast — rules engine only, milliseconds
body: JSON.stringify({ agent_output: agentResponse, mode: "fast" })
// Full — RAG + Claude deep analysis (default)
body: JSON.stringify({ agent_output: agentResponse, mode: "full" })Default Action
Override how Reglint handles all violations in a single request.
default_action lets you override the action for all violations in a single request — useful for testing, or when you want a blanket policy for a specific agent.
Reglint uses each rule's own default action (recommended). Same as omitting the field.
All violations trigger BLOCK — output is suppressed entirely.
All violations trigger REDACT — sensitive text is masked in the response.
All violations trigger ALERT — response is delivered, compliance team is notified.
Note: default_action overrides rules_config for all violations. If not set, per-rule configuration applies.
// AUTO — Reglint decides per rule (recommended)
body: JSON.stringify({ agent_output: agentResponse, default_action: "AUTO" })
// BLOCK — suppress everything
body: JSON.stringify({ agent_output: agentResponse, default_action: "BLOCK" })
// REDACT — mask sensitive data only
body: JSON.stringify({ agent_output: agentResponse, default_action: "REDACT" })
// ALERT — deliver + notify compliance team
body: JSON.stringify({ agent_output: agentResponse, default_action: "ALERT" })Per-Rule Configuration
Override the action for individual rules stored in your customer config.
Each customer can store a rules_config map in DynamoDB. When Reglint processes a request for your customer ID, it merges your overrides with the Reglint defaults. Set a rule to IGNORE to disable it entirely.
Example config stored for your customer:
{
"SSN_EXPOSURE": "BLOCK",
"EMAIL_EXPOSURE": "REDACT",
"MEDICAL_DATA_EXPOSURE": "ALERT",
"PHONE_EXPOSURE": "IGNORE"
}How Reglint Decides Severity
Reglint evaluates each scan in two layers. Understanding this helps you choose the right mode for your use case.
Layer 1: Rules Engine (Fast Mode)
Each of the 50 rules has a documented default action (BLOCK / REDACT / ALERT). The rules engine runs in both fast and full modes and follows these defaults exactly.
Layer 2: Claude AI (Full Mode Only)
In mode: full, Claude evaluates the violation in the context of your industry. Claude may upgrade severity (e.g., ALERT → REDACT) if the legal framework requires stricter handling. Claude does not downgrade.
Choosing Your Mode
- Fast mode: ~1.5s, predictable. Best for high-throughput screening.
- Full mode: ~10–15s, context-aware. Best for healthcare, finance, HR.
Enforcement Patterns: When Reglint Intervenes
Reglint returns a decision + a redacted version of the AI response. You decide when and how to act on it. Three common patterns are shown below — pick the one that matches your industry's compliance posture.
Pattern 1: Pre-Display Enforcement (Strict)
Hold the AI response, scan it through Reglint, then display based on the decision. The user never sees a violation. Best for: healthcare (HIPAA), finance (GLBA), HR (EEOC).
async function handleUserMessage(userMessage) {
// 1. Get AI response (held in memory, not displayed yet)
const aiResponse = await callAIAgent(userMessage);
// 2. Scan with Reglint BEFORE showing user
const scan = await fetch('https://reglint.ai/api/monitor/scan', {
method: 'POST',
headers: {
'x-api-key': process.env.REGLINT_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
agent_output: aiResponse,
industry: 'healthcare',
mode: 'full'
})
}).then(r => r.json());
// 3. Apply decision — user sees only the safe version
switch (scan.final_decision) {
case 'BLOCK':
return 'Sorry, I cannot help with that request.';
case 'REDACT':
return scan.redacted_output; // Reglint provides this
case 'ALERT':
case 'PASS':
default:
return aiResponse;
}
}User experience: safe content only. Latency cost: ~1–2s (fast mode) or ~10s (full mode).
Pattern 2: Post-Display Warning (Soft)
Display the AI response immediately, scan in parallel, then show a warning if a violation is detected. Best for: marketing chatbots, internal tools, low-risk content.
async function handleUserMessage(userMessage) {
// 1. Get AI response and display immediately
const aiResponse = await callAIAgent(userMessage);
displayInChat(aiResponse);
// 2. Scan in background (non-blocking)
fetch('https://reglint.ai/api/monitor/scan', {
method: 'POST',
headers: {
'x-api-key': process.env.REGLINT_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
agent_output: aiResponse,
industry: 'general',
mode: 'fast'
})
})
.then(r => r.json())
.then(scan => {
// 3. Show warning AFTER the response if violation detected
if (scan.final_decision !== 'PASS') {
showWarning(`Compliance flag: ${scan.violations[0].violation_id}`);
}
});
}User experience: fast response, occasional warnings. Latency cost: 0ms (scan runs in parallel).
Pattern 3: Audit-Only Logging (Silent)
Display AI responses without intervention. Use Reglint to log every interaction for compliance reporting and audits. Best for: enterprise audit trails, regulated industries requiring records, monitoring without UX changes.
async function handleUserMessage(userMessage) {
// 1. Get AI response and display immediately — no intervention
const aiResponse = await callAIAgent(userMessage);
displayInChat(aiResponse);
// 2. Log to Reglint for compliance audit (silent, fire-and-forget)
fetch('https://reglint.ai/api/monitor/scan', {
method: 'POST',
headers: {
'x-api-key': process.env.REGLINT_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
agent_output: aiResponse,
user_input: userMessage,
industry: 'finance',
mode: 'full',
consent_for_training: false
})
});
// No await — fire and forget. Audit happens server-side.
}User experience: identical to no Reglint. Compliance benefit: full audit trail in your Reglint dashboard.
Which Pattern Should You Use?
| Industry / Use Case | Recommended Pattern | Why |
|---|---|---|
| Healthcare (HIPAA) | Pre-Display (Strict) | PHI must never reach unauthorized users |
| Finance (GLBA, SOX) | Pre-Display (Strict) | Financial data exposure has legal liability |
| HR / Hiring | Pre-Display (Strict) | Discrimination prevention is non-negotiable |
| Marketing chatbots | Post-Display (Soft) | Speed matters more than strict compliance |
| Internal tools | Audit-Only | Employees trusted, but need audit trail |
| Customer support (general) | Post-Display or Pre-Display | Depends on data sensitivity |
| Education / EdTech (FERPA) | Pre-Display (Strict) | Student records protected by federal law |
Reglint provides the decision. You provide the policy. The same rules can produce different user experiences depending on your enforcement pattern. This flexibility lets Reglint serve every industry without forcing a one-size-fits-all approach.
All 69 Rule IDs
Use any of these IDs as keys in your rules_config:
| # | Rule ID | Default Action | Severity | Law |
|---|---|---|---|---|
| 1 | SSN_EXPOSURE | REDACT | critical | Privacy Act 1974, GDPR Article 9 |
| 2 | CREDIT_CARD_EXPOSURE | REDACT | critical | PCI DSS Requirement 3.2 |
| 3 | EMAIL_EXPOSURE | ALERT | high | GDPR Article 5, CCPA §1798.100 |
| 4 | PHONE_EXPOSURE | ALERT | high | TCPA, GDPR Article 5 |
| 5 | MEDICAL_DATA_EXPOSURE | BLOCK | critical | HIPAA §164.514, GDPR Article 9 |
| 6 | FINANCIAL_DATA_EXPOSURE | REDACT | critical | GLBA, PCI DSS |
| 7 | PASSWORD_EXPOSURE | BLOCK | critical | GDPR Article 32, NIST SP 800-63B |
| 8 | DISCRIMINATORY_CONTENT | BLOCK | critical | Title VII, ECOA, ADA |
| 9 | BIOMETRIC_DATA | BLOCK | critical | BIPA, GDPR Article 9 |
| 10 | CHILD_DATA | BLOCK | critical | COPPA, GDPR Article 8 |
| 11 | LOCATION_TRACKING | ALERT | high | CCPA, State Location Privacy Laws |
| 12 | DATA_BULK_EXPOSURE | BLOCK | critical | GDPR Article 5(1)(c), CCPA |
| 13 | FERPA_STUDENT_DATA | BLOCK | critical | FERPA 20 U.S.C. §1232g |
| 14 | TCPA_MARKETING | ALERT | high | TCPA 47 U.S.C. §227 |
| 15 | CAN_SPAM_VIOLATION | ALERT | high | CAN-SPAM Act 15 U.S.C. §7704 |
| 16 | VPPA_VIDEO_DATA | ALERT | high | VPPA 18 U.S.C. §2710 |
| 17 | DPPA_DRIVER_DATA | REDACT | critical | DPPA 18 U.S.C. §2721 |
| 18 | ECPA_WIRETAP | BLOCK | critical | ECPA 18 U.S.C. §2511 |
| 19 | GINA_GENETIC_DATA | BLOCK | critical | GINA 42 U.S.C. §2000ff |
| 20 | FTC_DARK_PATTERNS | ALERT | high | FTC Dark Patterns Report 2022 |
| 21 | EU_AI_ACT_HIGH_RISK | ALERT | critical | EU AI Act Article 6 |
| 22 | GDPR_CONSENT_VIOLATION | BLOCK | critical | GDPR Article 7 |
| 23 | AGE_DISCRIMINATION | BLOCK | critical | ADEA 29 U.S.C. §623 |
| 24 | IMMIGRATION_STATUS | BLOCK | critical | Immigration and Nationality Act |
| 25 | RACIAL_LANGUAGE | BLOCK | critical | Civil Rights Act Title VI |
| 26 | GLBA_FINANCIAL_PRIVACY | BLOCK | critical | GLBA 15 U.S.C. §6802 |
| 27 | SOX_FINANCIAL_MANIPULATION | ALERT | high | SOX Section 302 |
| 28 | ROUTING_NUMBER | REDACT | critical | GLBA, Reg E |
| 29 | ACCOUNT_NUMBER_EXPOSURE | REDACT | critical | GLBA, Reg E |
| 30 | FCRA_BACKGROUND_CHECK | ALERT | high | FCRA 15 U.S.C. §1681 |
| 31 | PASSPORT_EXPOSURE | REDACT | critical | Privacy Act 1974, GDPR Article 9 |
| 32 | CONTACT_PHI_COMBINATION | REDACT | high | HIPAA §164.514, GDPR Article 5 |
| 33 | INSURANCE_ID_EXPOSURE | REDACT | high | HIPAA §164.514, GLBA |
| 34 | CFAA_UNAUTHORIZED_ACCESS | BLOCK | critical | CFAA 18 U.S.C. §1030 |
| 35 | HITECH_BREACH_NOTIFICATION | ALERT | critical | HITECH Act 42 U.S.C. §17931 |
| 36 | FTC_DECEPTIVE_CLAIMS | ALERT | high | FTC Act Section 5 15 U.S.C. §45 |
| 37 | ADA_ACCESSIBILITY_BARRIER | ALERT | high | ADA Title II, WCAG 2.1 AA |
| 38 | CMIA_HEALTH_DATA | BLOCK | critical | CMIA Cal. Health & Safety Code §56 |
| 39 | SHIELD_ACT_DATA_EXPOSURE | ALERT | high | NY SHIELD Act N.Y. Gen. Bus. Law §899-aa |
| 40 | EPRIVACY_TRACKING_CONSENT | ALERT | high | ePrivacy Directive 2002/58/EC |
| 41 | ADPPA_DATA_MINIMIZATION | ALERT | high | ADPPA (proposed) H.R. 8152 |
| 42 | STATE_PRIVACY_DATA_RIGHTS | ALERT | high | State Privacy Laws (TX, FL, CT, OR, MT, DE, IA, IN, TN, ND, NH, NJ, KY) |
| 43 | MEDICAL_PHI_SOLICITATION | BLOCK | critical | HIPAA §164.508(a)(3) |
| 44 | DISCRIMINATORY_SOLICITATION | BLOCK | critical | ECOA Reg B 12 CFR §202.5, Title VII 42 U.S.C. §2000e, Fair Lending |
| 45 | PHI_TARGETED_MARKETING | BLOCK | critical | HIPAA §164.508(a)(3) |
| 46 | FINANCIAL_PII_INSECURE_REQUEST | ALERT | high | GLBA Safeguards Rule 16 CFR §314, PCI DSS Req 3.2, NIST SP 800-53 IA-5 |
| 47 | SANCTIONS_AWARENESS | ALERT | high | OFAC Regulations (31 CFR Chapter V), IEEPA, Executive Orders |
| 48 | ELDER_FINANCIAL_ABUSE | BLOCK | critical | Elder Justice Act, State Elder Abuse Statutes, FCRA |
| 49 | PREGNANCY_DISCRIMINATION_CONTEXT | ALERT | high | Pregnancy Discrimination Act (PDA), Title VII, FMLA |
| 50 | RELIGIOUS_DISCRIMINATION_CONTEXT | ALERT | high | Title VII, EEOC Religious Discrimination Guidelines |
| 51 | NATIONAL_ORIGIN_DISCRIMINATION | ALERT | high | Title VII, IRCA (Immigration Reform and Control Act), EEOC |
| 52 | MENTAL_HEALTH_DISCRIMINATION | ALERT | high | ADA (Americans with Disabilities Act), Mental Health Parity Act |
| 53 | VETERAN_STATUS_DISCRIMINATION | ALERT | high | USERRA, VEVRAA, Title VII |
| 54 | FAMILIAL_STATUS_DISCRIMINATION | ALERT | high | Title VII (sex discrimination), Family Responsibilities Discrimination |
| 55 | AGE_DISCRIMINATION_LANGUAGE | ALERT | high | ADEA (Age Discrimination in Employment Act), Title VII |
| 56 | PRIVACY_ACT_THIRD_PARTY | REDACT | critical | 5 U.S.C. § 552a(b) |
| 57 | EG_NATIONAL_ID | REDACT | high | قانون حماية البيانات الشخصية 151/2020، المادة 1 + اللائحة التنفيذية قرار 816/2025 |
| 58 | SA_NATIONAL_ID | REDACT | high | نظام حماية البيانات الشخصية السعودي، المادة 1 + اللوائح التنفيذية |
| 59 | AE_EMIRATES_ID | REDACT | high | المرسوم بقانون اتحادي 45/2021 بشأن حماية البيانات الشخصية (الإمارات) |
| 60 | QA_QID | REDACT | high | قانون رقم 13 لسنة 2016 بشأن حماية خصوصية البيانات الشخصية (قطر) |
| 61 | KW_CIVIL_ID | REDACT | high | قانون حماية البيانات (الكويت، لائحة CITRA) |
| 62 | BH_CPR | ALERT | medium | قانون رقم 30 لسنة 2018 بشأن حماية البيانات الشخصية (البحرين) |
| 63 | GCC_EG_IBAN | REDACT | high | قوانين حماية البيانات الخليجية/المصرية + تعليمات ساما لحماية عملاء البنوك |
| 64 | AR_PHONE_EXPOSURE | ALERT | medium | قوانين حماية البيانات الخليجية/المصرية (بيانات الاتصال) |
| 65 | AR_ID_SOLICITATION | BLOCK | high | قوانين حماية البيانات الخليجية/المصرية (طلب بيانات تعريفية في المحادثة) |
| 66 | AR_PASSWORD_EXPOSURE | BLOCK | critical | قوانين حماية البيانات + معايير أمن المعلومات (كشف كلمات المرور) |
| 67 | AR_MEDICAL_DATA | BLOCK | high | اللائحة التنفيذية 816/2025 (بيانات حساسة) / نظام حماية البيانات السعودي المادة 1 (البيانات الصحية) |
| 68 | AR_DOB | ALERT | medium | قوانين حماية البيانات الخليجية/المصرية (بيانات تعريفية) |
| 69 | AR_KYC_BYPASS_SOLICITATION | BLOCK | critical | متطلبات مكافحة غسل الأموال وتمويل الإرهاب (KYC) — السعودية/الإمارات/مصر/قطر/الكويت/البحرين |
How to Adjust Rules
Compliance rules are regex patterns paired with an enforcement action and severity level.
Each rule is a plain JavaScript / JSON object. Reglint evaluates rules in order of severity — critical first — and takes the highest-priority action that matches. A single scan can detect multiple violations.
Rules are maintained in your Lambda layer configuration and hot-reloaded on deploy. Contact support@reglint.ai or edit the rules file directly in your infrastructure repository to add, remove, or tune patterns.
Rule Object Shape
Every rule must include these fields:
// A single compliance rule object
const rule = {
pattern: "\\b(?!000|666|9\\d{2})\\d{3}-(?!00)\\d{2}-(?!0000)\\d{4}\\b",
violation_id: "SSN_EXPOSURE",
law: "HIPAA § 164.514 / CCPA",
description: "Social Security Number detected in agent output",
action: "BLOCK", // "BLOCK" | "REDACT" | "ALERT"
severity: "critical", // "critical" | "high" | "medium"
};| Field | Type | Description |
|---|---|---|
| pattern | string (RegExp) | Regular expression source (no delimiters). Flags i and g are applied automatically. |
| violation_id | string | Unique machine-readable identifier. Appears in logs and dashboard. |
| law | string | The regulation this rule enforces — e.g. "HIPAA § 164.514", "GDPR Art. 9". |
| description | string | Human-readable explanation of what the rule catches. |
| action | "BLOCK" | "REDACT" | "ALERT" | Enforcement action when the pattern matches. |
| severity | "critical" | "high" | "medium" | Controls prioritisation when multiple rules fire. |
When to use BLOCK vs REDACT vs ALERT
Use when exposure of any kind is unacceptable.
\b\d{3}-\d{2}-\d{4}\bbare Social Security Number\b(?:4\d{12}(?:\d{3})?|5[1-5]\d{14})\bLuhn-valid card numbersUse when the response is still useful after masking the sensitive token.
\b(0?[1-9]|1[0-2])[\/\-](0?[1-9]|[12]\d|3[01])[\/\-](\d{2}|\d{4})\bMM/DD/YYYY or MM-DD-YY\b(\+1[\s.-]?)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}\bUS phone formatsUse when you need visibility but the data is low-risk or contextually acceptable.
MRN[:\s#]*\d{5,10}Medical Record Number reference\b[A-Z]\d{2}(?:\.\d{1,2})?\bICD-10 diagnostic codesHow to Add a Webhook
Send scan results from your agent infrastructure directly to Reglint.
Obtain your webhook secret
AGENT_MONITOR_SECRET. Store it as an environment variable in your agent host — never hard-code it.Configure the endpoint
https://reglint.ai/api/agent-monitor/webhookx-reglint-secret: <your-secret>Build the payload
WebhookPayload interface. The four required fields are scan_id, customer_id, agent_name, and final_decision. All other fields are optional but recommended for full dashboard visibility.Handle the response
{ "received": true, "id": "agv_..." }. The endpoint is idempotent on scan_id — retrying a duplicate payload with the same ID will update mutable fields without creating a duplicate record.Full Payload Shape
TypeScript interface — all optional fields are marked with ?.
// Full WebhookPayload shape (TypeScript)
interface LambdaViolation {
violation_id?: string; // e.g. "SSN_EXPOSURE"
type?: string; // legacy alias for violation_id
law?: string; // e.g. "HIPAA § 164.514"
description?: string;
violating_text?: string; // the exact matched substring
action?: string; // BLOCK | REDACT | ALERT
severity?: string; // critical | high | medium
}
interface WebhookPayload {
scan_id: string; // unique scan UUID (idempotency key)
customer_id: string; // your Reglint user ID
agent_name: string; // human-readable agent label
industry?: string; // e.g. "healthcare", "finance"
final_decision: string; // "BLOCK" | "REDACT" | "ALERT" | "PASS"
violations_count: number;
violations: LambdaViolation[];
original_output?: string; // raw agent text before redaction
redacted_output?: string; // text with PII replaced by [REDACTED]
agent_endpoint?: string; // URL of the calling agent (optional)
processing_time_ms?: number; // scan duration
}JavaScript Example
Using the native fetch API (Node 18+, browser, Deno, Bun).
// JavaScript — send a scan result to Reglint
const payload = {
scan_id: crypto.randomUUID(),
customer_id: "usr_YOUR_REGLINT_USER_ID",
agent_name: "MedicalAdvisorBot",
industry: "healthcare",
final_decision: "BLOCK",
violations_count: 1,
violations: [
{
violation_id: "SSN_EXPOSURE",
law: "HIPAA § 164.514",
description: "SSN detected in agent response",
violating_text: "123-45-6789",
action: "BLOCK",
severity: "critical",
},
],
original_output: "Your SSN is 123-45-6789, here is your summary…",
redacted_output: "Your SSN is [REDACTED], here is your summary…",
processing_time_ms: 42,
};
const res = await fetch(
"https://reglint.ai/api/agent-monitor/webhook",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"x-reglint-secret": process.env.REGLINT_WEBHOOK_SECRET,
},
body: JSON.stringify(payload),
}
);
const data = await res.json();
// { received: true, id: "agv_..." }
console.log(data);Python Example
Using the requests library.
# Python — send a scan result to Reglint
import os
import uuid
import requests
payload = {
"scan_id": str(uuid.uuid4()),
"customer_id": "usr_YOUR_REGLINT_USER_ID",
"agent_name": "MedicalAdvisorBot",
"industry": "healthcare",
"final_decision": "BLOCK",
"violations_count": 1,
"violations": [
{
"violation_id": "SSN_EXPOSURE",
"law": "HIPAA § 164.514",
"description": "SSN detected in agent response",
"violating_text": "123-45-6789",
"action": "BLOCK",
"severity": "critical",
}
],
"original_output": "Your SSN is 123-45-6789, here is your summary…",
"redacted_output": "Your SSN is [REDACTED], here is your summary…",
"processing_time_ms": 42,
}
response = requests.post(
"https://reglint.ai/api/agent-monitor/webhook",
json=payload,
headers={
"x-reglint-secret": os.environ["REGLINT_WEBHOOK_SECRET"],
},
timeout=10,
)
data = response.json()
# {'received': True, 'id': 'agv_...'}
print(data)Response Codes
| Status | Meaning |
|---|---|
| 200 OK | Payload received and stored (or idempotent duplicate). |
| 400 Bad Request | Missing required fields: scan_id, customer_id, agent_name, or final_decision. |
| 401 Unauthorized | The x-reglint-secret header is missing or does not match. |
| 500 Internal Server Error | Unexpected server error — retry with exponential back-off. |
Implementation tip
Generate a fresh scan_id (UUID v4) for every unique scan. If your infrastructure retries on failure, reuse the same scan_id — Reglint will upsert rather than duplicate. Use a queue (SQS, RabbitMQ) to buffer webhooks and retry on 5xx with exponential back-off.
Complete Integration Example
A production-ready pattern for wrapping any AI agent with Reglint compliance.
This example wraps any AI agent call with Reglint and handles all four decision outcomes. Drop it into your backend as a utility and call it wherever you invoke an agent.
const REGLINT_ENDPOINT =
'https://reglint.ai/api/monitor/scan';
async function runAgentWithReglint(userMessage, agentName, industry) {
const agentResponse = await myAIAgent.run(userMessage);
const result = await fetch(REGLINT_ENDPOINT, {
method: 'POST',
headers: {
'x-api-key': process.env.REGLINT_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
agent_output: agentResponse,
agent_name: agentName,
industry: industry,
mode: 'full',
default_action: 'AUTO'
})
}).then(r => r.json());
switch (result.final_decision) {
case 'BLOCK':
return {
delivered: false,
message: "Unable to process this request due to compliance restrictions.",
violations: result.violations
};
case 'REDACT':
return {
delivered: true,
message: result.redacted_output,
violations: result.violations
};
case 'ALERT':
return {
delivered: true,
message: agentResponse,
violations: result.violations
};
case 'PASS':
default:
return {
delivered: true,
message: agentResponse,
violations: []
};
}
}delivered: false — show a generic error to the user.
delivered: true — serve redacted_output instead of the original.
delivered: true — serve original. Compliance team is notified via email.
delivered: true — serve original. No violations found, no action needed.
Supported Integrations
Reglint is model-agnostic. Any LLM output, any framework, any language.
Reglint exposes a plain HTTP REST API — there is no SDK required and no vendor lock-in. If your agent can make an HTTP POST request, it works with Reglint. The table below lists tested integrations with copy-paste examples.
Pass agent_name as a human-readable label so violations are correctly attributed in your Agents dashboard.
| Provider / Framework | Type | agent_name suggestion | Notes |
|---|---|---|---|
| OpenAI (GPT-4, GPT-3.5) | LLM | "gpt4o-agent" | Scan chat.completions response before returning to user. |
| Anthropic Claude | LLM | "claude-agent" | Scan message.content[0].text from Messages API. |
| Google Gemini | LLM | "gemini-agent" | Scan response.candidates[0].content.parts[0].text. |
| Meta Llama (via Ollama) | Local LLM | "ollama-llama3" | Run Ollama locally; scan response.response field. |
| Mistral | LLM | "mistral-agent" | Mistral API or local — scan the text output. |
| Cohere | LLM | "cohere-agent" | Scan response.text from Co.generate or Co.chat. |
| LangChain | Framework | "langchain-chain" | Intercept chain.invoke() result before returning. |
| LlamaIndex | Framework | "llamaindex-query" | Wrap QueryEngine.query() response.response. |
| CrewAI | Framework | "crewai-crew" | Scan crew.kickoff() final output string. |
| Any custom model (HTTP API) | Custom | "custom-model" | Works with any model accessible via HTTP — local or hosted. |
TypeScript + OpenAI (GPT-4o)
Full compliance wrapper using the OpenAI Node SDK and fetch.
import OpenAI from 'openai';
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const REGLINT_ENDPOINT = 'https://reglint.ai/api/monitor/scan';
async function runCompliantAgent(userMessage: string): Promise<{
delivered: boolean;
message: string;
violations: unknown[];
}> {
// 1. Get GPT-4o response
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: userMessage },
],
});
const rawOutput = completion.choices[0].message.content ?? '';
// 2. Scan with Reglint
const scan = await fetch(REGLINT_ENDPOINT, {
method: 'POST',
headers: {
'x-api-key': process.env.REGLINT_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
agent_output: rawOutput,
agent_name: 'gpt4o-assistant',
industry: 'general',
mode: 'full',
}),
}).then(r => r.json());
// 3. Enforce decision
switch (scan.final_decision) {
case 'BLOCK':
return { delivered: false, message: 'Response blocked due to compliance violation.', violations: scan.violations };
case 'REDACT':
return { delivered: true, message: scan.redacted_output ?? rawOutput, violations: scan.violations };
default:
return { delivered: true, message: rawOutput, violations: scan.violations ?? [] };
}
}
const result = await runCompliantAgent('Summarize the customer account.');
console.log(result.delivered ? result.message : '⛔ Blocked');Python + Anthropic Claude
Using the anthropic Python SDK with Reglint compliance scanning.
import os
import requests
import anthropic
claude = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
REGLINT_API_KEY = os.environ["REGLINT_API_KEY"]
REGLINT_ENDPOINT = "https://reglint.ai/api/monitor/scan"
def run_compliant_claude(user_message: str, industry: str = "general") -> dict:
"""Run a Claude agent and scan its output with Reglint before returning."""
# 1. Call Claude
message = claude.messages.create(
model="claude-opus-4-7",
max_tokens=1024,
messages=[{"role": "user", "content": user_message}],
)
raw_output = message.content[0].text
# 2. Scan with Reglint
scan = requests.post(
REGLINT_ENDPOINT,
json={
"agent_output": raw_output,
"agent_name": "claude-opus-4-agent",
"industry": industry,
"mode": "full",
"default_action": "AUTO",
},
headers={"x-api-key": REGLINT_API_KEY},
timeout=15,
).json()
decision = scan.get("final_decision", "PASS")
if decision == "BLOCK":
return {
"delivered": False,
"message": "Blocked — compliance violation detected.",
"violations": scan.get("violations", []),
}
elif decision == "REDACT":
return {
"delivered": True,
"message": scan.get("redacted_output", raw_output),
"violations": scan.get("violations", []),
}
else: # ALERT or PASS
return {
"delivered": True,
"message": raw_output,
"violations": scan.get("violations", []),
}
if __name__ == "__main__":
result = run_compliant_claude("Show me the patient's latest test results.", industry="healthcare")
if result["delivered"]:
print("Agent:", result["message"])
else:
print("Blocked:", result["message"])
for v in result["violations"]:
print(f" • {v.get('violation_id')} — {v.get('law')}")Python + Llama (via Ollama)
Run a local Llama model with Ollama and scan its output — zero cloud LLM dependency.
import os
import requests
# Ollama runs locally at http://localhost:11434 by default
OLLAMA_ENDPOINT = "http://localhost:11434/api/generate"
REGLINT_API_KEY = os.environ["REGLINT_API_KEY"]
REGLINT_ENDPOINT = "https://reglint.ai/api/monitor/scan"
def run_compliant_llama(prompt: str, model: str = "llama3.2") -> dict:
"""Run a local Llama model via Ollama and scan its output with Reglint."""
# 1. Call Ollama / local Llama
ollama_res = requests.post(
OLLAMA_ENDPOINT,
json={"model": model, "prompt": prompt, "stream": False},
timeout=60,
).json()
raw_output = ollama_res.get("response", "")
# 2. Scan with Reglint — use "fast" mode for low latency in local dev
scan = requests.post(
REGLINT_ENDPOINT,
json={
"agent_output": raw_output,
"agent_name": f"ollama-{model}",
"industry": "privacy",
"mode": "fast",
},
headers={"x-api-key": REGLINT_API_KEY},
timeout=15,
).json()
decision = scan.get("final_decision", "PASS")
latency = scan.get("processing_time_ms")
print(f"[Reglint] decision={decision}, violations={scan.get('violations_count', 0)}, latency={latency}ms")
if decision == "BLOCK":
return {"delivered": False, "message": "Response blocked.", "violations": scan.get("violations", [])}
elif decision == "REDACT":
return {"delivered": True, "message": scan.get("redacted_output", raw_output), "violations": scan.get("violations", [])}
else:
return {"delivered": True, "message": raw_output, "violations": []}
if __name__ == "__main__":
result = run_compliant_llama("Tell me about this user's medical history.")
if result["delivered"]:
print("Output:", result["message"])
else:
print("Blocked — not delivered to user.")Works With Any Language
Reglint is a plain REST API — no SDK needed. Any programming language that can send an HTTP POST request works out of the box. The integration is always the same three steps:
- Get your agent's raw output.
- POST it to the Reglint monitor endpoint with your API key.
- Check
final_decisionand enforce accordingly.
# The simplest possible integration — any language, any shell
curl -X POST https://reglint.ai/api/monitor/scan \
-H "x-api-key: $REGLINT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent_output": "'"$AGENT_OUTPUT"'",
"agent_name": "my-agent",
"industry": "healthcare",
"mode": "fast"
}' | jq '.final_decision'Email Alerts
Configure who gets notified when violations are detected — per agent, per severity, per team.
Reglint can email your team when compliance violations are detected. You control which decisions trigger an alert, minimum severity, and which addresses receive the notification — all in your request payload.
The email_alerts field is optional. When omitted, alerts fall back to the account-level alert email set in Settings → Notifications.
Default Behavior (no email_alerts)
Omit email_alerts and Reglint sends violation alerts to the account-level alert email for any BLOCK or violation-producing scan.
// Without email_alerts — uses account default alert email (Settings → Notifications)
const response = await fetch('https://reglint.ai/api/monitor/scan', {
method: 'POST',
headers: {
'x-api-key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
agent_output: agentResponse,
agent_name: 'my-bot',
industry: 'healthcare',
mode: 'full',
}),
});Custom Email Routing
Add email_alerts to your request body to route alerts to specific teams based on decision and severity:
// With email_alerts — custom routing to compliance team
const response = await fetch('https://reglint.ai/api/monitor/scan', {
method: 'POST',
headers: {
'x-api-key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
agent_output: agentResponse,
agent_name: 'healthcare-bot',
industry: 'healthcare',
mode: 'full',
email_alerts: [
{
alert_on: ['BLOCK', 'REDACT'],
severity_min: 'high',
receivers: ['compliance@yourcompany.com'],
},
],
}),
});Configuration Schema
// TypeScript — email_alerts schema
email_alerts?: Array<{
enabled?: boolean; // default: true — set false to skip
alert_on?: ('BLOCK' | 'REDACT' | 'ALERT')[]; // default: all three
severity_min?: 'low' | 'medium' | 'high' | 'critical'; // default: 'low'
receivers: string[]; // required: one or more email addresses
}>enabled — disable an alert config without removing it
Set enabled: false to temporarily silence a config entry. Useful during deployments, incident response, or testing — the config stays in your code so you can re-enable with a one-character change.
// Temporarily disable alerts without deleting the config
email_alerts: [{
enabled: false, // ← flip to true to re-enable
alert_on: ['BLOCK', 'REDACT', 'ALERT'],
severity_min: 'high',
receivers: ['compliance@company.com'],
}]alert_on — decisions that trigger an alert
Critical violations — request was suppressed entirely
Sensitive data was masked in the response
Borderline issues flagged but response delivered
Default: all three when omitted.
severity_min — minimum severity threshold
criticalOnly critical violations (SSN, PHI, PCI, credentials)
highCritical + High (medical data, financial info, location)
mediumCritical + High + Medium (emails, phone numbers)
lowAll violations — broadest coverage, most noise
Default: low (sends for all severities).
Multi-Team Routing
Pass multiple configs in the array — each entry is evaluated independently. Different teams get different alerts from the same scan:
body: JSON.stringify({
agent_output: agentResponse,
agent_name: 'customer-service-prod',
industry: 'general',
email_alerts: [
{
// Critical incidents → CISO immediately
alert_on: ['BLOCK'],
severity_min: 'critical',
receivers: ['ciso@company.com'],
},
{
// All violations → Compliance team
alert_on: ['BLOCK', 'REDACT', 'ALERT'],
severity_min: 'low',
receivers: ['compliance@company.com'],
},
{
// High-severity → Security team
alert_on: ['BLOCK', 'REDACT'],
severity_min: 'high',
receivers: ['security@company.com'],
},
],
})Industry Examples
Healthcare — Compliance Team
email_alerts: [{
alert_on: ['BLOCK', 'REDACT', 'ALERT'],
severity_min: 'low',
receivers: ['hipaa-compliance@hospital.com'],
}]Banking — Fraud + Compliance
email_alerts: [{
alert_on: ['BLOCK', 'REDACT'],
severity_min: 'high',
receivers: [
'fraud@bank.com',
'compliance@bank.com',
],
}]HR — Legal Team
email_alerts: [{
alert_on: ['BLOCK', 'ALERT'],
severity_min: 'medium',
receivers: ['hr-legal@company.com'],
}]SaaS — On-Call Only Critical
email_alerts: [{
alert_on: ['BLOCK'],
severity_min: 'critical',
receivers: ['oncall@company.com'],
}]Environment-Based Routing
Use different alert configs per environment to avoid dev noise in production inboxes:
// Development — critical only, dev team
const devAlerts = [{
alert_on: ['BLOCK'],
severity_min: 'critical',
receivers: ['dev-team@company.com'],
}];
// Staging — high severity, QA team
const stagingAlerts = [{
alert_on: ['BLOCK', 'REDACT'],
severity_min: 'high',
receivers: ['qa-team@company.com'],
}];
// Production — all violations, multiple teams
const prodAlerts = [{
alert_on: ['BLOCK', 'REDACT', 'ALERT'],
severity_min: 'low',
receivers: ['compliance@company.com', 'security@company.com', 'oncall@company.com'],
}];
const email_alerts = process.env.NODE_ENV === 'production' ? prodAlerts
: process.env.NODE_ENV === 'staging' ? stagingAlerts
: devAlerts;How It Works
What's in Each Alert Email
Do
- ✓Use severity_min: "high" for production critical paths
- ✓Send to security@ AND compliance@ for critical violations
- ✓Use distribution lists, not personal emails
- ✓Test with alert_on: ["BLOCK"] first, then expand
- ✓Use different configs per environment
Don't
- ✗Send severity_min: "low" to executive emails (too noisy)
- ✗Hardcode personal email addresses
- ✗Set alert_on: ["ALERT"] only — you'll miss BLOCK events
- ✗Forget to test your alert config before going to production
Per-scan recipient control
Alert recipients are configured per-scan via the email_alerts array in your Reglint config. Each entry can target different receivers, severity thresholds, and decision filters — giving you full control without a shared account-level setting.
Request-Level Customization
Override rule actions per-scan without touching your DynamoDB config — useful for testing, staging, or context-specific agents.
Reglint supports two levels of rule customization:
Stored config (DynamoDB)
Persistent, per-customer overrides. Supports BLOCK, REDACT, ALERT, and IGNORE. Set via the Reglint dashboard or direct DynamoDB update. Applied to all scans for your customer ID.
Per-request override (API body)
One-time overrides sent in the request body as rules_config. Supports BLOCK, REDACT, ALERT only (not IGNORE). Applied only to this scan — no persistence.
How to Send Per-Request Overrides
Include rules_config directly in your scan request body:
// Override specific rules for this scan only — no DynamoDB update needed
body: JSON.stringify({
agent_output: agentResponse,
agent_name: 'medical-chatbot',
industry: 'healthcare',
mode: 'full',
rules_config: {
SSN_EXPOSURE: 'REDACT', // downgrade from BLOCK for this scan
MEDICAL_DATA_EXPOSURE: 'ALERT', // downgrade from BLOCK for demo purposes
LOCATION_TRACKING: 'ALERT', // keep at default (no change needed if same)
}
})Priority Order
When multiple configuration levels exist, Reglint resolves them in this priority order (highest wins):
// Priority order (highest wins):
// 1. per-request rules_config ← this request's body
// 2. default_action ← blanket override, if set
// 3. DynamoDB customer config ← stored per-customer overrides
// 4. Reglint built-in default ← each rule's default_action field
// Example: rule SSN_EXPOSURE has built-in default = BLOCK
// DynamoDB config says SSN_EXPOSURE = REDACT
// This request says rules_config.SSN_EXPOSURE = ALERT
// → Final action = ALERT (per-request wins)| Priority | Source | Scope | Supports IGNORE? |
|---|---|---|---|
| 1 (highest) | Per-request rules_config | This scan only | No |
| 2 | default_action (body field) | All rules, this scan | No |
| 3 | DynamoDB customer config | All scans, this customer | Yes |
| 4 (lowest) | Reglint built-in default | Universal fallback | N/A |
Rule Groups
Instead of naming every rule, rules_config also accepts group keys whose value is { default_action }. A group sets the action for a whole set of rules at once:
| Group key | Applies to |
|---|---|
| en | All non-Arabic (Layer-1) rules |
| ar | All 13 Arabic Layer-1 rules |
| ar.sa · ar.ae · ar.eg · ar.qa · ar.kw · ar.bh | That country’s national-ID rule |
{
"rules_config": {
"ar": { "default_action": "alert_hitl" }, // all Arabic rules → hold for review
"ar.sa": { "default_action": "block" }, // …but Saudi national-ID → block
"AR_MEDICAL_DATA": "REDACT" // …and this one rule → redact
}
}Group precedence (highest wins): per-rule id override › country group (ar.sa) › language group (ar/en) ›default_action. Group keys persist in a key›s saved policy exactly like per-rule overrides. A malformed group value is ignored (never weakens enforcement).
Common Use Cases
Testing / Staging environments
Downgrade BLOCK rules to ALERT during test runs so violations are visible in logs but responses aren't suppressed.
Context-specific agents
A legal research agent that legitimately quotes PHI in anonymized case studies can downgrade HIPAA rules to ALERT for that specific agent only.
Gradual rollout
Start with all rules at ALERT, validate your pipeline, then upgrade to BLOCK once you're confident in your integration.
HR training / compliance education tools
Training bots that teach employees about discrimination may intentionally generate examples of prohibited language. Use per-request overrides to audit-log without blocking.
Example: HR Training Mode
Downgrade all 9 employment discrimination rules from BLOCK/ALERT to ALERT for a training agent:
// HR compliance agent — tone down employment discrimination alerts for training mode
body: JSON.stringify({
agent_output: agentResponse,
agent_name: 'hr-training-bot',
industry: 'hr',
mode: 'full',
rules_config: {
// During training/testing, downgrade BLOCK to ALERT so responses aren't suppressed
DISCRIMINATORY_CONTENT: 'ALERT',
RACIAL_LANGUAGE: 'ALERT',
AGE_DISCRIMINATION: 'ALERT',
PREGNANCY_DISCRIMINATION_CONTEXT: 'ALERT',
RELIGIOUS_DISCRIMINATION_CONTEXT: 'ALERT',
MENTAL_HEALTH_DISCRIMINATION: 'ALERT',
VETERAN_STATUS_DISCRIMINATION: 'ALERT',
FAMILIAL_STATUS_DISCRIMINATION: 'ALERT',
AGE_DISCRIMINATION_LANGUAGE: 'ALERT',
}
})Full mode: Claude may escalate above your override
In mode: full, Claude AI performs deep legal analysis and may upgrade the decision above your rules_config setting if the regulatory context demands it (e.g., Claude may return BLOCK for a pattern you set to ALERT if it detects severe PHI exposure in context). In mode: fast, your rules_config values are applied exactly. Use mode: fast when you need deterministic enforcement.
Trusted User Access
Allow the AI to share PII with verified users while keeping fraud and sanctions protection active.
Security Warning
Setting trusted_users_access: true is intended only for authenticated contexts where the user's identity has been verified. Do not enable this for public chatbots, anonymous users, or any flow before authentication. The customer is responsible for verifying user identity and data entitlement.
A single boolean controls whether Reglint allows data sharing for the current request. Behavioral compliance protections (fraud, sanctions, abuse) remain fully active regardless.
trueAuthenticated portal mode
Reglint dismisses PII exposure, account, and transaction disclosure violations. The AI can share the user's own data freely. Wire fraud, sanctions, elder abuse, and other behavioral violations are still caught.
falseStandard mode (default)
All violations are active. PII exposure is blocked. This is the safe default for public-facing deployments.
const reglintConfig = {
api_key: "rgl_...",
endpoint: "https://reglint.ai/api/monitor/scan",
industry: "finance",
mode: "full",
// true → AI can share PII with verified user (fraud/sanctions still caught)
// false → all violations active (safe default for public deployments)
trusted_users_access: true,
};✓ Good fit
- Authenticated banking portal (logged-in user, own balance)
- Healthcare patient portal (verified patient, own records)
- Enterprise internal tool (verified employee credentials)
- Logged-in customer service AI assistant
✗ Not a good fit
- Public website chatbot
- Marketing AI on landing pages
- Any flow before user authentication
- Multi-user shared sessions
Always enforced — even when trusted_users_access: true
Federal Crimes
- •Wire fraud (18 U.S.C. § 1343)
- •Structuring (31 U.S.C. § 5324)
- •AML violations
- •OFAC sanctions bypass
- •Bank fraud
Vulnerable Populations
- •Elder financial abuse
- •Child data (COPPA)
- •Deceased account fraud
- •Impersonation of authority
Compliance Bypass
- •KYC bypass
- •Customer notification bypass
- •Authentication bypass
- •Loan underwriting fraud
{
"final_decision": "PASS",
"trusted_users_access": true,
"violations": [],
"metadata": {
"v3_dismissed_count": 3,
"scan_mode": "full"
}
}Custom Policies
Your own organizational rules, enforced by AI in real time alongside 69 deterministic regulatory patterns.
Custom Policies let your admin write plain-language prohibitions that Reglint enforces on every scan — in addition to built-in regulatory rules. They are evaluated by the same Claude AI that handles HIPAA, GDPR, and the rest of the ruleset. Custom policies are additive only: they can never dismiss or weaken a regulatory violation.
How to write a good rule
One clear prohibition per rule, in plain language. Concrete beats vague:
| Good rule | Too vague — avoid |
|---|---|
| “Never state prices or discounts before manager approval.” | “Be careful with pricing.” |
| “Do not name any competitor in agent output.” | “Avoid competitor mentions.” |
| “Never share internal headcount or revenue figures with external users.” | “Keep financials confidential.” |
Rule fields
| Field | Values | Description |
|---|---|---|
| id | CP-001, CP-002 … | Auto-assigned sequential ID |
| rule | string ≤ 300 chars | Plain-language prohibition |
| action | BLOCK · REDACT · ALERT | Enforcement action when violated |
| applies_to | human · agent · both | Which actor type this rule targets |
| channels | null or channel array | null = all 8 channels; or restrict to a subset |
| enabled | true · false | Per-rule toggle — disabled rules are ignored |
How violations appear
Custom policy violations arrive inside the existing violations[] array, indistinguishable to the extension UI. You can tell them apart in the raw payload by two fields:
violation_id: the CP id, e.g.“CP-001”source:“custom_policy”(regulatory violations have“rules_engine”or“claude_analysis”)
They appear in the Violations Hub like any other violation. The rule's configured action contributes to the final decision on the same BLOCK > REDACT > ALERT ladder as regulatory rules.
Limits
- Max 20 rules per API key
- Max 300 characters per rule
- Custom policies are additive — they never override or dismiss a regulatory violation
- The master kill switch (
custom_policies_enabled: false) disables all custom rules without deleting them
Example JSON
{
"custom_policies_enabled": true,
"custom_policies": [
{
"id": "CP-001",
"rule": "Never state prices or discounts before manager approval.",
"action": "BLOCK",
"applies_to": "both",
"channels": null,
"enabled": true
},
{
"id": "CP-002",
"rule": "Do not name any competitor in agent output.",
"action": "ALERT",
"applies_to": "agent",
"channels": ["slack", "gmail"],
"enabled": true
}
]
}Chrome Extension & Command Center
Install the Reglint browser extension to protect Gmail, Outlook, Slack, WhatsApp, and LinkedIn. Admins configure team compliance policy from the Command Center — no local settings needed.
Install the Extension
Add Reglint to Chrome in under two minutes.
Install from the Chrome Web Store
Open Settings
Enter your API Key
rgl_… key in the API Key field. Get it from reglint.ai/settings/api-keys. Click Save Settings — the badge turns green (ON).Test the connection
Your key is shown once. If you lose it, generate a new one from Settings → API Keys. The old key can be revoked from the same page.
Supported Channels
Reglint intercepts outgoing messages on five platforms before they are sent.
mail.google.com
Intercepts Send button clicks and Ctrl/Cmd+Enter. Scans subject + body combined. Supports subject redaction.
outlook.live.com / outlook.office.com
Intercepts the Send button in the compose pane. Scans subject + body combined.
app.slack.com
Intercepts Enter key and Send button in message input boxes.
web.whatsapp.com
Intercepts Enter key and Send icon in the message composer.
linkedin.com
Intercepts message Send in Messaging and InMail compose windows.
How it works on every channel
- Employee clicks Send (or presses the keyboard shortcut).
- Reglint intercepts the action and shows a scanning spinner.
- The message text is sent to the Reglint API using the configured API key.
- If the scan passes, the message is sent normally.
- If a violation is detected, a compliance modal appears — employee can review, proceed with redaction, or cancel.
Device Settings
Settings stored on the employee's browser. Each employee configures these once.
API KeyrequiredYour personal or team rgl_… key from reglint.ai/settings/api-keys. Stored encrypted in Chrome sync storage.
e.g. rgl_abc123…API EndpointrequiredThe scan endpoint. Leave at the default unless your organisation self-hosts Reglint.
e.g. https://www.reglint.ai/api/monitor/scanEmployee Display Name / EmailoptionalOverride how the sender appears in violation logs. Leave blank to auto-detect from the Chrome profile or the open platform (Gmail, etc.).
e.g. alice@company.comOn API ErroroptionalFail Open (default) — allow send if the Reglint API is unreachable. Fail Closed — block send if the API is unreachable. Admins can override this via server-side key policy.
e.g. fail-openScan policy is not set in the extension. Industry, scan mode, violation behavior, and per-rule configuration are all controlled by your admin in the Command Center and applied server-side to every employee using the same API key.
Admin Policy via Command Center
Admins set team compliance policy on each API key — no employee action required.
Go to Settings → API Keys
Settings → API Keys. Each key represents a team or department.Click "Edit Policy" on a key
Configure the policy
Policy Fields
| Field | Options | What it controls |
|---|---|---|
| Team Label | Any text | Human-readable name shown in violation logs and alerts. |
| Industry | healthcare · fintech · hr · privacy · general | Filters the per-rule table to show relevant rules and tells the scan engine which regulations to prioritise. |
| Scan Mode | fast · full | fast = regex only (ms). full = RAG + Claude (2–8s, contextual). |
| Default Action | BLOCK · REDACT · ALERT | Blanket enforcement for all violations when no per-rule override exists. |
| Violation Behavior | block · warn-only · log-only | block = prevent send, show modal. warn-only = show modal, allow override. log-only = silent, no modal. |
| On API Error | fail-open · fail-closed | What happens when the Reglint API is unreachable. |
| Trusted Users Access | on / off | Allow the AI to share PII with authenticated users (fraud/sanctions still caught). |
| Per-Rule Overrides | BLOCK · REDACT · ALERT · IGNORE per rule | Override the default action for individual compliance rules. |
Industry filter on the per-rule table
When you select an Industry in the Form view, the per-rule configuration table automatically filters to show only the rules relevant to that industry — for example, selectinghealthcareshows HIPAA, HITECH, CMIA, and GINA rules; selectinghr shows Title VII, ADEA, ADA, and GINA rules. Leave industry unset to see all 55 rules.
JSON View
Switch to the JSON tab to view and edit the full policy as structured JSON. The Form and JSON views stay in sync — changes in either are reflected in the other.
{
"teamLabel": "Clinical AI Team",
"industry": "healthcare",
"mode": "full",
"defaultAction": "BLOCK",
"behavior": "block",
"failMode": "fail-closed",
"trustedUsersAccess": false,
"rulesConfig": {
"MEDICAL_DATA_EXPOSURE": "REDACT",
"CONTACT_PHI_COMBINATION": "ALERT",
"LOCATION_TRACKING": "IGNORE"
}
}Policy Hierarchy
Server-side key policy overrides all local extension defaults — employees see the effect automatically.
When the Reglint API processes a scan request from the extension, it applies the policy attached to the API key server-side. The employee never has to change anything locally — the admin's policy takes effect for every scan on that key.
1 (highest)Server key policy
Set by admin in Command Center. Overrides everything below.
2Extension device defaults
Fail mode set by employee in Options page. Applies only if server policy field is null.
3 (lowest)Reglint built-in defaults
industry=general, mode=full, behavior=block — applied when neither policy nor extension sets the field.
What admins control (server-side)
- ✓Industry & scan mode
- ✓Default violation action (BLOCK / REDACT / ALERT)
- ✓Violation behavior (block / warn-only / log-only)
- ✓Fail mode (open / closed)
- ✓Trusted users access
- ✓Per-rule action overrides
What employees control (device-side)
- •API key (required)
- •API endpoint (default unless self-hosting)
- •Display name / email override (optional)
- •On API Error fallback (if not set by admin)
Action-Level Scanning (beta)
Scan a proposed tool call before the agent executes it.
In addition to scanning agent output text, you can ask Reglint to evaluate a proposed tool call before it executes. Pass the two optional fields alongside your normal request — when absent, behaviour is identical to today.
New optional request fields
proposed_actionobject | null — the tool call the agent wants to make: { tool: string, args: object }declared_rationalestring | null — the agent's stated reason for the action (max 1 000 chars)How it works
Rules engine on action args (fast + full mode)
rules_engine violation.LLM risk evaluation (full mode only)
Request example
POST /api/monitor/scan
x-api-key: rgl_...
{
"agent_output": "I will process the wire transfer now.",
"proposed_action": {
"tool": "transferMoney",
"args": { "amount": 50000, "to_account": "external-unverified" }
},
"declared_rationale": "customer asked",
"mode": "full"
}Response — HIGH_RISK_ACTION violation
{
"final_decision": "ALERT",
"violations": [
{
"violation_id": "HIGH_RISK_ACTION",
"severity": "high",
"law": "Operational Compliance",
"description": "Agent proposes an irreversible $50,000 wire transfer to an unverified external account with insufficient rationale.",
"recommended_action": "ALERT",
"source": "gemini_analysis"
}
]
}Human-in-the-Loop (HITL)
Hold high-risk output for a person to approve, reject, or edit before it is delivered.
Signal, not execution
When the engine assigns ALERT_HITL, the item is held — not delivered — and routed to your pending Review Queue at /dashboard/agents/queue. A reviewer resolves it with Approve, Reject, or Edit. Three rules apply to every integration below:
- 1.Reglint provides the signal; your client executes. On approval Reglint flips a status — it never sends, delivers, or acts on your behalf. Your code performs the action and your credentials never leave your system.
- 2.HITL requires Full mode. Deep review runs in
mode: "full". In Fast mode a would-be HITL item degrades to a plain ALERT (delivered + logged, never held). - 3.The review email is mandatory. A held item always emails your alert address (and any
email_alertsreceivers). It bypassesalert_on/severity_minand cannot be disabled.
HITL Status Endpoint (polled)
https://reglint.ai/api/agent-monitor/disposition-status?scan_id=<id>x-api-key: YOUR_API_KEYRead-only. Returns { scan_id, hitl_status, final_decision } where hitl_status ∈ none | pending | approved | rejected | edited. Rate-limited to ~60 requests/min per key — poll politely.
Guide 1 — Chrome Extension (automatic hold & release)
For teams using the Reglint extension. No code — the extension does the hold and the poll for you.
Set a HITL rule
The send is held
The extension polls (~6s)
Release on decision
Guide 2 — n8n (Wait + poll pattern)
For n8n workflows that scan agent output, then gate the delivery action on a human decision.
HTTP Request — Scan
/api/monitor/scan withmode: "full" and headerx-api-key.IF — is it held?
{{ $json.final_decision === 'ALERT_HITL' }}. False → deliver as normal. True → capture scan_id in a Set node.Wait → poll loop
hitl_status. Loop back to Wait while pending. Add a max-iteration guard (a sensible timeout) so the loop can't run forever.Act on the decision
approved → run your delivery action.rejected → stop.edited → deliver the returned edited_content (the reviewer's edit is the final decision).[Trigger]
│
[HTTP Request: POST /api/monitor/scan] body: { agent_output, agent_name, mode: "full" }
│ header: x-api-key: YOUR_API_KEY
[IF {{ $json.final_decision === 'ALERT_HITL' }}]
├─ false ─▶ [Deliver action] (PASS / ALERT / REDACT handled as usual)
└─ true ─▶ [Set: scan_id = {{ $json.scan_id }}]
│
┌─▶ [Wait 20s]
│ │
│ [HTTP Request: GET /api/agent-monitor/disposition-status?scan_id={{ $json.scan_id }}]
│ │ header: x-api-key: YOUR_API_KEY
│ [Switch on {{ $json.hitl_status }}]
│ ├─ pending ─┘ (loop back to Wait; cap at e.g. 45 iterations ≈ 15 min)
│ ├─ approved ─▶ [Deliver action]
│ ├─ rejected ─▶ [Stop / notify]
│ └─ edited ─▶ [Deliver {{ $json.edited_content }} — the reviewer's edit is final]edited, the status response includes the reviewer'sedited_content — deliver that; the reviewer's edit is the final decision.Guide 3 — Custom Agent / API (the developer contract)
The raw contract for any custom integration. Three steps: scan, poll, act.
Scan → maybe held
/api/monitor/scan. A held response returns final_decision: "ALERT_HITL",safe_to_deliver: false, and ascan_id. Do not deliver — hold your action.Poll the status endpoint
/api/agent-monitor/disposition-status?scan_id=<id>with your x-api-key untilhitl_status leaves pending.Act — your code, your credentials
approved → your code executes the action (Reglint only signals). rejected → discard.edited → deliver the returnededited_content (the reviewer's edit is the final decision).const BASE = 'https://reglint.ai';
// 1) Scan. A held item comes back ALERT_HITL / safe_to_deliver:false / scan_id.
async function scan(agentOutput) {
const r = await fetch(BASE + '/api/monitor/scan', {
method: 'POST',
headers: { 'x-api-key': process.env.REGLINT_API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ agent_output: agentOutput, agent_name: 'my-agent', mode: 'full' }),
});
return r.json();
}
// 2) Poll disposition-status with backoff + a hard timeout. Returns the terminal status.
async function waitForDecision(scanId, { intervalMs = 15000, timeoutMs = 15 * 60 * 1000 } = {}) {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
const r = await fetch(
BASE + '/api/agent-monitor/disposition-status?scan_id=' + encodeURIComponent(scanId),
{ headers: { 'x-api-key': process.env.REGLINT_API_KEY } },
);
if (r.status === 429) { await sleep(intervalMs * 2); continue; } // backoff on rate limit
if (r.status === 404) { await sleep(intervalMs); continue; } // row not landed yet
if (!r.ok) throw new Error('status ' + r.status); // 400/401 = fix your call
const data = await r.json(); // { scan_id, hitl_status, final_decision, edited_content? }
if (data.hitl_status !== 'pending' && data.hitl_status !== 'none') return data;
await sleep(intervalMs);
}
return 'timeout';
}
const sleep = (ms) => new Promise((res) => setTimeout(res, ms));
// 3) Act — Reglint signals, YOUR code executes.
const result = await scan(agentOutput);
if (result.final_decision !== 'ALERT_HITL') {
deliver(result); // PASS / ALERT / REDACT — your normal path
} else {
const outcome = await waitForDecision(result.scan_id);
if (outcome.hitl_status === 'approved') deliver({ ...result, original_output: agentOutput });
else if (outcome.hitl_status === 'rejected') discard(result.scan_id);
else if (outcome.hitl_status === 'edited') deliver({ ...result, original_output: outcome.edited_content }); // reviewer's edit is final
else /* timeout */ escalateToOps(result.scan_id, outcome);
}Status endpoint response codes
SIEM Integrations
Stream compliance events — scans, HITL decisions, and dispositions — to Datadog or a generic signed webhook.
Ship your audit trail to your SIEM
Configure an export under Settings → Integrations. Reglint then streams each compliance event to Datadog (Logs API) or a generic signed webhook (Splunk HEC and others). Events are metadata only — statutes, severities, decisions, and IDs. Message content and violating_text are never exported.
- •The API key is write-only. It is stored AES-256-GCM encrypted and never shown again after saving.
- •Delivery is durable. Events queue in an outbox and are retried on failure — they survive a transient SIEM outage or a Reglint restart.
- •Event filter. Choose Violations + HITL (default), All scans (incl. clean passes), or HITL only.
Datadog
Compliance events land as structured logs, queryable in Log Explorer within seconds.
Create a Datadog API key
Set your Datadog site
datadoghq.com (US1, default), us5.datadoghq.com (US5), datadoghq.eu (EU). Reglint posts to https://http-intake.logs.<site>/api/v2/logs.Choose events + enable
Send a test event
scan_completed through the real delivery path and shows the HTTP result inline (Datadog returns 202 on success).Verify in Log Explorer
service:reglint-monitor (or ddsource:reglint). Each log carries tags — customer, event, decision, channel — plus the full event as structured attributes.Example log in Datadog:
{
"ddsource": "reglint",
"service": "reglint-monitor",
"ddtags": "env:prod,customer:usr_123,event:scan_completed,decision:alert,channel:gmail",
"message": "reglint scan_completed ALERT",
"event_type": "scan_completed",
"event_id": "3f8c1a4e-…",
"occurred_at": "2026-07-03T14:22:05.001Z",
"customer_id": "usr_123",
"scan_id": "scan_abc",
"agent_name": "support-bot",
"final_decision": "ALERT",
"violations_count": 1,
"violations": [
{ "violation_id": "SSN_EXPOSURE", "law": "GLBA", "type": "pii", "severity": "high" }
]
}Generic webhook
Point Reglint at any HTTPS collector (Splunk HEC, a Lambda, your own service). Each event is POSTed as JSON, signed so you can verify it came from Reglint.
- •Endpoint must be
https://— plaintexthttp://is rejected when you save. - •Body is the raw event JSON (see the schema below).
- •Signature. Every request carries
X-Reglint-Signature: sha256=<hex>, an HMAC-SHA256 of the raw body keyed by the signing secret you set in the config. Verify it before trusting the payload.
Verify the signature (Node, Express):
import crypto from 'crypto';
import express from 'express';
const app = express();
// Use the RAW body — the signature is over the exact bytes we sent.
app.post('/reglint', express.raw({ type: 'application/json' }), (req, res) => {
const secret = process.env.REGLINT_SIGNING_SECRET;
const expected = 'sha256=' + crypto.createHmac('sha256', secret)
.update(req.body) // Buffer of the raw request body
.digest('hex');
const got = req.get('X-Reglint-Signature') || '';
const a = Buffer.from(got);
const b = Buffer.from(expected);
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
return res.status(401).end(); // reject forgeries
}
const event = JSON.parse(req.body.toString('utf8'));
// …forward to your SIEM…
res.status(200).end(); // 2xx = acknowledged
});1m → 5m → 30m → 2h → 6h — up to 8 attempts, then marks it failed. Deliveries are at-least-once; dedupe on event_id if you need exactly-once.Event schema
Every event shares a common envelope, plus fields specific to its event_type. All events are metadata only.
Common envelope (on every event):
event_type— scan_completed | hitl_decision | disposition_reportedevent_id— UUID, stable dedupe keyoccurred_at— ISO-8601 timestampcustomer_id— your Reglint account id
scan_completed — a scan finished.
{
"event_type": "scan_completed",
"scan_id": "scan_abc",
"agent_name": "support-bot",
"industry": "legal",
"channel": "gmail", // null for agent (API) traffic
"actor_type": "human", // "human" | "agent"
"actor_id": "employee@corp.com",
"final_decision": "ALERT", // PASS | ALERT | REDACT | BLOCK | ALERT_HITL
"violations_count": 1,
"violations": [
{ "violation_id": "SSN_EXPOSURE", "law": "GLBA", "type": "pii",
"severity": "high", "description": "…" }
],
"processing_time_ms": 812
}hitl_decision — a reviewer resolved a held item.
{
"event_type": "hitl_decision",
"scan_id": "scan_abc",
"agent_name": "support-bot",
"decision": "edited", // approved | rejected | edited
"reviewer_id": "usr_123",
"edited": true,
"delivery_mode": "auto", // "auto" | "consent" | null (only on edited)
"has_note": true
}disposition_reported — the final send outcome of a flagged/held item.
{
"event_type": "disposition_reported",
"scan_id": "scan_abc",
"agent_name": "support-bot",
"final_decision": "ALERT",
"disposition": "sent_edited"
// blocked_by_user | sent_redacted | sent_original_override
// | sent_on_approval | sent_edited | edit_applied
}Reglint Layer 2 Agent Monitor — Developer Docs
Back to top