Tenzro Testnet is live —request testnet TNZO
← Back to Tutorials
InstitutionalAdvanced

Build an Institutional AML Agent

Build a production-grade Anti-Money Laundering (AML) compliance agent for banks and financial institutions. The agent runs AI models inside TEE enclaves for privacy, checks transactions against ERC-3643 compliance rules, generates verifiable attestations, and publishes to the Tenzro agent marketplace so any app on the network can use it.

What We're Building

Architecture


// Fintech App                    AML Agent (on Tenzro Network)
//     |                              |
//     |-- "Check this tx" ---------->| 1. Receive via A2A/MCP
//     |   (pays 0.001 TNZO)         | 2. Run gemma3-270m in TEE
//     |                              | 3. Check ERC-3643 rules
//     |                              | 4. Generate TEE attestation
//     |<-- Compliance result --------| 5. Return result + proof
//     |   + TEE attestation          |
//     |                              | Settlement on Canton DAML

Step 1: Set Up the Agent

import { TenzroClient, TESTNET_CONFIG } from 'tenzro-sdk';

const client = new TenzroClient(TESTNET_CONFIG);

// Register the AML agent
const agent = await client.agent.register(
  'aml-compliance-oracle',
  'AML Compliance Oracle',
  ['compliance', 'kyc', 'screening', 'aml']
);

// Fund the agent wallet via atomic server-side hybrid sign + submit.
// tenzro_signAndSendTransaction identifies the signing wallet from the
// ambient DPoP-bound JWT, assembles the canonical Transaction::hash()
// preimage (which commits to the wallet's ML-DSA-65 public key), signs
// both the Ed25519 leg and the ML-DSA-65 (FIPS 204) leg, verifies them,
// and submits in one call. An invalid signature on either leg returns
// JSON-RPC error -32003. Private keys never travel over the wire.
const fundTx = await client.rpc.call<string>(
  'tenzro_signAndSendTransaction',
  [{
    from: myAddress,
    to: agent.wallet_address,
    value: '0x56bc75e2d63100000', // 100 TNZO in wei (hex)
    nonce: '0x0',
    chain_id: 1337,
  }],
);
console.log('Agent funded:', fundTx);

Step 2: Detect TEE and Generate Attestation

// Check TEE hardware
const tee = await client.tee.detectTee();
console.log('TEE available:', tee.available);
console.log('Vendor:', tee.vendor); // e.g., "intel-tdx", "amd-sev-snp"

// Generate attestation (proves code runs in secure enclave)
const attestation = await client.tee.getAttestation(tee.vendor);
console.log('Report:', attestation.report.substring(0, 64) + '...');
console.log('Cert chain:', attestation.certificate_chain.length, 'certs');

Step 3: Register Compliance Rules

// Register ERC-3643 compliance for TNZO
await client.compliance.registerCompliance('TNZO', true, 10000);
// kyc_required: true
// holder_limit: 10,000

// For a security token
await client.compliance.registerCompliance('SEC-TOKEN', true, 500);

Step 4: Run AI Analysis in TEE

// Seal transaction data in TEE (encrypted, never leaves enclave)
const sealed = await client.tee.sealData(
  Buffer.from(JSON.stringify({
    from: '0xSender...',
    to: '0xRecipient...',
    amount: '50000000000000000000', // 50 TNZO
    timestamp: Date.now(),
  })).toString('hex'),
  'aml-analysis-key'
);

// Run gemma3-270m inference on the sealed data
const analysis = await client.inference.request(
  'gemma3-270m',
  'Analyze this transaction for AML risk: ' +
  'sender=0xSender, recipient=0xRecipient, amount=50 TNZO. ' +
  'Check for: unusual patterns, high-risk jurisdictions, structuring.',
  512
);

console.log('AML Analysis:', analysis.output);
console.log('Risk score:', analysis.output.includes('high risk') ? 'HIGH' : 'LOW');

Step 5: Check ERC-3643 Compliance

// Check if transfer is compliant
const compliance = await client.compliance.checkCompliance(
  'TNZO',
  '0xSender...',
  '0xRecipient...',
  '50000000000000000000'
);

console.log('Compliant:', compliance.compliant);
console.log('Reason:', compliance.reason || 'Transfer approved');

// If non-compliant, freeze the address
if (!compliance.compliant) {
  await client.compliance.freezeAddress('TNZO', '0xSender...');
  console.log('Address frozen');
}

Step 6: Generate ZK Proof of Compliance

// Create a ZK proof that the compliance check was performed correctly
// without revealing the transaction details
const proof = await client.zk.createProof(
  'settlement',
  { amount: 50, compliant: true, risk_score: 0.1 },
  ['0x01', '0x02'] // public inputs
);

console.log('ZK Proof:', proof.proof.substring(0, 64) + '...');
console.log('Proof type:', proof.proof_type); // groth16

Step 7: Publish to Agent Marketplace

// Publish as a reusable infrastructure agent
const marketplace = client.marketplace();
const template = await marketplace.registerAgentTemplate({
  name: 'AML Compliance Oracle',
  description: 'Real-time AML/KYC screening with TEE attestation and ZK proofs',
  template_type: 'infrastructure',
  tags: ['compliance', 'aml', 'kyc', 'screening'],
});

console.log('Template ID:', template.template_id);
console.log('Status: Published to marketplace');

// Other apps can now discover and use this agent:
// const templates = await marketplace.listAgentTemplates({ tags: ['aml'] });
// const amlAgent = await marketplace.spawnAgentFromTemplate(templates[0].template_id, 'my-aml');
// const result = await client.agent.delegateTask(amlAgent.agent_id, 'Check tx 0x...');

Step 8: Set Up Billing (Micropayments)

// Create escrow for per-check billing
const escrowId = await client.settlement.createEscrow(
  agent.wallet_address,
  10000000000000000000n, // 10 TNZO deposit
  'TNZO',
  JSON.stringify({ type: 'per_check', price: '0.001' })
);

console.log('Escrow ID:', escrowId);
console.log('Pricing: 0.001 TNZO per compliance check');

Step 9: Canton DAML Integration (Institutional)

// For institutional settlement, use Canton DAML
const domains = await client.canton.listDomains();

// Submit compliance result as a DAML contract
await client.canton.submitCommand({
  domain_id: domains[0].id,
  command_type: 'create',
  act_as: ['AML-Compliance-Party'],
  template_id: 'AmlComplianceResult',
  payload: {
    transactionId: 'tx-123',
    sender: '0xSender...',
    recipient: '0xRecipient...',
    amount: '50 TNZO',
    compliant: true,
    attestation: attestation.report,
    zkProof: proof.proof,
    timestamp: new Date().toISOString(),
  }
});

Production Deployment

Related