FORMA — AI agent compliance SDK. Zero-config tracking, EU AI Act/DPDP/RBI compliance, cryptographic audit trails.
Project description
FORMA SDK — v2.3.0
Make non-compliance impossible — in one line of code.
FORMA doesn't just record what your AI did; it blocks non-compliant decisions before they execute. Add enforce=[...] and PII leaks, prompt injections, and policy violations are stopped at runtime — then every decision is HMAC-signed and mapped to RBI, DPDP, EU AI Act, and ISO 42001.
Install
pip install forma-sdk
Import name is trustlayer:
import trustlayer as tl
Quickstart — runtime enforcement (zero-touch)
import trustlayer as tl
# One call. Enforcement is process-wide on every LLM/tool call — no decorators,
# no context managers, no edits inside your business logic.
tl.init(
api_key="tl_live_YOUR_KEY", # from formaai.in → Settings
human_sponsor="ops@company.com",
enforce=["rbi_ml_risk", "dpdp"], # ← blocks violations BEFORE they run
)
# Prove enforcement is live — 4 adversarial probes, no network:
result = tl.verify()
assert result["verified"], f"Gate not working: {result['summary']}"
# Your existing code is unchanged.
result = run_underwriting_model(application)
Now, before any LLM or tool call executes:
- An Aadhaar / PAN / GSTIN / IFSC / Indian Passport / card number → blocked (DPDP)
- "Ignore previous instructions…" / jailbreaks → blocked
- "Auto-approve without review" → blocked (RBI human-review rule)
A blocked action raises ComplianceViolation. The gate runs locally in < 1 ms — no network hop. Tool calls get a 1.25× threat multiplier; dangerous tool names (exec, shell, rm, delete, drop) add a further +0.35.
Init-time validation:
enforce=["dpdpp"](typo) raisesValueErrorimmediately with a link to the docs — misconfigurations are caught before any traffic flows.
Multiple agents — tl.register() / agents= (still zero edits)
Map your existing functions to agents without touching their bodies:
import trustlayer as tl
from my_app import approve_loan, validate_kyc, detect_fraud
tl.init(
api_key="tl_live_YOUR_KEY",
agents={
"kyc-validator": validate_kyc, # bare callable
"loan-approval": {"fn": approve_loan, "enforce": ["rbi_ml_risk", "dpdp"],
"risk_level": "HIGH"},
"fraud-detector": {"fn": detect_fraud, "enforce": ["dpdp"]},
},
)
# Or register after init (decorator form also works):
tl.register("loan-approval", approve_loan, enforce=["rbi_ml_risk"], risk_level="HIGH")
# Call them exactly as before — each governed and attributed independently.
result = approve_loan(application)
from trustlayer import ComplianceViolation
try:
result = approve_loan(application)
except ComplianceViolation as e:
print(e.reason) # "PII detected in LLM prompt: Aadhaar number. ..."
Observability API (v2.3.0)
Three functions let you inspect the in-process gate from health checks, startup scripts, or unit tests — no network calls needed.
tl.verify() — Prove enforcement is active
Runs 4 adversarial self-test probes against the local gate. Use at startup to confirm the gate is wired before any real traffic flows.
tl.init(api_key="tl_live_...", enforce=["dpdp"])
result = tl.verify()
# → {verified: True, probes_passed: 4, probes_total: 4, summary: "4/4 probes passed — gate is active"}
# Probes (all local — no network):
# 1. Aadhaar PII → must block
# 2. Indian PAN → must block
# 3. Canonical jailbreak → must block
# 4. Clean benign prompt → must allow
# 5. Unauthorized tool (if authorized_actions set) → must block
tl.status() — Real-time enforcement state
Returns a live snapshot of the gate — decision counts, top blocked rules, circuit-breaker state:
s = tl.status()
# → {
# "version": "2.3.0",
# "enforcement_active": True,
# "decisions_total": 1847,
# "decisions_blocked": 23,
# "decisions_warned": 4,
# "decisions_allowed": 1820,
# "top_rule_hits": {"pii_in_prompt": 18, "threat_prompt_injection": 5},
# "circuit_breaker_open": False,
# "kill_switch_active": False,
# "last_policy_sync": "2026-06-17T10:15:32Z",
# ...
# }
tl.preview() — Dry-run gate check
Simulate what the gate would decide for any prompt — no side effects, no ComplianceViolation, no audit log entry:
r = tl.preview("My Aadhaar is 1234 5678 9012")
# → {"decision": "block", "rule_id": "pii_in_prompt", "reason": "PII detected: Aadhaar number..."}
r = tl.preview("What is the loan status?")
# → {"decision": "allow", "rule_id": None, "reason": None}
# Test a tool call (higher threat multiplier):
r = tl.preview("drop tables", action_type="tool_call", tool_name="exec_sql")
# → {"decision": "block", ...}
trustlayer verify-decisions — Tamper-evident audit CLI
Every gate decision is HMAC-SHA256 signed before buffering. This CLI command fetches the log and verifies every signature:
trustlayer verify-decisions
# ✓ 47 decisions verified (0 tampered, 0 unsigned)
# Blocked: 8 | Warned: 3 | Allowed: 36
# Top rule: pii_aadhaar (5 hits)
trustlayer verify-decisions --agent loan-approval-agent --limit 500
# exits 1 if any decision fails verification — wire into CI
Zero-config tracking (no enforcement)
import trustlayer as tl
tl.init(api_key="tl_live_YOUR_KEY")
# Every OpenAI / Anthropic / LangChain / LiteLLM call is auto-captured —
# tokens, cost, latency, anomaly score — with no other code changes.
Human approvals (EU AI Act Article 14 / RBI human review)
tl.init(
api_key="tl_live_YOUR_KEY",
require_approval_when=lambda ctx: ctx.get("amount", 0) > 1_000_000,
approval_message="Loan above ₹10L requires human review.",
)
result = approve_loan(application) # pauses for sign-off on high-stakes calls
Policy packs
| Pack | Region | Enforces |
|---|---|---|
dpdp |
India | Aadhaar / PAN / GSTIN / IFSC / Passport / card / phone / DoB blocked; consent-bypass blocked |
rbi_ml_risk |
India Banking | auto-approval-without-review blocked; fund-disbursal routed to approval |
eu_ai_act |
EU | human-oversight bypass (Art. 14) & logging suppression (Art. 12) blocked |
iso42001 |
Global | concealing AI involvement blocked |
PII patterns (17 — India + global)
Aadhaar · PAN · GSTIN (15-char) · IFSC code · Indian Passport · Driving License · Date of Birth (with context) · Visa card · Mastercard · Amex · CVV · phone · email · SSN · generic credit card · IBAN · passport (generic)
Kill switch
Pass kill_switch=True to tl.init(). When you trigger a kill from the dashboard, the next LLM/tool call raises KillSwitchTriggered in < 100 ms.
CI/CD compliance gate
trustlayer gate --pre-deploy --fail-below 80
trustlayer verify-decisions --limit 500 # tamper check in CI
Production reliability (v2.3.0)
| Feature | Behaviour |
|---|---|
| Policy sync circuit breaker | Stops retry storms after 5 consecutive server failures; auto-resets after 5 min. Gate stays up using the last known policy. |
| Disk-backed decision buffer | Unflushed decisions are persisted to ~/.forma/pending_decisions.jsonl on flush failure and replayed on next startup — no audit data lost on transient outages. |
| HMAC-signed entries | Every buffered gate decision is signed with your API key before queuing — tamper-detectable by verify-decisions CLI or cache.verify_log(). |
tl.init() parameters (all 25)
| Parameter | Description |
|---|---|
api_key |
FORMA API key (or FORMA_API_KEY env). |
api_url |
Backend URL override. |
agent_name |
Display name for ambient auto-captured runs. |
human_sponsor |
Accountable human on the audit record. |
auto_capture (True) |
Auto-patch OpenAI/Anthropic/LiteLLM/LangChain. |
kill_switch (False) |
Start global process-level kill-switch watcher. |
gate (True) |
Pre-check every auto-captured call through the compliance gate. |
compliance |
Frameworks for scoring/reports (EU_AI_ACT, DPDP, RBI_MRM, ISO_42001). |
ambient_runs (True) |
Create signed runs for auto-captured calls. |
enforce |
Policy packs blocked locally (dpdp, rbi_ml_risk, eu_ai_act, iso42001). Typos raise ValueError at init time. |
agents |
Zero-edit multi-agent map. {"name": fn} or {"name": {"fn": fn, "enforce": [...], ...}}. |
purpose |
Plain-English purpose stored in the identity passport. |
risk_level ("MEDIUM") |
LOW | MEDIUM | HIGH | CRITICAL. |
authorized_actions |
Allow-list of tool names; gate blocks others. |
drift_threshold (0.15) |
Behavioural drift threshold. |
max_cost_usd |
Hard per-run cost cap. |
require_approval_when |
Predicate ctx→bool; True pauses for human approval. |
approval_message / approval_title |
Text in the Approvals inbox. |
approval_timeout (3600) |
Seconds to wait for a decision. |
approval_poll_interval (5) |
Seconds between inbox polls. |
approval_via ("forma") |
Approval channel. |
timeout (10) |
HTTP timeout seconds. |
max_retries (2) |
Transport retry attempts. |
fail_closed (False) |
Block when the gate is unreachable (default: fail open). |
tl.register(name, fn, **cfg) — the second entry point
Binds one existing function to a governed agent. Works as a decorator too. Accepts the same full governance argument set as init(agents={...}) per-agent config (unknown keyword → TypeError).
When to use which
| Use… | When |
|---|---|
tl.init(agents={...}) |
All agent functions importable at init() call. Simplest. |
tl.register(name, fn, ...) |
Function defined/imported after init(), decorator form, or dynamic registration. |
Node.js / TypeScript
Coming soon. Runtime enforcement (
enforce) and approvals are Python-only today.
Dashboard & docs
- Dashboard: formaai.in
- Developer guide: formaai.in/developer-guide
- Snippet generator: formaai.in/snippet-generator
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file forma_sdk-2.4.0.tar.gz.
File metadata
- Download URL: forma_sdk-2.4.0.tar.gz
- Upload date:
- Size: 155.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1a38d3a76af587ef70b8e48318cd1acf3dd26525af646edaf82dbd88c365b531
|
|
| MD5 |
b190950a8c35d68190515d7e5f73dde1
|
|
| BLAKE2b-256 |
584e7ce504b71c9bfaf0f72507765d10021153cb7e31dbe90c60560702e56f10
|
File details
Details for the file forma_sdk-2.4.0-py3-none-any.whl.
File metadata
- Download URL: forma_sdk-2.4.0-py3-none-any.whl
- Upload date:
- Size: 94.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8dfa35504736f9a5a37744846be591e0a06833dac64804c960662010fbc9bc47
|
|
| MD5 |
025f60bd433bba973cd464e4bc1f1c7d
|
|
| BLAKE2b-256 |
aee357c1e1a24a8b1153ba106cf997438daaf0bc9924239349cf96b0bbb5653d
|