Software & AI Products

Guardrails for your product with one base URL change.

Software and AI product companies have to offer their enterprise customers a guardrail, evidence and approval layer. Few want to write one from scratch. Thulpar runs in front of the model as an OpenAI-compatible gateway, in front of tool servers as an MCP proxy, and is called from inside the application through the check API. It is multi-tenant. Every customer gets its own policy pack, ledger and evidence pack. The only things that change in the code are the base URL and an API key.

Policy template

eu-ai-act-high-risk

Recommended install

Managed private instance, Kubernetes or on-premise in the customer’s environment. Multi-tenant. The Python SDK.

Surfaces
OpenAI-compatible gatewayMCP proxyCheck API
Regulatory basis
  • EU AI Act Art. 50, Annex III (provider obligations)
  • ISO/IEC 42001 · SOC 2 evidence requirements
  • KVKK / GDPR (as processor)
Policy template

Policy per customer

A bank customer and a retail customer want different rules. Policy inheritance is needed.

Watch the runs →
Runs

The scenarios below are derived from the product’s real rules.

Every scenario is an agent run written to the product’s real rules. It shows the stage, the rails, the decision, the finding, the approval and the ledger entry step by step.

4 scenarios →
Software & AI Products

What comes up in practice

Policy per customer

A bank customer and a retail customer want different rules. Policy inheritance is needed.

Evidence as a sales blocker

Enterprise buyers ask for an audit trail and evidence packs. The product ends up carrying them alone.

Closed-circuit demands

Some customers want the product in their own data centre. The guardrail has to come along.

Runs

4 scenarios

The player opens on the flagship scenario. Pick the others below.

One product, two tenants: same request, different decisions · Customer-support AI (SaaS, private instance)gatewayeu-ai-act-high-riskstandart
Decision trailSupport Agent · llama-3.3-70b · vLLM · managed private instance
U
01inputuser
The same prompt from two tenants: “Refund 2,400 TRY to customer 4471, notify by e-mail.” Key → tenant → pack.
A
02tool_callagent
tnt_banka: orders:refund {amount: 2400, currency: "TRY"}; the bank child pack’s four-eyes threshold: 1,000.
A
03tool_callagent
tnt_perakende: the same orders:refund call; the retail child pack’s threshold: 5,000 → permit, no approval.
A
04tool_callagent
tnt_banka: mail:send with the refund confirmation; the customer’s IBAN in the body.
A
05tool_callagent
tnt_perakende: mail:send with the same body; the retail pack masks and sends.
R
06retrievalretrieval
kb:search returns only from the tenant’s own collection; the cross-tenant canary document never appears.
M
07outputmodel
Two answers, two ledgers: each tenant’s own hash chain and evidence pack; the product changed only a base URL.
A
08memory_writeagent
Each tenant writes to its own memory store; provenance required, a mismatched tenant label is refused.
Thulpar · Rails

thulpar-gateway in front of the product’s model; bank and retail tenants get different decisions on one request.

crm:lookuporders:refundmail:sendkb:search
Controls: GR-TEN-01 · GR-TOOL-02 · GR-IFC-01 · GR-PII-01 · GR-GOV-01
Evidence ledger0000…0000
Simulation · runs in your browser · no request leaves the pageadded latency: 0 ms · 8 steps · SHA-256 chain
Controls exercised in these scenarios

17 GR-*

idcontrolOWASPrails
GR-TEN-01Tenant isolation across retrieval, credentials, memory, logs + canary testsLLM08, LLM02 / ASI03, ASI06 / MCP10
GR-TOOL-02Durable human approval on high-impact actions, four eyesLLM06 / ASI02, ASI09labels.sink
GR-IFC-01Information-flow labels (integrity, confidentiality, tenant, PII class) enforced at sensitive sinksLLM02 / ASI01, ASI03 / MCP10labels.sink, pii.detect
GR-PII-01PII and special-category detection + masking (TCKN, IBAN, phone, health) on input/tool/output/logLLM02 / — / MCP10pii.detect, pii.redact, file.metadata_pii
GR-GOV-01Versioned, signed policy packs; ISO 42001 / Annex IV / BDDK / DORA evidence export—
GR-OUT-01Output handling: no raw HTML, code sandbox, schema validationLLM05 / ASI05 / MCP05code, schema, regex, secrets, file.analyze, file.type, file.active_content, yara
GR-SYS-01System-prompt leak + canaryLLM07 / ASI01system_prompt.leak
GR-INJ-01Direct injection and jailbreak at the gate (TR+EN)LLM01 / ASI01 / MCP06injection.direct, jailbreak
GR-TOOL-05SQL / command / path traversal / RFI / XSS injection in tool arguments (libinjection + OWASP CRS)LLM05 / ASI02, ASI05 / MCP05tool.args.injection
GR-LOG-01Tamper-evident event log (model/tool/policy/approval/hit), ≥ 6 months, auditor export— / — / MCP08
GR-TRANS-01AI disclosure: chat + voice— / ASI09conversation
GR-CONT-01Content-harm policy (AILuminate 12 + TR) with tenant thresholdsLLM09 / ASI09content.input, content.output, toxicity, topic, groundedness, language, image.content_safety, banlist, competitors
GR-TOOL-01Tool-call privilege policy (default deny)LLM06 / ASI02, ASI03 / MCP02tool.authz, tool.args
GR-TOOL-03Tool schema pinning / diff / quarantine (rug-pull)LLM03 / ASI04 / MCP03, MCP04tool.schema_pin
GR-TOOL-04Tool description hygieneLLM03 / ASI04 / MCP03
GR-RES-01Per-run rate/cost/loop limits, circuit breakerLLM10 / ASI08budget
GR-INJ-02Indirect injection from tool/RAG output: untrusted label, no new tool call without policyLLM01, LLM08 / ASI01, ASI06 / MCP06, MCP10injection.indirect, file.hidden_text

The full catalogue and evidence packs →

See it in your own environment.

A one-hour technical demo: your scenario, your policy pack, on a closed-circuit install. Then the install kit and a trial licence for a pilot.