KAKUNIN

Tutorial: Implement Secure Runtime Binding for Your Agent

This tutorial walks you through integrating Kakunin runtime binding into an existing agent. By the end, every action your agent takes will be cryptographically signed and scope-enforced.


Prerequisites


Step 1: Install Kakunin SDK

TypeScript/Node.js

npm install @kakunin/sdk

Python

pip install kakunin-sdk

Step 2: Initialize Kakunin Client

TypeScript

import { KakuninClient } from '@kakunin/sdk';

const kakunin = new KakuninClient({
  apiKey: process.env.KAKUNIN_API_KEY,
  baseUrl: 'https://api.kakunin.ai',
});

Python

from kakunin import KakuninClient

kakunin = KakuninClient(
    api_key=os.getenv('KAKUNIN_API_KEY'),
    base_url='https://api.kakunin.ai'
)

Step 3: Bind Agent Identity at Startup

Create or retrieve an agent and bind it to your process.

TypeScript

async function setupAgent() {
  // Option 1: Create a new agent
  const agent = await kakunin.agents.create({
    name: 'my_trading_bot',
    metadata: { version: 'v1.0.0' },
  });
  
  // Option 2: Retrieve existing agent
  // const agent = await kakunin.agents.get('my_trading_bot');
  
  // Issue or retrieve certificate
  const cert = await kakunin.agents.getCertificate(agent.id, {
    validityDays: 365,
    scope: {
      maxTransactionSize: 50000,
      allowedMarkets: ['EUR_USD', 'GBP_USD'],
      allowedRegions: ['eu-west-1'],
    },
  });
  
  // Store certificate and KMS ARN in memory
  // Never store private key — it stays in KMS
  return {
    agentId: agent.id,
    certificatePem: cert.certificate_pem,
    kmsKeyArn: cert.kms_key_arn,
    serialNumber: cert.serial_number,
  };
}

const identity = await setupAgent();
console.log(`Agent bound: ${identity.agentId}`);

Python

async def setup_agent():
    # Create or retrieve agent
    agent = await kakunin.agents.create(
        name='my_trading_bot',
        metadata={'version': 'v1.0.0'}
    )
    
    # Issue certificate
    cert = await kakunin.agents.get_certificate(
        agent['id'],
        validity_days=365,
        scope={
            'max_transaction_size': 50000,
            'allowed_markets': ['EUR_USD', 'GBP_USD'],
            'allowed_regions': ['eu-west-1'],
        }
    )
    
    return {
        'agent_id': agent['id'],
        'certificate_pem': cert['certificate_pem'],
        'kms_key_arn': cert['kms_key_arn'],
        'serial_number': cert['serial_number'],
    }

identity = await setup_agent()

Step 4: Sign Actions Before Execution

Before your agent executes any significant action (trade, write data, etc.), sign it:

TypeScript

async function executeTrade(tradeRequest: {
  market: string;
  side: 'BUY' | 'SELL';
  size: number;
}) {
  // 1. Serialize request deterministically
  const payload = JSON.stringify(tradeRequest, 
    Object.keys(tradeRequest).sort()
  );
  
  // 2. Sign with agent's identity
  const signedAction = await kakunin.actions.sign({
    agentId: identity.agentId,
    payload,
    metadata: {
      actionType: 'trade.execute',
      timestamp: Date.now(),
    },
  });
  
  console.log(`Action signed: ${signedAction.signature.substring(0, 20)}...`);
  
  // 3. Submit to exchange with proof
  const response = await fetch('https://api.exchange.com/v1/trades', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Agent-Certificate': identity.certificatePem,
      'X-Agent-Signature': signedAction.signature,
      'X-Agent-Timestamp': signedAction.timestamp.toString(),
      'Authorization': `Bearer ${process.env.EXCHANGE_API_KEY}`,
    },
    body: payload,
  });
  
  if (!response.ok) {
    throw new Error(`Trade failed: ${await response.text()}`);
  }
  
  return response.json();
}

// Execute trade
const trade = {
  market: 'EUR_USD',
  side: 'BUY',
  size: 45000,
};

const result = await executeTrade(trade);
console.log(`Trade executed: ${result.orderId}`);

Python

async def execute_trade(trade_request: dict):
    # Serialize deterministically
    payload = json.dumps(trade_request, sort_keys=True)
    
    # Sign action
    signed_action = await kakunin.actions.sign(
        agent_id=identity['agent_id'],
        payload=payload,
        metadata={
            'action_type': 'trade.execute',
            'timestamp': int(time.time() * 1000),
        }
    )
    
    # Submit with proof
    async with aiohttp.ClientSession() as session:
        async with session.post(
            'https://api.exchange.com/v1/trades',
            headers={
                'X-Agent-Certificate': identity['certificate_pem'],
                'X-Agent-Signature': signed_action['signature'],
                'X-Agent-Timestamp': str(signed_action['timestamp']),
            },
            data=payload,
        ) as response:
            if response.status != 200:
                raise Exception(f"Trade failed: {await response.text()}")
            return await response.json()

trade = {
    'market': 'EUR_USD',
    'side': 'BUY',
    'size': 45000,
}

result = await execute_trade(trade)

Step 5: Handle Revocation

Your agent should check revocation status periodically. Kakunin handles this automatically if you use the signing service, but you can also check manually:

TypeScript

async function checkRevocationStatus(): Promise<boolean> {
  const status = await kakunin.certificates.getStatus(
    identity.serialNumber
  );
  
  if (status.revoked) {
    console.error(`Agent revoked: ${status.revocation_reason}`);
    process.exit(1); // Stop execution immediately
  }
  
  return !status.revoked;
}

// Check on startup
await checkRevocationStatus();

// Check periodically (e.g., every 5 minutes)
setInterval(checkRevocationStatus, 5 * 60 * 1000);

Python

async def check_revocation_status() -> bool:
    status = await kakunin.certificates.get_status(
        identity['serial_number']
    )
    
    if status.get('revoked'):
        logger.error(f"Agent revoked: {status['revocation_reason']}")
        sys.exit(1)
    
    return not status.get('revoked', False)

await check_revocation_status()
asyncio.create_task(periodic_check(check_revocation_status, 5 * 60))

Step 6: Monitor and Log

Log all actions with their signatures for audit trails:

TypeScript

async function logAction(
  action: string,
  request: any,
  signature: string,
  result: any
) {
  const auditEntry = {
    timestamp: new Date().toISOString(),
    agent_id: identity.agentId,
    agent_cert_serial: identity.serialNumber,
    action_type: action,
    request_payload: request,
    signature: signature.substring(0, 50) + '...',
    result_status: result.status || 'success',
  };
  
  // Log to stdout (structured for Datadog/Better Stack)
  console.log(JSON.stringify(auditEntry));
  
  // Optional: Send to compliance audit system
  await complianceAuditLog.insert(auditEntry);
}

Step 7: Test Integration

Test locally before deploying:

TypeScript

async function testIntegration() {
  // 1. Setup
  const identity = await setupAgent();
  console.log('✓ Agent identity bound');
  
  // 2. Sign action
  const testPayload = JSON.stringify({ test: true });
  const signed = await kakunin.actions.sign({
    agentId: identity.agentId,
    payload: testPayload,
  });
  console.log('✓ Action signed');
  
  // 3. Check revocation
  const notRevoked = await checkRevocationStatus();
  console.log(`✓ Revocation check passed: ${notRevoked}`);
  
  // 4. Test with mock exchange
  const mockResponse = await testMockExchange(
    testPayload,
    identity.certificatePem,
    signed.signature
  );
  console.log(`✓ Mock exchange accepted signature: ${mockResponse.ok}`);
  
  console.log('\n✅ Runtime binding integration successful');
}

await testIntegration();

Environment Variables

Create .env:

# Kakunin API
KAKUNIN_API_KEY=sk_live_xxxxxxxxxxxxxxxx

# Exchange API (if needed)
EXCHANGE_API_KEY=your_exchange_api_key

# Logging
LOG_LEVEL=info
AUDIT_LOG_ENDPOINT=https://audit.yourcompany.com/api/log

What's Next?

Now that your agent is cryptographically bound:

  1. Monitor behavior: Set up alerts in Kakunin dashboard for anomalies
  2. Test scope enforcement: Verify agent refuses out-of-scope requests
  3. Deploy to production: Follow deployment best practices
  4. Generate compliance reports: Use Kakunin to export audit trails for regulators

Troubleshooting

"Certificate not found"

"Signature verification failed"

"KMS access denied"


Resources