@the-bot-club/agentguard
v0.9.0
Published
AgentGuard SDK — policy engine, audit trail, kill switch, and LangChain/OpenAI integrations
Downloads
488
Readme
@the-bot-club/agentguard
Runtime security for AI agents — policy engine, audit trail, kill switch, and cloud API client.
Overview
AgentGuard gives you production-grade guardrails for AI agents:
- 🛡️ Policy Engine — evaluate tool calls against a YAML policy DSL (local, zero-latency)
- 📋 Audit Trail — append-only, tamper-evident hash chain of every action
- 🔴 Kill Switch — instantly halt one agent or all agents
- 🌐 Cloud API Client — connect to the hosted AgentGuard API
- 🔗 Framework Integrations — one-liner guards for LangChain, OpenAI, CrewAI, Express, and Fastify
Installation
npm install @the-bot-club/agentguardRequires Node.js 18+ (uses native fetch).
Quick Start — Cloud API Client
import { AgentGuard } from '@the-bot-club/agentguard';
const guard = new AgentGuard({ apiKey: 'ag_your_api_key' });
// Evaluate an agent action before executing it
const decision = await guard.evaluate({
tool: 'send_email',
params: { to: '[email protected]', subject: 'Hello' },
});
if (decision.result === 'allow') {
// Safe to proceed
console.log('Action allowed, risk score:', decision.riskScore);
} else if (decision.result === 'block') {
console.error('Action blocked:', decision.reason);
} else if (decision.result === 'require_approval') {
console.log('Waiting for human approval...');
}Get Usage Statistics
const usage = await guard.getUsage();
console.log(usage);Get Audit Trail
const audit = await guard.getAudit({ limit: 50, offset: 0 });
console.log(audit.events);Activate Kill Switch
// Halt all agents immediately
await guard.killSwitch(true);
// Resume operations
await guard.killSwitch(false);Webhooks
// Register a webhook endpoint
const webhook = await guard.createWebhook({
url: 'https://example.com/hooks/agentguard',
events: ['action.blocked', 'killswitch.activated'],
secret: 'my-signing-secret', // optional
});
console.log('Webhook ID:', webhook.id);
// List all webhooks
const { webhooks } = await guard.listWebhooks();
// Remove a webhook
await guard.deleteWebhook('wh_abc123');Agents
// Register an agent
const agent = await guard.createAgent({
name: 'email-agent',
policyScope: { allowedTools: ['send_email', 'read_inbox'] }, // optional
});
console.log('Agent ID:', agent.id);
// List all agents
const { agents } = await guard.listAgents();
// Remove an agent
await guard.deleteAgent('ag_abc123');Templates
// Browse available policy templates
const { templates } = await guard.listTemplates();
// Inspect a template
const template = await guard.getTemplate('strict');
console.log(template.rules);
// Apply a template to your tenant
await guard.applyTemplate('strict');Rate Limits
// Set a tenant-wide rate limit: max 100 requests per 60 seconds
const limit = await guard.setRateLimit({ windowSeconds: 60, maxRequests: 100 });
// Scope to a specific agent
await guard.setRateLimit({ agentId: 'ag_abc123', windowSeconds: 60, maxRequests: 20 });
// List all rate limits
const { rateLimits } = await guard.listRateLimits();
// Delete a rate limit
await guard.deleteRateLimit(limit.id);Cost
// Get overall cost summary
const summary = await guard.getCostSummary();
// Filter by agent and date range
const filtered = await guard.getCostSummary({
agentId: 'ag_abc123',
from: '2024-01-01',
to: '2024-01-31',
groupBy: 'day',
});
// Per-agent cost breakdown
const agentCosts = await guard.getAgentCosts();Dashboard
// High-level stats (requests, blocks, risk scores)
const stats = await guard.getDashboardStats();
// Live activity feed
const feed = await guard.getDashboardFeed();
// Feed from a specific timestamp onward
const recent = await guard.getDashboardFeed({ since: '2024-06-01T00:00:00Z' });
// Per-agent activity summary
const activity = await guard.getAgentActivity();PolicyEngine — Local Evaluation
For zero-latency, in-process policy evaluation without a network call:
import { PolicyEngine, PolicyBundle } from '@the-bot-club/agentguard';
// Load your compiled policy bundle (from AgentGuard Control Plane or local YAML)
const bundle: PolicyBundle = {
policyId: 'my-policy',
version: '1.0.0',
compiledAt: new Date().toISOString(),
defaultAction: 'block',
rules: [
{
id: 'allow-read-tools',
priority: 100,
action: 'allow',
toolCondition: { in: ['read_file', 'list_directory', 'search'] },
paramConditions: [],
contextConditions: [],
dataClassConditions: [],
timeConditions: [],
severity: 'low',
riskBoost: 0,
tags: ['read-only'],
},
{
id: 'block-delete',
priority: 200,
action: 'block',
toolCondition: { matches: ['*delete*', '*remove*', '*drop*'] },
paramConditions: [],
contextConditions: [],
dataClassConditions: [],
timeConditions: [],
severity: 'critical',
riskBoost: 500,
tags: ['destructive'],
},
],
toolIndex: {
'*': [0, 1],
},
checksum: 'abc123',
ruleCount: 2,
};
const engine = new PolicyEngine(bundle);
const decision = engine.evaluate({
id: crypto.randomUUID(),
agentId: 'agent-1',
tool: 'read_file',
params: { path: '/data/config.json' },
inputDataLabels: [],
timestamp: new Date().toISOString(),
});
console.log(decision.result); // 'allow'
console.log(decision.riskScore); // 0AuditLogger
import { AuditLogger } from '@the-bot-club/agentguard';
const logger = new AuditLogger();
// Log an action decision
const event = logger.log({
agentId: 'agent-1',
sessionId: 'session-abc',
policyVersion: '1.0.0',
tool: 'send_email',
params: { to: '[email protected]' },
decision: 'allow',
matchedRuleId: 'allow-email',
monitorRuleIds: [],
riskScore: 10,
reason: 'Matched allow-email rule',
durationMs: 1.2,
});
// Verify the entire audit chain
const { valid, invalidAt } = logger.verify();
console.log('Chain valid:', valid); // trueKillSwitch
import { KillSwitch } from '@the-bot-club/agentguard';
const ks = new KillSwitch();
// Register agent check in your tool execution loop
ks.on('halt', ({ tier, reason }) => {
console.error(`HALT [${tier}]:`, reason);
});
// Before every tool call:
if (ks.isHalted('agent-1')) {
throw new Error('Agent is halted');
}
// Halt globally
ks.haltGlobal('Security incident detected');
// Halt a specific agent
ks.haltAgent('agent-1', 'Exceeded rate limit');Framework Integrations
One-liner guards for popular AI agent frameworks. No peer dependencies required.
LangChain
import { langchainGuard } from '@the-bot-club/agentguard';
// Pass as a callback to AgentExecutor — every tool call is evaluated automatically:
const executor = AgentExecutor.fromAgentAndTools({
agent,
tools,
callbacks: [langchainGuard({ apiKey: 'ag_...' })],
});Blocked tool calls throw AgentGuardBlockError — LangChain surfaces this as a tool execution error:
import { AgentGuardCallbackHandler, AgentGuardBlockError } from '@the-bot-club/agentguard';
const handler = new AgentGuardCallbackHandler({ apiKey: 'ag_...', agentId: 'my-agent' });
try {
await handler.handleToolStart({ name: 'exec' }, '{"cmd":"rm -rf /"}');
} catch (err) {
if (err instanceof AgentGuardBlockError) {
console.log('Blocked:', err.reason);
console.log('Try instead:', err.alternatives);
}
}OpenAI
import OpenAI from 'openai';
import { openaiGuard } from '@the-bot-club/agentguard';
const client = new OpenAI({ apiKey: 'sk-...' });
const guarded = openaiGuard(client, { apiKey: 'ag_...' });
// Use `guarded` exactly like the regular OpenAI client:
const response = await guarded.chat.completions.create({
model: 'gpt-4o',
messages: [...],
tools: [...],
});
// Check which tool calls were blocked before executing them:
if (response._agentguard?.hasBlocks) {
for (const d of response._agentguard.decisions) {
if (d.decision === 'block') {
console.log(`Blocked ${d.tool}: ${d.reason}`);
console.log(`Suggestion: ${d.suggestion}`);
}
}
}CrewAI
import { crewaiGuard } from '@the-bot-club/agentguard';
const guard = crewaiGuard({ apiKey: 'ag_...' });
// In your agent tool execution hook — throws on block:
await guard.beforeToolExecution('send_email', { to: '[email protected]' });
// Batch evaluate (no throw — caller handles blocks):
const results = await guard.evaluateBatch([
{ tool: 'file_read', args: { path: '/data/report.csv' } },
{ tool: 'send_email', args: { to: '[email protected]' } },
]);Express / Fastify
import express from 'express';
import { expressMiddleware } from '@the-bot-club/agentguard';
const app = express();
app.use(expressMiddleware({ apiKey: 'ag_...' }));
// `req.agentguard` is now available in all route handlers:
app.post('/run-agent', async (req, res) => {
const decision = await req.agentguard.evaluate({
tool: req.body.tool,
params: req.body.params,
});
if (decision.result !== 'allow') {
return res.status(403).json({ error: 'blocked', reason: decision.reason });
}
// ... proceed
});Fastify:
import { fastifyMiddleware } from '@the-bot-club/agentguard';
app.addHook('preHandler', fastifyMiddleware({ apiKey: 'ag_...' }));Batch Evaluate
Evaluate multiple tool calls in a single round-trip (1–50 calls):
const batch = await guard.evaluateBatch({
agentId: 'my-agent',
calls: [
{ tool: 'file_read', params: { path: '/data/report.csv' } },
{ tool: 'send_email', params: { to: '[email protected]' } },
{ tool: 'exec', params: { cmd: 'rm -rf /' } },
],
});
console.log(`${batch.summary.blocked}/${batch.summary.total} calls blocked`);
for (const result of batch.results) {
if (result.decision === 'block') {
console.log(`[${result.tool}] BLOCKED: ${result.reason}`);
console.log(` Suggestion: ${result.suggestion}`);
console.log(` Docs: ${result.docs}`);
}
}LangChain Integration (Core Wrapper)
For local in-process policy enforcement with a full PolicyEngine, use the lower-level AgentGuardToolWrapper:
import { AgentGuardToolWrapper } from '@the-bot-club/agentguard';
import { DynamicTool } from 'langchain/tools';
// Your existing LangChain tool
const emailTool = new DynamicTool({
name: 'send_email',
description: 'Send an email',
func: async (input) => {
// ... send email logic
return 'Email sent';
},
});
// Wrap with AgentGuard policy enforcement
const wrapper = new AgentGuardToolWrapper(engine, auditLogger, killSwitch, agentContext);
const guardedTool = wrapper.wrap(emailTool);
// Use the guarded tool in your LangChain agent — policy is enforced automatically
const result = await guardedTool.invoke({ input: '{"to":"[email protected]"}' });API Reference
AgentGuard (Cloud Client)
| Method | Description |
|---|---|
| evaluate(action) | Evaluate a tool call against your hosted policy |
| getUsage() | Get usage stats for your tenant |
| getAudit(options?) | Retrieve audit trail events |
| killSwitch(active) | Activate (true) or deactivate (false) global kill switch |
| createWebhook(config) | Register a new webhook endpoint |
| listWebhooks() | List all webhook subscriptions |
| deleteWebhook(id) | Delete a webhook subscription |
| createAgent(config) | Register a new agent |
| listAgents() | List all registered agents |
| deleteAgent(id) | Delete a registered agent |
| listTemplates() | List available policy templates |
| getTemplate(name) | Get a specific policy template |
| applyTemplate(name) | Apply a template to your tenant |
| setRateLimit(config) | Create a rate limit rule |
| listRateLimits() | List all rate limit rules |
| deleteRateLimit(id) | Delete a rate limit rule |
| getCostSummary(options?) | Get cost summary with optional filters |
| getAgentCosts() | Get per-agent cost breakdown |
| getDashboardStats() | Get high-level dashboard statistics |
| getDashboardFeed(options?) | Get the live activity feed |
| getAgentActivity() | Get per-agent activity summary |
PolicyEngine
| Method | Description |
|---|---|
| evaluate(request) | Evaluate an ActionRequest, returns PolicyDecision |
AuditLogger
| Method | Description |
|---|---|
| log(input) | Append an AuditEvent to the chain |
| getEvents() | Return all events |
| verify() | Verify the hash chain integrity |
KillSwitch
| Method | Description |
|---|---|
| isHalted(agentId) | Returns true if agent or global halt is active |
| haltGlobal(reason) | Halt all agents |
| haltAgent(id, reason) | Halt a specific agent |
| resumeGlobal() | Resume global operations |
| resumeAgent(id) | Resume a specific agent |
