TypeScript SDK Reference

Package: @mima-ai/governance · Version: 0.1.x · Node.js: 18+


Building a TypeScript AI agent? You don’t need this SDK. Configure the MCP server in 4 lines and your agent has full governance evidence — no code changes, any language:

Use this SDK when your TypeScript app code calls AI APIs directly — LangChain chains, batch pipelines, CI scripts, or any workflow where you control the call site.


$npm install @mima-ai/governance

Requires Node.js 18+ for native fetch and crypto. No runtime dependencies.


Client setup

1import { MimaGovernance } from '@mima-ai/governance';
2
3const mima = new MimaGovernance({
4 apiKey: process.env.MIMA_API_KEY!, // required
5 systemName: 'my-ai-pipeline', // required
6 workspaceId: undefined, // resolved from API key automatically
7 baseUrl: 'https://api.mima.ai', // override for self-hosted
8 agentName: undefined, // defaults to systemName
9 signingKey: undefined, // 32-byte hex key for GRC signing
10 authorisedBy: {
11 identity: 'alice@example.com',
12 role: 'ml-engineer',
13 },
14 onError: 'warn', // 'warn' | 'raise' | 'silent'
15 batchFlushInterval: 30_000, // ms
16 batchMaxSize: 100,
17});

Environment variables

VariablePurpose
MIMA_API_KEYAlternative to passing apiKey
MIMA_WORKSPACE_IDAlternative to passing workspaceId

Attestation

mima.wrap() — function wrapper

TypeScript’s equivalent of Python’s @mima.attest() decorator. Takes a function and returns a wrapped version that attests every call.

1const classify = mima.wrap('classify_document', async (doc: string) => {
2 const resp = await anthropic.messages.create({
3 model: 'claude-opus-4-6',
4 messages: [{ role: 'user', content: `Classify: ${doc}` }],
5 });
6 return resp.content[0].type === 'text' ? resp.content[0].text : '';
7});
8
9const label = await classify(document); // attests automatically

Parameters

ParameterTypeDefaultDescription
toolNamestringrequiredName of the tool / action
fnFunctionrequiredFunction to wrap
options.modelIdstringLLM model identifier
options.authorisedByAuthorisedByclient defaultOverride for this call
options.mode'sync' | 'batch''sync'Push immediately or buffer

The wrapped function always returns Promise<TReturn>. If the original function was sync, the return type becomes Promise<OriginalReturnType>.


mima.push() — explicit attestation

Use when you have pre-computed hashes (e.g. from a pipeline step with its own hashing).

1import { createHash } from 'node:crypto';
2
3const inputHash = createHash('sha256').update(JSON.stringify(input)).digest('hex');
4const outputHash = createHash('sha256').update(JSON.stringify(output)).digest('hex');
5
6await mima.push('generate_report', inputHash, outputHash, {
7 modelId: 'claude-opus-4-6',
8 executedAt: new Date().toISOString(),
9});

mima.trace() — manual hash capture

Pass a callback. Call ctx.setInput() / ctx.setOutput() to capture hashes at the right moment.

1const result = await mima.trace('run_pipeline', async (ctx) => {
2 ctx.setInput(inputDocs);
3 const output = await pipeline.run(inputDocs);
4 ctx.setOutput(output);
5 ctx.setModelId('claude-opus-4-6');
6 return output;
7});

mima.batch() — buffered bulk push

1await mima.batch(async (b) => {
2 for (const item of workQueue) {
3 const result = await processItem(item);
4 b.add('process_item', { input: item, output: result });
5 }
6});
7// All records flushed in a single batch request on exit.

GRC evidence methods

All GRC methods are async and return Promise<GrcResult>:

1interface GrcResult {
2 recordId: string; // '' on failure
3 recordType: RecordType;
4 mappedControls: string[]; // e.g. ['EUAIA_ART9', 'ISO42001_6_1']
5 detail: string; // 'ok' on success
6}

mima.aiRiskAssessment()

1await mima.aiRiskAssessment(
2 'loan-scorer',
3 'high',
4 'Automated credit scoring for consumer loans',
5 {
6 intendedPurpose: 'Score loan applications for human review',
7 impactDomains: ['credit', 'consumer_finance'],
8 art5SelfAssessment: true, // certifies no Art.5 prohibited practices
9 assessor: 'alice@example.com',
10 annexIiiCategory: 'essential_services', // required for high-risk
11 environment: 'production',
12 systemVersion: 'v2.1.0',
13 technicalDocUrl: 'https://docs.internal/loan-scorer/annex-iv',
14 },
15);

art5SelfAssessment: true certifies no Art. 5 prohibited practices. Never set without explicit human confirmation.


mima.modelEvaluation()

1await mima.modelEvaluation(
2 'loan-scorer-v2.1',
3 'holdout-q2-2026',
4 0.94,
5 {
6 evaluatedBy: 'alice@example.com',
7 evaluationType: 'quarterly',
8 biasMetrics: { demographic_parity: 0.02, equal_opportunity: 0.01 },
9 robustnessScore: 0.91,
10 passedThreshold: true,
11 },
12);

mima.humanOversight()

1await mima.humanOversight(
2 'loan-app-48291',
3 'approve',
4 'reject',
5 {
6 reviewer: 'bob@example.com',
7 rationale: 'Flagged for fraud indicators not in model training data',
8 modelId: 'loan-scorer-v2.1',
9 },
10);
11// override: true is inferred (approve !== reject)

mima.trainingDataGovernance()

1await mima.trainingDataGovernance(
2 'loan-scorer-v2.1',
3 'training-set-2026-q1',
4 2_400_000,
5 {
6 biasChecksPerformed: true,
7 approvedBy: 'data-governance@example.com',
8 dataSources: ['internal_originations', 'credit_bureau_x'],
9 dataCategories: ['financial_history', 'demographics'],
10 knownLimitations: 'Underrepresented: self-employed applicants pre-2020',
11 },
12);

mima.incidentReport()

1await mima.incidentReport(
2 'Model output hallucination on edge case inputs',
3 'high',
4 {
5 description: 'Model returned invalid IBANs for 3 users on 2026-06-01',
6 affectedSystems: ['payment-processor-ai'],
7 detectedAt: '2026-06-01T14:22:00Z',
8 authorityNotifiedAt: '2026-06-01T18:00:00Z',
9 },
10);

mima.accessReview()

1await mima.accessReview(
2 'contractor@external.com',
3 'model-training-pipeline',
4 false,
5 {
6 reviewedBy: 'alice@example.com',
7 reviewType: 'periodic',
8 reason: 'Contractor engagement ended 2026-05-31',
9 },
10);

mima.changeEvent()

1await mima.changeEvent(
2 'prompt_update',
3 'alice@example.com',
4 'Updated system prompt to add output format constraints',
5 {
6 environment: 'production',
7 system: 'customer-support-ai',
8 changeId: 'CHG-4821',
9 },
10);

mima.vendorRisk()

1await mima.vendorRisk('OpenAI', 'high', {
2 lastReviewed: '2026-06-01',
3 findings: 2,
4 contacts: ['security@openai.com'],
5});

mima.policyAcknowledged()

1await mima.policyAcknowledged(
2 'AI Use Policy',
3 'alice@example.com',
4 {
5 version: 'v3.1.0',
6 acknowledgmentType: 'initial',
7 policyUrl: 'https://internal.example.com/policies/ai-use/v3.1.0',
8 channel: 'in-app',
9 },
10);

mima.modelDriftEvent()

1await mima.modelDriftEvent(
2 'loan-scorer-v2.1',
3 'f1_score',
4 0.94,
5 0.88,
6 0.90,
7 {
8 driftType: 'performance',
9 detectedBy: 'monitoring-agent',
10 actionTaken: 'Model retraining scheduled for 2026-07-01',
11 },
12);

mima.governanceReview()

1await mima.governanceReview(
2 'ciso@example.com',
3 'quarterly',
4 {
5 frameworksReviewed: ['EU_AI_ACT', 'ISO_42001', 'SOC2'],
6 overallReadiness: 78,
7 actionItems: 4,
8 notes: 'Three open gaps in Art.9 documentation.',
9 },
10);

Lifecycle

Always call mima.close() at the end of a long-running process or serverless function. It flushes any buffered batch records.

1// Express / Next.js — on shutdown
2process.on('SIGTERM', async () => {
3 await mima.close();
4 process.exit(0);
5});
6
7// Lambda / serverless — at the end of each handler
8export const handler = async (event: APIGatewayEvent) => {
9 try {
10 return await handleRequest(event);
11 } finally {
12 await mima.close();
13 }
14};

The client also registers process.once('beforeExit', ...) as a safety net.


Signing GRC records

Pass a 32-byte hex key to enable HMAC-SHA256 signing. Every GRC push includes client_sig and client_sig_algo: "hmac-sha256".

1import { randomBytes } from 'node:crypto';
2// Generate once and store in a secrets manager:
3const signingKey = randomBytes(32).toString('hex');
4
5const mima = new MimaGovernance({
6 apiKey: '...',
7 systemName: '...',
8 signingKey,
9});

The canonical message is cross-compatible with the Python SDK — signatures generated by either SDK verify against each other.


ESM setup

The package is ESM-only. In a CommonJS project, use dynamic import:

1// CommonJS
2const { MimaGovernance } = await import('@mima-ai/governance');

For mixed projects, add "type": "module" to your package.json and rename .js files to .mjs as needed.


Error handling

1import { MimaGovernance, MimaAttestationError } from '@mima-ai/governance';
2
3const mima = new MimaGovernance({ ..., onError: 'raise' });
4
5try {
6 await mima.push('tool', inputHash, outputHash);
7} catch (err) {
8 if (err instanceof MimaAttestationError) {
9 logger.error('Governance record failed:', err.message);
10 }
11}

Check for failure without raising:

1const result = await mima.push('tool', inputHash, outputHash);
2if (!result.recordId) {
3 logger.warn('Push failed:', result.detail);
4}