Table of Contents

Build a Security and Compliance Toolkit Agent

Enterprise applications handle sensitive data at every layer: customer records, API tokens, passwords, file transfers, and authentication artifacts. LM-Kit.NET ships six security built-in tools (Hash, Crypto, JWT, Validator, Password, Checksum) that an agent can call autonomously to validate, hash, encrypt, and audit data. Combined with PII extraction, this creates a complete compliance toolkit that runs entirely on your infrastructure. This tutorial builds a security agent that audits data quality, anonymizes PII, verifies file integrity, and enforces password policies.


Why This Matters

Two enterprise problems that a local security toolkit agent solves:

  1. Compliance without data exfiltration. Regulations like GDPR, HIPAA, and PCI DSS require that sensitive data be validated, encrypted, and audited. Sending customer records to cloud security services for validation means the data you are trying to protect leaves your infrastructure. A local agent performs all validation, hashing, and encryption on-premises without any external network calls.
  2. Automated security audits at scale. Manually checking email formats, password strength, JWT expiration, and file checksums across thousands of records is error-prone and slow. An agent with security tools can process entire datasets in a single prompt, reporting every issue in a structured format.

Prerequisites

Requirement Minimum
.NET SDK 8.0+
VRAM 6+ GB (for Qwen 3 8B with tool-calling support)
Disk ~5 GB free for model download

You need a model that supports tool calling. Recommended: qwen3:8b. Verify with model.HasToolCalls after loading.


Step 1: Create the Project

dotnet new console -n SecurityToolkitAgent
cd SecurityToolkitAgent
dotnet add package LM-Kit.NET

Step 2: Understand the Security Tools Ecosystem

LM-Kit.NET provides six dedicated security tools, each accessed through the BuiltInTools factory class. Together they cover the full spectrum of data security operations.

Tool BuiltInTools Property Key Operations Enterprise Use Case
Hash BuiltInTools.Hash sha256, sha512, md5, sha1, base64_encode, base64_decode, url_encode, url_decode Anonymizing PII before storage, generating deterministic identifiers
Crypto BuiltInTools.Crypto encrypt, decrypt, generate_key, generate_iv, random_bytes, random_token, derive_key Encrypting sensitive fields in transit, generating secure API tokens
Validator BuiltInTools.Validator email, url, ip, ipv4, ipv6, phone, credit_card, date, uuid, json, hex, base64 Data quality audits, input sanitization, format compliance
JWT BuiltInTools.Jwt decode, validate, verify, create, get_claims, is_expired API authentication auditing, token lifecycle management
Password BuiltInTools.Password generate, strength, entropy, validate, memorable, passphrase Security policy enforcement, credential rotation audits
Checksum BuiltInTools.Checksum crc32, adler32, all, verify, combine File transfer verification, data integrity checks

The agent selects the right tool and operation based on the user's natural language request. You register all six tools, and the ReAct planning loop handles the orchestration.


Step 3: Build a Data Validation Agent

This is the foundation. Register all six security tools with a single agent configured as a security analyst.

using System.Text;
using LMKit.Model;
using LMKit.Agents;
using LMKit.Agents.Tools.BuiltIn;

LMKit.Licensing.LicenseManager.SetLicenseKey("");

Console.InputEncoding = Encoding.UTF8;
Console.OutputEncoding = Encoding.UTF8;

// ──────────────────────────────────────
// 1. Load a tool-calling model
// ──────────────────────────────────────
Console.WriteLine("Loading model...");
using LM model = LM.LoadFromModelID("qwen3:8b",
    downloadingProgress: (_, len, read) =>
    {
        if (len.HasValue) Console.Write($"\r  Downloading: {(double)read / len.Value * 100:F1}%   ");
        return true;
    },
    loadingProgress: p => { Console.Write($"\r  Loading: {p * 100:F0}%   "); return true; });

Console.WriteLine($"\n  Tool calling supported: {model.HasToolCalls}\n");

// ──────────────────────────────────────
// 2. Build the security agent
// ──────────────────────────────────────
var agent = Agent.CreateBuilder(model)
    .WithPersona("Security and Compliance Analyst")
    .WithInstruction("You are a data security expert. Validate, hash, encrypt, and audit data. " +
                     "Always report findings in a structured format with clear pass/fail indicators. " +
                     "When processing multiple items, handle each one individually and summarize results at the end.")
    .WithPlanning(PlanningStrategy.ReAct)
    .WithTools(tools =>
    {
        tools.Register(BuiltInTools.Validator);
        tools.Register(BuiltInTools.Hash);
        tools.Register(BuiltInTools.Crypto);
        tools.Register(BuiltInTools.Jwt);
        tools.Register(BuiltInTools.Password);
        tools.Register(BuiltInTools.Checksum);
    })
    .WithMaxIterations(15)
    .Build();

// ──────────────────────────────────────
// 3. Interactive security audit loop
// ──────────────────────────────────────
Console.WriteLine("Security agent ready. Describe your audit task (or 'quit' to exit):\n");

while (true)
{
    Console.ForegroundColor = ConsoleColor.Green;
    Console.Write("You: ");
    Console.ResetColor();

    string? input = Console.ReadLine();
    if (string.IsNullOrWhiteSpace(input) || input.Equals("quit", StringComparison.OrdinalIgnoreCase))
        break;

    var result = await agent.RunAsync(input);

    if (result.IsSuccess)
    {
        Console.ForegroundColor = ConsoleColor.Cyan;
        Console.WriteLine($"\nAnalyst: {result.Content}");
        Console.ResetColor();

        if (result.ToolCalls.Count > 0)
        {
            Console.ForegroundColor = ConsoleColor.DarkGray;
            var toolSummary = result.ToolCalls
                .GroupBy(tc => tc.ToolName)
                .Select(g => $"{g.Key} ({g.Count()}x)");
            Console.WriteLine($"  Tools: {string.Join(", ", toolSummary)}");
            Console.WriteLine($"  Duration: {result.Duration.TotalSeconds:F1}s");
            Console.ResetColor();
        }
    }
    else
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine($"\nError: {result.Error?.Message}");
        Console.ResetColor();
    }

    Console.WriteLine();
}

Step 4: Validate Data Formats at Scale

The Validator tool checks emails, phone numbers, credit cards, URLs, IPs, and UUIDs with detailed structural analysis. Ask the agent to validate an entire customer record, and it calls the validator for each field.

var validationResult = await agent.RunAsync(
    "Validate these customer records for data quality:\n" +
    "- Email: jane.doe@example.com\n" +
    "- Email: invalid-email@@broken\n" +
    "- Phone: +1 (555) 867-5309\n" +
    "- Phone: 12345\n" +
    "- Credit card: 4532-1234-5678-4242\n" +
    "- Credit card: 1111-2222-3333-4444\n" +
    "- URL: https://api.company.com/v2/users\n" +
    "- URL: not-a-url\n" +
    "- IP: 192.168.1.100\n" +
    "- IP: 999.999.999.999\n" +
    "- UUID: 550e8400-e29b-41d4-a716-446655440000\n" +
    "\nFor each item, report whether it is valid and provide any details about the format.");

Console.WriteLine(validationResult.Content);

The agent calls the validator tool repeatedly with operations like email, phone, credit_card, url, ip, and uuid. Each call returns structured data: the Validator reports not just pass/fail but also parsed components (email user/host, credit card type via Luhn check, IP address family and privacy status, UUID format).


Step 5: Hash Sensitive Data for Privacy

The Hash tool computes SHA-256, SHA-512, MD5, and SHA-1 digests and handles Base64 and URL encoding. Use it to anonymize PII before storage or logging.

var hashResult = await agent.RunAsync(
    "I need to anonymize these email addresses before storing them in our analytics database. " +
    "Please hash each one with SHA-256 so we can track unique users without storing actual emails:\n" +
    "- alice.johnson@company.com\n" +
    "- bob.smith@provider.net\n" +
    "- carol.williams@example.org\n" +
    "\nAlso, Base64 encode the string 'audit-session-2025-06-15' for use as a tracking identifier, " +
    "and URL encode the query string 'name=John Doe&role=admin&dept=IT Security'.");

Console.WriteLine(hashResult.Content);

The agent calls hash with operation: "sha256" for each email, returning both hex and Base64 representations. It then uses base64_encode and url_encode for the remaining tasks. This workflow is common in GDPR compliance where you need pseudonymized identifiers that are consistent (same input always produces the same hash) but irreversible.


Step 6: Encrypt and Decrypt Data with AES

The Crypto tool provides AES-256-CBC encryption with HMAC authentication, key generation, key derivation (PBKDF2), and secure random token generation. Use it to protect sensitive fields before transit or storage.

// Step 1: Ask the agent to generate a key and encrypt data
var encryptResult = await agent.RunAsync(
    "I need to encrypt a sensitive customer record before sending it to our partner API. " +
    "Please do the following:\n" +
    "1. Generate a new AES-256 encryption key.\n" +
    "2. Encrypt this data with the generated key: " +
    "'SSN: 234-56-7890, Account: 9876543210, DOB: 1985-03-15'\n" +
    "3. Show me the encrypted output and the key (I will store the key separately in our vault).");

Console.WriteLine(encryptResult.Content);

// Step 2: Ask the agent to decrypt (using the key from the previous step)
var decryptResult = await agent.RunAsync(
    "Now decrypt the data you just encrypted using the same key, " +
    "to verify the round-trip works correctly.");

Console.WriteLine(decryptResult.Content);

The agent first calls crypto with operation: "generate_key" to create a 256-bit key, then calls encrypt with the plaintext and key. The encrypted output includes the ciphertext, IV, and HMAC tag. For decryption, it calls decrypt with the same key. The HMAC verification ensures the ciphertext has not been tampered with.

You can also ask the agent to derive keys from passwords using PBKDF2:

var keyResult = await agent.RunAsync(
    "Derive an AES-256 encryption key from the password 'compliance-audit-2025' " +
    "using 100,000 PBKDF2 iterations. Also generate a secure random API token (64 bytes).");

Console.WriteLine(keyResult.Content);

Step 7: Audit JWT Tokens

The JWT tool decodes tokens, validates structure and expiration, verifies HMAC signatures, and extracts claims. Use it for API authentication auditing.

// Sample JWT token (expired, for audit demonstration)
string sampleJwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9." +
    "eyJzdWIiOiJ1c2VyLTEyMzQ1IiwibmFtZSI6IkphbmUgRG9lIiwicm9sZSI6ImFkbWluIiwiZXhwIjoxNzAwMDAwMDAwLCJpYXQiOjE2OTk5OTAwMDB9." +
    "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";

var jwtResult = await agent.RunAsync(
    $"Perform a full security audit on this JWT token:\n{sampleJwt}\n\n" +
    "Please:\n" +
    "1. Decode it and show the header and payload.\n" +
    "2. Validate the token structure (are required fields present?).\n" +
    "3. Check if the token is expired.\n" +
    "4. Extract all claims and categorize them as standard vs. custom.\n" +
    "5. Try verifying the HMAC signature with the secret 'my-api-secret'.\n" +
    "6. Provide an overall security assessment.");

Console.WriteLine(jwtResult.Content);

The agent calls jwt with operations decode, validate, is_expired, get_claims, and verify in sequence. Each operation returns structured results: decoded header/payload, a list of validation issues, expiration status with time remaining or expired duration, categorized claims, and signature verification status.

This is valuable for auditing API authentication across services. You can feed the agent a batch of tokens from your logs and get a comprehensive report on expired tokens, missing claims, and signature failures.


Step 8: Generate and Audit Passwords

The Password tool generates secure passwords, checks strength, calculates entropy, validates against custom policies, and creates memorable passphrases. Use it for security policy enforcement.

var passwordResult = await agent.RunAsync(
    "Our security policy requires the following for all service accounts:\n" +
    "- Minimum 20 characters\n" +
    "- Must include uppercase, lowercase, numbers, and symbols\n" +
    "- Minimum 90 bits of entropy\n\n" +
    "Please:\n" +
    "1. Generate 3 secure passwords that meet this policy.\n" +
    "2. Check the strength of these existing passwords:\n" +
    "   - 'Welcome123'\n" +
    "   - 'x9$Km!pQ2v#nR8wL'\n" +
    "   - 'correcthorsebatterystaple'\n" +
    "3. Generate a 5-word passphrase as an alternative.\n" +
    "4. Validate 'Admin2025!' against our policy.");

Console.WriteLine(passwordResult.Content);

The agent calls password with operations like generate (with length and character requirements), strength (returning entropy, score out of 10, and estimated crack time), passphrase (with word count), and validate (with custom policy parameters like minLength, requireUppercase, requireSymbols). The strength check reports whether the password contains repeating patterns or matches common password lists.


Step 9: Verify Data Integrity with Checksums

The Checksum tool computes CRC32 and Adler32 checksums for fast, non-cryptographic integrity verification. Use it for file transfer verification and data pipeline integrity.

var checksumResult = await agent.RunAsync(
    "We received a data file from our partner with these claimed checksums:\n" +
    "- Content: 'invoice-batch-2025-Q2-final-approved'\n" +
    "- Expected CRC32: 7A8B3C4D\n\n" +
    "Please:\n" +
    "1. Compute the CRC32 and Adler32 checksums for the content.\n" +
    "2. Verify whether the CRC32 matches the expected value.\n" +
    "3. Also compute checksums for these two data segments separately:\n" +
    "   - Segment A: 'invoice-batch-2025-Q2'\n" +
    "   - Segment B: 'final-approved'\n" +
    "4. Report whether the transfer integrity check passes or fails.");

Console.WriteLine(checksumResult.Content);

The agent calls checksum with operation: "all" to compute both CRC32 and Adler32, then uses verify to compare against the expected value. For segmented data, it computes individual checksums with crc32 and can combine them with combine to verify against a whole-file checksum. This is essential for verifying data pipeline integrity where files are transferred in chunks.


Step 10: Combine with PII Extraction for Full Compliance Audit

The most powerful workflow combines LM-Kit.NET's PiiExtraction class with the security agent. First, detect PII in unstructured text. Then, let the agent validate the detected entities and secure them.

using System.Text;
using LMKit.Model;
using LMKit.Agents;
using LMKit.Agents.Tools.BuiltIn;
using LMKit.TextAnalysis;

LMKit.Licensing.LicenseManager.SetLicenseKey("");

Console.InputEncoding = Encoding.UTF8;
Console.OutputEncoding = Encoding.UTF8;

// ──────────────────────────────────────
// 1. Load model
// ──────────────────────────────────────
Console.WriteLine("Loading model...");
using LM model = LM.LoadFromModelID("qwen3:8b",
    downloadingProgress: (_, len, read) =>
    {
        if (len.HasValue) Console.Write($"\r  Downloading: {(double)read / len.Value * 100:F1}%   ");
        return true;
    },
    loadingProgress: p => { Console.Write($"\r  Loading: {p * 100:F0}%   "); return true; });
Console.WriteLine("\n");

// ──────────────────────────────────────
// 2. Detect PII in unstructured text
// ──────────────────────────────────────
var piiExtractor = new PiiExtraction(model);

string document = """
    Customer intake form received on 2025-06-15:

    Name: Maria Garcia
    Email: maria.garcia@example.com
    Phone: (555) 234-8901
    SSN: 567-89-0123
    Credit Card: 4532-8901-2345-6789
    IP Address: 10.0.15.42
    Date of Birth: 08/22/1990

    Notes: Customer called from 192.168.1.55 requesting account changes.
    Backup email provided: m.garcia_backup@provider.net
    """;

Console.WriteLine("Scanning document for PII...\n");
List<PiiExtraction.PiiExtractedEntity> entities = piiExtractor.Extract(document);

Console.WriteLine($"Found {entities.Count} PII entities:\n");

foreach (var entity in entities)
{
    Console.ForegroundColor = ConsoleColor.Yellow;
    Console.Write($"  {entity.EntityDefinition.Label,-25}");
    Console.ResetColor();
    Console.WriteLine(entity.Value);
}

Console.WriteLine();

// ──────────────────────────────────────
// 3. Build the security agent
// ──────────────────────────────────────
var agent = Agent.CreateBuilder(model)
    .WithPersona("Security and Compliance Analyst")
    .WithInstruction("You are a data security expert. Validate, hash, encrypt, and audit data. " +
                     "Always report findings in a structured format.")
    .WithPlanning(PlanningStrategy.ReAct)
    .WithTools(tools =>
    {
        tools.Register(BuiltInTools.Validator);
        tools.Register(BuiltInTools.Hash);
        tools.Register(BuiltInTools.Crypto);
        tools.Register(BuiltInTools.Jwt);
        tools.Register(BuiltInTools.Password);
        tools.Register(BuiltInTools.Checksum);
    })
    .WithMaxIterations(20)
    .Build();

// ──────────────────────────────────────
// 4. Agent validates and secures detected PII
// ──────────────────────────────────────
string piiSummary = string.Join("\n",
    entities.Select(e => $"- {e.EntityDefinition.Label}: {e.Value}"));

var auditResult = await agent.RunAsync(
    $"I found these PII items in a customer document:\n{piiSummary}\n\n" +
    "Please perform a full compliance audit:\n" +
    "1. Validate the format of each email address, phone number, credit card, and IP address.\n" +
    "2. Hash all valid PII items with SHA-256 for anonymized storage.\n" +
    "3. Generate an AES-256 encryption key, then encrypt the SSN and credit card number.\n" +
    "4. Compute a CRC32 checksum of the original document text for integrity tracking.\n" +
    "5. Provide a compliance summary: which items are valid, which failed validation, " +
    "and confirmation that sensitive items have been hashed and encrypted.");

if (auditResult.IsSuccess)
{
    Console.ForegroundColor = ConsoleColor.Cyan;
    Console.WriteLine($"Compliance Report:\n{auditResult.Content}");
    Console.ResetColor();

    if (auditResult.ToolCalls.Count > 0)
    {
        Console.ForegroundColor = ConsoleColor.DarkGray;
        var toolSummary = auditResult.ToolCalls
            .GroupBy(tc => tc.ToolName)
            .Select(g => $"{g.Key} ({g.Count()}x)");
        Console.WriteLine($"\n  Tools used: {string.Join(", ", toolSummary)}");
        Console.WriteLine($"  Total duration: {auditResult.Duration.TotalSeconds:F1}s");
        Console.ResetColor();
    }
}
else
{
    Console.ForegroundColor = ConsoleColor.Red;
    Console.WriteLine($"Error: {auditResult.Error?.Message}");
    Console.ResetColor();
}

This creates a complete compliance pipeline:

  Unstructured document
         │
         ▼
  PiiExtraction.Extract()   →   List of detected PII entities
         │
         ▼
  Agent + Security Tools
    ├── Validator: check format of emails, phones, cards, IPs
    ├── Hash: SHA-256 anonymize all valid PII
    ├── Crypto: AES-256 encrypt SSN and credit card
    └── Checksum: CRC32 for document integrity tracking
         │
         ▼
  Structured compliance report

Common Issues

Problem Cause Fix
Agent skips some security tools Too many tools registered, model gets confused Use a larger model (qwen3:8b or qwen3:14b). Reduce the number of tasks per prompt
Encryption fails with "Key must be 256 bits" Agent passed a raw string instead of a Base64 key Ask the agent to generate a key first with generate_key, then use the returned Base64 key for encryption
JWT verification returns false for valid tokens Wrong secret or algorithm mismatch Ensure the secret matches the one used to sign the token. Specify the algorithm (HS256, HS384, HS512) explicitly in the prompt
Validator reports credit card as invalid Card number fails Luhn checksum This is correct behavior. The Luhn algorithm detects transposed or mistyped digits. Double-check the card number
PII extraction misses some entities Default entity types do not cover the data Add custom PiiEntityDefinition entries and provide Guidance describing the document format
Agent runs out of iterations Complex audit with many items exceeds MaxIterations Increase WithMaxIterations() to 20 or 25. Alternatively, break the audit into smaller batches

Next Steps