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:
- 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.
- 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
- Extract PII and Redact Sensitive Data: deeper dive into PII detection, custom entity types, and batch processing.
- Build a Content Moderation Filter: combine security auditing with content moderation for user-generated data.
- Intercept and Control Tool Invocations: add logging, rate limiting, and security filtering to tool calls.
- Build a Compliance Validation System: document-level compliance checks for contracts and regulatory filings.
- Create an AI Agent with Tools: learn the full agent architecture, custom tools via
ITool, and planning strategies.