Skip to navigation

Python SDK Reference

Package: mima-governance · Version: 0.3.x · Python: 3.9+

pip install mima-governance # core
pip install "mima-governance[otel]" # + OpenTelemetry guard
pip install "mima-governance[all]" # + otel + langchain + llamaindex + autogen

Client setup

from mima_governance import MimaGovernance, AuthorisedBy
mima = MimaGovernance(
api_key="mima_ext_...", # required
system_name="my-ai-pipeline", # required — matches mima.attest() system_name
workspace_id=None, # resolved automatically from API key
base_url="https://api.mima.works", # override for self-hosted deployments
agent_name=None, # defaults to system_name
signing_key=None, # 32-byte hex key for HMAC-SHA256 GRC signing
authorised_by=AuthorisedBy( # default principal for all attestations
identity="alice@example.com",
role="ml-engineer",
),
on_error="warn", # "warn" | "raise" | "silent"
batch_flush_interval=30.0, # seconds
batch_max_size=100,
)

Environment variables

VariablePurpose
MIMA_API_KEYAlternative to passing api_key=
MIMA_WORKSPACE_IDAlternative to passing workspace_id=
MIMA_BASE_URLAlternative to passing base_url=

Attestation

@mima.attest() — decorator

Wraps any function. Records input hash, output hash, and execution time.

@mima.attest(tool_name="classify_document", model_id="claude-opus-4-6")
def classify(document: str) -> str:
return llm.complete(document)

Parameters

ParameterTypeDefaultDescription
tool_namestrrequiredName of the tool / action
modestr"sync""sync" pushes immediately; "batch" buffers
model_idstrNoneLLM model identifier
authorised_byAuthorisedByclient defaultOverride for this call
approval_tokentokenNoneToken from require_approval()

Works with async functions:

@mima.attest(tool_name="generate_summary")
async def summarise(text: str) -> str:
return await async_llm.complete(text)

mima.push() — explicit attestation

Use when you already have input/output hashes (e.g. from a pipeline step).

import hashlib
input_hash = hashlib.sha256(json.dumps(payload).encode()).hexdigest()
output_hash = hashlib.sha256(json.dumps(result).encode()).hexdigest()
result = mima.push(
"generate_report",
input_hash,
output_hash,
model_id="claude-opus-4-6",
)

mima.trace() — context manager

Capture hashes manually within the with block.

with mima.trace("run_pipeline") as t:
t.set_input(input_docs)
output = pipeline.run(input_docs)
t.set_output(output)
t.set_model_id("gpt-4o")

mima.batch() — buffered bulk push

with mima.batch() as b:
for item in work_queue:
result = process(item)
b.add("process_item", input=item, output=result)
# Flushes on exit — single batch API call.

Pre-approval gates

Block an AI action until a GRC manager approves it in the dashboard.

from mima_governance.approvals import ApprovalDenied, ApprovalTimeout
try:
token = mima.require_approval(
action_type="high_risk_decision",
context={"affected_users": 1200, "policy": "credit_v3"},
timeout_seconds=300,
approver="bob@example.com",
on_timeout="raise",
)
except ApprovalDenied:
return {"status": "rejected"}
# Use the token to link attestation to the approval record.
@mima.attest(tool_name="credit_decision", approval_token=token)
def make_credit_decision(application):
return model.predict(application)

When token is an ApprovalToken, the decorator also pushes a human_oversight GRC record with oversight_status='approved', earning EUAIA_ART14.

Do not call require_approval() inside a web request handler — it holds the connection for up to timeout_seconds. Gate job submission instead.


GRC evidence methods

All 11 methods push to POST /api/workspaces/{ws}/governance/grc/evidence and return a GrcResult:

@dataclass
class GrcResult:
record_id: str # "" on failure
record_type: str
mapped_controls: list # e.g. ['EUAIA_ART9', 'ISO42001_6_1']
detail: str # "ok" on success, error message on failure

mima.works_risk_assessment()

Records an AI system risk classification under EU AI Act Art. 9.

mima.works_risk_assessment(
system_name="loan-scorer",
risk_tier="high",
use_case="Automated credit scoring for consumer loans",
intended_purpose="Score loan applications and surface them for human review",
impact_domains=["credit", "consumer_finance"],
art5_self_assessment=True, # certifies no Art.5 prohibited practices
assessor="alice@example.com",
annex_iii_category="essential_services", # required for high-risk
environment="production",
system_version="v2.1.0",
technical_doc_url="https://docs.internal/loan-scorer/annex-iv",
)

art5_self_assessment=True certifies the system does not engage in any Art. 5 prohibited practices. Never set without explicit human confirmation.

annex_iii_category must be one of: biometric_identification, critical_infrastructure, education_vocational, employment_management, essential_services, law_enforcement, migration_border, justice_democratic, not_annex_iii


mima.model_evaluation()

mima.model_evaluation(
model_id="loan-scorer-v2.1",
dataset="holdout-q2-2026",
accuracy=0.94,
evaluated_by="alice@example.com",
evaluation_type="quarterly", # "initial" | "quarterly" | "triggered"
bias_metrics={"demographic_parity": 0.02, "equal_opportunity": 0.01},
robustness_score=0.91,
passed_threshold=True,
)

mima.human_oversight()

mima.human_oversight(
decision_id="loan-app-48291",
ai_recommendation="approve",
human_decision="reject",
reviewer="bob@example.com",
rationale="Application flagged for fraud indicators not in model training data",
model_id="loan-scorer-v2.1",
)
# override=True is inferred automatically (ai_recommendation != human_decision)

mima.training_data_governance()

mima.training_data_governance(
model_id="loan-scorer-v2.1",
dataset_id="training-set-2026-q1",
record_count=2_400_000,
bias_checks_performed=True,
approved_by="data-governance@example.com",
data_sources=["internal_originations", "credit_bureau_x"],
data_categories=["financial_history", "demographics"],
known_limitations="Underrepresented: self-employed applicants pre-2020",
)

mima.incident_report()

mima.incident_report(
title="Model output hallucination on edge case inputs",
severity="high", # "critical" | "high" | "medium" | "low"
description="Model returned invalid IBAN numbers for 3 users on 2026-06-01",
affected_systems=["payment-processor-ai"],
detected_at="2026-06-01T14:22:00Z",
authority_notified_at="2026-06-01T18:00:00Z",
)

mima.access_review()

mima.access_review(
user="contractor@external.com",
resource="model-training-pipeline",
granted=False,
reviewed_by="alice@example.com",
review_type="periodic",
reason="Contractor engagement ended 2026-05-31",
)

mima.change_event()

mima.change_event(
type="prompt_update",
by="alice@example.com",
description="Updated system prompt to add output format constraints",
environment="production",
system="customer-support-ai",
change_id="CHG-4821",
)

mima.vendor_risk()

mima.vendor_risk(
vendor="OpenAI",
tier="high", # "critical" | "high" | "medium" | "low"
last_reviewed="2026-06-01",
findings=2,
contacts=["security@openai.com"],
)

mima.policy_acknowledged()

mima.policy_acknowledged(
policy="AI Use Policy",
user="alice@example.com",
version="v3.1.0",
acknowledgment_type="initial", # "initial" | "renewal" | "update"
policy_url="https://internal.example.com/policies/ai-use/v3.1.0",
channel="in-app",
)

mima.model_drift_event()

mima.model_drift_event(
model_id="loan-scorer-v2.1",
metric="f1_score",
baseline=0.94,
current=0.88,
threshold=0.90,
drift_type="performance", # "performance" | "data" | "concept"
detected_by="monitoring-agent",
action_taken="Model retraining scheduled for 2026-07-01",
)

mima.governance_review()

mima.governance_review(
reviewed_by="ciso@example.com",
report_type="quarterly",
frameworks_reviewed=["EU_AI_ACT", "ISO_42001", "SOC2"],
overall_readiness=78,
action_items=4,
notes="Three open gaps in Art.9 documentation. Drift monitoring not yet wired.",
)

Async client

from mima_governance.async_client import AsyncMimaGovernance
mima = AsyncMimaGovernance(
api_key="mima_ext_...",
system_name="async-pipeline",
)
@mima.attest(tool_name="generate")
async def generate(prompt: str) -> str:
return await llm.complete(prompt)
# GRC methods are also async:
await mima.works_risk_assessment(
system_name="async-pipeline",
risk_tier="limited",
...
)

Signing GRC records

Pass a 32-byte hex key to enable HMAC-SHA256 record signing:

import secrets
# Generate once and store in secrets manager:
signing_key = secrets.token_hex(32)
mima = MimaGovernance(
api_key="mima_ext_...",
system_name="my-system",
signing_key=signing_key,
)

Every GRC push includes client_sig and client_sig_algo: "hmac-sha256". Auditors can verify signatures using the canonical message format (see api-reference.md).


Framework integrations

LangChain

from mima_governance.integrations.langchain_callback import MimaLangChainCallback
handler = MimaLangChainCallback(mima)
chain.invoke({"question": "..."}, config={"callbacks": [handler]})

LlamaIndex

from mima_governance.integrations.llamaindex_handler import MimaLlamaIndexHandler
Settings.callback_manager.add_handler(MimaLlamaIndexHandler(mima))

AutoGen

from mima_governance.integrations.autogen_middleware import MimaAutoGenMiddleware
middleware = MimaAutoGenMiddleware(mima, agent_name="assistant")
# Pass as a message hook when building your ConversableAgent reply chain.

Error handling

Error modes

on_errorBehaviour
"warn" (default)Logs to stderr with warnings.warn, returns empty result (record_id="")
"raise"Raises MimaAttestationError
"silent"Swallows errors entirely, returns empty result

Catching errors

from mima_governance import MimaGovernance, MimaAttestationError
mima = MimaGovernance(api_key="...", system_name="...", on_error="raise")
try:
mima.push("tool", input_hash, output_hash)
except MimaAttestationError as e:
logger.error("Governance record failed: %s", e)

Detecting failure without raising

result = mima.push("tool", input_hash, output_hash)
if not result.record_id:
logger.warning("Push failed: %s", result.detail)

The pattern is the same for all GRC methods — result.record_id == "" means failure.

Exception hierarchy

MimaGovernanceError # base class for all SDK exceptions
├── MimaAttestationError # attestation/GRC push failures (network, auth, validation)
├── ApprovalDenied # human rejected the approval request
├── ApprovalTimeout # no decision within timeout_seconds
└── ApprovalCancelled # requester cancelled the approval

Approval exceptions

from mima_governance.approvals import ApprovalDenied, ApprovalTimeout, ApprovalCancelled
try:
token = mima.require_approval(
action_type="deploy_model",
description="Deploy fraud-detection v2.1 to production",
timeout_seconds=300,
on_timeout="raise",
)
except ApprovalDenied as e:
# e.approval_id, e.rejected_by, e.reason
logger.error("Blocked by %s: %s", e.rejected_by, e.reason)
except ApprovalTimeout as e:
# e.approval_id, e.timeout_seconds
logger.warning("No response in %ds — retry later", e.timeout_seconds)
except ApprovalCancelled as e:
# e.approval_id
logger.info("Approval %s was cancelled", e.approval_id)

ApprovalToken vs TimeoutToken

Token typeReturned whenEarns human-oversight controlsSingle-use
ApprovalTokenHuman clicks ApproveYes (EUAIA_ART14, ISO42001_9_1)Yes — ValueError on second use
TimeoutTokenon_timeout="warn" and timeout elapsesNo — produces oversight_status='timeout_unblocked'No
token = mima.require_approval(..., on_timeout="warn")
if isinstance(token, ApprovalToken):
# Human approved — safe to proceed, earns compliance controls
mima.attest(approval_token=token)
elif isinstance(token, TimeoutToken):
# Timed out — proceeding without human sign-off
# Record is created but with degraded compliance status
mima.attest(approval_token=token)

Network and rate limits

ScenarioBehaviour
Network timeout15 s hardcoded; triggers error mode
HTTP 429 (rate limit)Retries after Retry-After header; limit is 2000 req/min
HTTP 401/403Invalid or expired API key; triggers error mode
HTTP 5xxServer error; triggers error mode (no automatic retry)

Workspace ID resolution

If you omit workspace_id, the SDK resolves it from your API key on first call. If resolution fails:

MimaAttestationError: workspace_id not set and could not be resolved automatically

Fix: pass workspace_id explicitly or set MIMA_WORKSPACE_ID.

Signing key dependency

GRC record signing requires pynacl:

pip install mima-governance[otel] # includes pynacl
# or directly:
pip install pynacl

If signing_key is set but pynacl is not installed, the first push raises ImportError.

Batch flush on shutdown

Call mima.shutdown() (or await mima.shutdown() for the async client) before process exit. Unflushed batch records are lost if the process terminates without shutdown.


Type reference

Result types

@dataclass
class AttestationResult:
attestation_id: str # unique ID, empty string on failure
external_verified: bool
trust_tier: str # 'verified' | 'attested' | 'observed'
detail: str
@dataclass
class GrcResult:
record_id: str # unique ID, empty string on failure
record_type: str # one of the 11 RecordType values
mapped_controls: list[str] # e.g. ['EUAIA_ART9', 'ISO42001_6_1']
detail: str

Configuration

mima = MimaGovernance(
api_key="mima_ext_...", # required
system_name="my-pipeline", # required
workspace_id=None, # auto-resolved from API key
base_url="https://api.mima.works",
agent_name=None, # defaults to system_name
signing_key=None, # 32-byte hex HMAC-SHA256 key
authorised_by=AuthorisedBy(identity="alice@co.com", role="ml-eng"),
on_error="warn", # 'warn' | 'raise' | 'silent'
batch_flush_interval=30, # seconds
batch_max_size=100,
)

Record types

RecordType = Literal[
'ai_risk_assessment', 'governance_review', 'model_evaluation',
'training_data_governance', 'human_oversight', 'incident_report',
'change_event', 'access_review', 'vendor_risk', 'model_drift_event',
'policy_acknowledged',
]