Build walkthrough · Custom AI Development
Building a White-Label AI Compliance Scanner
Inside the build: a multi-tenant platform that grades website privacy compliance with an LLM, resold under an agency's own brand.
In short
We shipped this for a privacy-compliance martech platform: an agency wanted to sell website privacy-compliance monitoring under its own brand, at scale, without paying a human analyst to read every privacy policy by hand. The answer was a multi-tenant Django platform where a headless browser extracts the policy and GPT-4 grades it, with 0 human review in the scanning loop.
The problem with selling compliance monitoring by hand
Privacy-compliance monitoring is a good subscription business on paper. Every site with a cookie banner is a prospect, regulations keep shifting, and a scan that flags a missing disclosure or an out-of-date consent mechanism is easy to sell as recurring value.
The trouble is the analyst bottleneck. If a human has to open every site, read the privacy policy, cross-reference it against a checklist, and write up findings, the business caps out at however many sites one analyst can review in a day. An agency cannot resell that under its own brand at any scale worth having, because the cost structure scales linearly with customer count and the output is inconsistent between analysts.
The agency's ask was specific: a product they could put their logo on, sell to their own client list, and run without adding headcount for every hundred new sites. That meant the grading step itself had to be automated, not just the dashboard around it.
The architecture: scan, grade, brand, bill
The platform has four moving pieces that have to work together per tenant, not just per platform.
A headless browser (Selenium) visits the target site, follows the link to the privacy policy, and extracts the policy text along with the cookie-consent implementation it finds on the page. A discovery crawler runs alongside it to find pages the initial scan might miss, subdomains and forms that collect data without a visible disclosure being the usual culprits.
The extracted policy text goes to GPT-4, which grades it against a compliance rubric and returns a structured status plus a specific, actionable list of fixes, not a vague summary. The cookie-consent module checks the actual mechanism against what the policy claims it does. Scans run on a cron, so a customer's compliance status is a living number, not a one-time report.
Everything above sits behind a tenant boundary. Each agency gets its own subdomain, its own branding, its own billing relationship with its own customers, and its own re-scan schedule, all as first-class rows in the data model rather than presentation-layer tricks.
The GPT-4 grading step
The hard problem is not calling an LLM. It is getting a consistent, structured answer out of it across thousands of policies written in wildly different styles, lengths, and legal conventions, and doing it without a human checking the output.
The grading prompt is built as a constrained task, not an open-ended question. The model receives the extracted policy text, the site's detected data-collection behaviors from the crawler, and a fixed rubric. It returns a status enum (something like compliant, partial, non_compliant) plus a list of specific fixes tied to what the rubric found missing, not free-text commentary that a downstream system would have to parse loosely.
A simplified illustration of that shape. The rubric, the prompt, and the tuning behind them are the client's product, so what follows is a generic pattern rather than what shipped:
from enum import Enum
from pydantic import BaseModel
from openai import OpenAI
client = OpenAI()
class ComplianceStatus(str, Enum):
COMPLIANT = "compliant"
PARTIAL = "partial"
NON_COMPLIANT = "non_compliant"
class ComplianceFix(BaseModel):
issue: str
rule_reference: str
fix: str
class ComplianceGrade(BaseModel):
status: ComplianceStatus
fixes: list[ComplianceFix]
summary: str
GRADING_PROMPT = """
You are grading a website privacy policy against a fixed compliance rubric.
Return only findings supported by the policy text and detected site behavior
below. Do not infer intent. If a required disclosure is present, do not flag it.
RUBRIC:
{rubric}
DETECTED SITE BEHAVIOR (from crawler + cookie-consent scan):
{detected_behavior}
POLICY TEXT:
{policy_text}
"""
def grade_policy(policy_text: str, detected_behavior: str, rubric: str) -> ComplianceGrade:
response = client.beta.chat.completions.parse(
model="gpt-4",
messages=[
{"role": "system", "content": "You return structured compliance grades only."},
{"role": "user", "content": GRADING_PROMPT.format(
rubric=rubric,
detected_behavior=detected_behavior,
policy_text=policy_text,
)},
],
response_format=ComplianceGrade,
)
return response.choices[0].message.parsed
The structured output is what lets the platform run with zero human review. A status enum and a typed fix list slot straight into the tenant's dashboard, the outreach email, and the historical record used to show a customer their compliance trend over time. There is no free-text report for an analyst to interpret before a customer sees it.
What makes it actually white-label, not re-skinned
A lot of "white-label" software is one app with a logo swap in the CSS. That works until an agency's customer emails support and the reply comes from the platform's own domain, or until two agencies' customer lists show up in the same admin view because tenancy was never modeled as data, only as branding.
Genuine white-label status is a data-model decision made on day one, not a feature added later. Three things have to be first-class:
Tenant isolation. Every scan, every customer record, every billing event belongs to an agency (tenant), and the application layer enforces that boundary on every query, not just on the parts of the UI that show a logo.
Per-tenant billing. Each agency runs its own Stripe-connected billing relationship with its own customers, at its own prices, on its own trial terms. The platform is not one subscription with agencies as a reseller layer bolted on top; each agency's revenue relationship is a real, separate object in the system.
Per-tenant branding, resolved by subdomain. The routing layer resolves an agency's brand assets, domain, and customer scope from the subdomain before anything else runs, so agency-a.example.com and agency-b.example.com are functionally separate storefronts sharing one engine.
A simplified version of that routing pattern:
interface TenantContext {
tenantId: string;
brandName: string;
logoUrl: string;
primaryDomain: string;
billingPlan: "trial" | "active" | "past_due";
}
async function resolveTenant(hostname: string): Promise<TenantContext> {
const subdomain = hostname.split(".")[0];
const tenant = await db.tenant.findUnique({
where: { subdomain },
select: {
id: true,
brandName: true,
logoUrl: true,
primaryDomain: true,
billingPlan: true,
},
});
if (!tenant) {
throw new UnknownTenantError(hostname);
}
return {
tenantId: tenant.id,
brandName: tenant.brandName,
logoUrl: tenant.logoUrl,
primaryDomain: tenant.primaryDomain,
billingPlan: tenant.billingPlan,
};
}
// every scan, invoice, and outreach email query is scoped by tenantId,
// resolved once at the edge and threaded through the request context
Every downstream query, the scan record, the customer's dashboard data, the outreach email template, the Stripe subscription object, carries that tenantId. Nothing in the request path is allowed to reach across tenants. That is the difference between a resold product and a shared product with a coat of paint on it.
The trial-to-paid loop, running without a human
The cron is the part that makes this a subscription business rather than a one-time audit tool. Once a customer's site is onboarded under an agency, the platform re-scans it on a schedule, compares the new grade to the last one, and triggers automated outreach when the status changes, a new fix appears, or a previous issue is resolved.
That loop is what turns a free trial into a paid subscription without an agency's staff doing anything. A prospect signs up under an agency's branded page, gets an initial scan and grade for free, sees specific fixes tied to their actual policy, and converts to paid to get ongoing monitoring and the automated re-scan cadence. The agency never touches a single scan. Docker packages the whole stack so an agency's deployment is repeatable and the platform team can stand up infrastructure without a bespoke setup each time. All of it ships into the client's own repository and cloud account, with no license-back and nothing depending on a service we run, which is the ownership posture described on our security page.
This is the outcome as it shipped: agencies onboard under their own logo and domain, customers self-serve, monitoring runs on a cron, and trial-to-paid conversion is built into the platform rather than added afterward as a manual sales step.
Why this shape works for an agency's economics
An agency reselling compliance monitoring is really running an AI automation business layered on top of a platform it does not have to build itself. The agency's margin depends entirely on the marginal cost of adding the next customer staying near zero. A human-review workflow breaks that math immediately, every new customer is a fixed cost against a recurring revenue line. A GPT-4 grading step with a structured output and a cron-driven re-scan breaks that dependency: the marginal cost of the next customer is compute, not headcount.
This is also why the build order mattered. Tenant isolation, per-tenant billing, and subdomain branding went into the data model before the grading prompt was tuned, because retrofitting multi-tenancy onto a single-tenant app later means touching every query in the codebase. Building it as a resellable product from the schema up is what let the agency put its brand on day one rather than after a migration project. A build with that many parallel pieces, crawler, grading step, billing, tenancy, is why work like this runs as a pod with a lead and a bench rather than a single contractor working through it in sequence. For a broader look at where AI automation earns its keep in a business versus where it does not, see our breakdown of what to automate first and how automation agencies typically structure this kind of resale relationship.
The short version
A resellable compliance scanner is not a scanning script with a logo. It is a data model where tenant isolation, billing, and branding are first-class objects, an extraction pipeline (Selenium) feeding a structured grading step (GPT-4) that returns an enum and a fix list instead of prose, and a cron loop that turns a free scan into a paid subscription without a human touching a single result. Get the tenancy right in the schema before tuning the prompt, and the platform scales by adding compute, not analysts.
Frequently asked questions
- How does the platform grade a privacy policy without a human reading it?
- A headless browser extracts the policy text and the site's actual cookie-consent behavior, then GPT-4 grades that text against a fixed compliance rubric and returns a structured status (compliant, partial, non-compliant) plus a specific list of fixes. The structured output, not free text, is what lets the result flow straight into a dashboard and an outreach email with zero human review in the loop.
- What actually makes a platform white-label instead of just re-skinned?
- Tenant isolation, per-tenant billing, and per-tenant branding have to be first-class parts of the data model, not a logo swap in the front end. Every scan, customer record, and billing event is scoped to a tenant ID resolved from the agency's subdomain, so two agencies never share a customer list or a support inbox by accident.
- Does this kind of build fit a Builder Pod or a Growth Pod?
- A platform with this many concurrent pieces, headless browsing, an LLM grading step, multi-tenant billing, and a cron-driven outreach loop, typically needs two build tracks running in parallel, which is the shape of a [Growth Pod](/pods) at $10,000 a month. A narrower first version (single-tenant scanning and grading before multi-tenancy) can start on a Builder Pod at $5,000 a month and expand once the core grading loop is proven.
- Is the compliance grading itself legally binding or a compliance certification?
- No. The platform grades a policy against a rubric and flags fixes, it does not constitute legal advice or a certification that a site is compliant with any specific regulation. Agencies reselling it position it as monitoring and a remediation guide, not a legal opinion, which is also why the fix list is specific rather than a bare pass or fail.
- How do you handle the AI code quality on a build with this much automated decision-making?
- The same way we handle every build: every change is a pull request in the client's own repository, reviewed by the named engineer who owns it, with typed contracts and tests running in CI. Our [security page](/security) covers the broader posture, including that we never train models on client data and everything ships into the client's own cloud account from week one.