Skip to main content

FORMA — AI agent compliance SDK. Zero-config tracking, EU AI Act/DPDP/RBI compliance, cryptographic audit trails.

Project description

FORMA SDK

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 cryptographically signed and mapped to RBI, DPDP, EU AI Act, and ISO 42001.

License: MIT Python 3.8+


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 forma.2bd.net → Settings
    human_sponsor="ops@company.com",
    enforce=["rbi_ml_risk", "dpdp"],   # ← blocks violations BEFORE they run
)

# Your existing code is unchanged.
result = run_underwriting_model(application)

Now, before any LLM or tool call executes:

  • An Aadhaar / PAN / card number in the prompt → blocked (DPDP)
  • "Ignore previous instructions…" / jailbreaks → blocked
  • "Auto-approve without review" → blocked (RBI human-review rule)

A blocked action raises ComplianceViolation, and every decision (allow / warn / block) lands in your signed audit trail. The gate runs locally in ~1 ms — no network hop in your request path.

Multiple agents — tl.register() / agents= (still zero edits)

Map your existing functions to agents without touching their bodies. Each gets its own discrete signed run plus its own enforce / risk_level / compliance / approval config:

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"},                              # per-agent config
        "fraud-detector": {"fn": detect_fraud, "enforce": ["dpdp"]},
    },
)

# Equivalent if you register after init:
tl.register("loan-approval", approve_loan, enforce=["rbi_ml_risk"], risk_level="HIGH")

# Call them exactly as before — each is governed and attributed independently.
result = approve_loan(application)

register / agents= work for sync and async def functions and stay correct under 20+ concurrent agents (scope is tracked with contextvars, so threads and asyncio tasks never cross-attribute). They must run before the target is called (top of your entrypoint).

from trustlayer import ComplianceViolation

try:
    result = approve_loan(application)
except ComplianceViolation as e:
    print(e.reason)   # "PII detected in LLM prompt: Aadhaar number. ..."

Zero-config tracking (no enforcement)

import trustlayer as tl
tl.init(api_key="tl_live_YOUR_KEY")

# Every OpenAI / Anthropic / LangChain / LiteLLM call is now auto-captured —
# tokens, cost, latency, anomaly score — with no other code changes.

Human approvals (EU AI Act Article 14 / RBI human review)

import trustlayer as tl

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.",
)

# Your existing function runs unchanged — high-stakes calls pause for sign-off.
result = approve_loan(application)

The decision pauses in your FORMA Approvals inbox until a human approves or rejects. Fail-closed: a timeout or unreachable API is treated as a denial — a skipped review never silently passes.


Policy packs

Pack Region Enforces
dpdp India Aadhaar / PAN / card / phone blocked from prompts & tool args; 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; PII protection
iso42001 Global concealing AI involvement blocked

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 under ~100 ms.

CI/CD compliance gate

# Blocks the deploy (exit 1) if any agent is below the threshold
trustlayer gate --pre-deploy --fail-below 80

tl.init() parameters (all 24)

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 so every LLM call is captured with no code edits.
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 real signed runs for auto-captured calls.
enforce Policy packs blocked locally pre-execution (dpdp, rbi_ml_risk, eu_ai_act, iso42001).
agents Zero-edit multi-agent map. {"name": fn} or {"name": {"fn": fn, "enforce": [...], "risk_level": "HIGH", ...}}.
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 for the passport.
max_cost_usd Hard per-run cost cap; over-budget runs marked failed.
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 fails open).

tl.register(name, fn, **cfg) — the second entry point

FORMA's public API is exactly two calls: tl.init() and tl.register().

tl.register() binds one existing function to a governed agent with no code edits. It re-points the function's name in its defining module to a governed wrapper (and also works as a decorator @tl.register(...)). agents={...} on tl.init() does the same for a whole map at once. Both support sync + async def.

tl.register("loan-approval", approve_loan, enforce=["rbi_ml_risk"], risk_level="HIGH")
# decorator form:
@tl.register("loan-approval", enforce=["rbi_ml_risk"])
def approve_loan(application): ...

When to use tl.init(agents={...}) vs tl.register()

Use… When
tl.init(agents={...}) All agent functions are importable at the single init() call (top of your entrypoint). Simplest — one block governs everything.
tl.register(name, fn, ...) A function is imported/defined after init(), you want the decorator form @tl.register(...), or you need conditional / dynamic registration.

tl.register() parameters (full parity with init's per-agent config)

tl.register() accepts the same governance arguments as a tl.init(agents={...}) per-agent config dict (unknown keyword → TypeError):

Parameter Description
name Agent name (positional).
fn The function to govern (positional; omit for the @tl.register(...) decorator form).
enforce Policy packs blocked locally pre-execution (dpdp, rbi_ml_risk, eu_ai_act, iso42001).
compliance Frameworks for scoring/reports (EU_AI_ACT, DPDP, RBI_MRM, ISO_42001).
risk_level ("MEDIUM") LOW | MEDIUM | HIGH | CRITICAL.
human_sponsor Accountable human on the audit record.
purpose Plain-English purpose stored in the agent's identity passport.
authorized_actions Allow-list of tool names; the gate blocks others.
max_cost_usd Hard per-run cost cap; over-budget runs marked failed.
kill_switch (False) Start a per-agent kill-switch watcher; a kill halts this agent's next call.
drift_threshold (0.15) Behavioural drift threshold stored on the agent's passport.
require_approval_when Predicate ctx→bool; True pauses for human approval.
approval_message / approval_title Text shown 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.
version Agent version label.

Node.js / TypeScript

npm install forma-sdk
import * as forma from "forma-sdk";

forma.init({ apiKey: "tl_live_YOUR_KEY", humanSponsor: "ops@company.com" });

const { decision } = await forma.gate("agent-id", {
    actionType: "llm_call",
    prompt: userPrompt,
});

Note: The Node SDK is coming soon (not yet published to npm). Runtime enforcement (enforce) and approvals are Python-only today. The Node package will provide init + gate first; enforcement parity is on the roadmap.


Dashboard & docs

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

forma_sdk-2.2.0.tar.gz (59.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

forma_sdk-2.2.0-py3-none-any.whl (58.7 kB view details)

Uploaded Python 3

File details

Details for the file forma_sdk-2.2.0.tar.gz.

File metadata

  • Download URL: forma_sdk-2.2.0.tar.gz
  • Upload date:
  • Size: 59.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for forma_sdk-2.2.0.tar.gz
Algorithm Hash digest
SHA256 b7c28bbd0a1098929b45e01c0de182e62881541766da5136cb05db6190061ff9
MD5 94ee083daae430620825c428a618968a
BLAKE2b-256 dc94f58920111b3bcef75773e9e1f6461fd973c82a4169006b6532a31473b445

See more details on using hashes here.

File details

Details for the file forma_sdk-2.2.0-py3-none-any.whl.

File metadata

  • Download URL: forma_sdk-2.2.0-py3-none-any.whl
  • Upload date:
  • Size: 58.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for forma_sdk-2.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4f09bac7e1b1bf3e471ba9d0c0df968b4045e024d0d25143bc9049f9a12a47d2
MD5 0a4ce67857ebb32010c3755f6ff298ae
BLAKE2b-256 7b3440dcdb075204ed3e4476681ee3d557cb99661d102e59d371879497f43c74

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page