trustloop
v1.0.0
Published
AI governance SDK — intercept, audit, and control AI agent tool calls. Add human-in-the-loop approval, kill switches, and a full audit trail to any AI agent.
Maintainers
Readme
trustloop
AI governance SDK for Node.js — add human-in-the-loop approval, kill switches, and a tamper-evident audit trail to any AI agent in minutes.
What is TrustLoop?
When an AI agent calls a tool — sends an email, writes to a database, approves a wire transfer — TrustLoop intercepts that action before it executes, evaluates it against your governance rules, and either:
- Allows it (logs to audit trail)
- Blocks it (kill switch or rule match)
- Holds it for human approval (notifies via email, Slack, Teams, or Discord)
Works with OpenAI function calling, MCP (Model Context Protocol), LangChain, CrewAI, and any agent framework.
Installation
npm install trustloopRequires Node.js 18+. No dependencies.
Quick Start
Option A — OpenAI Proxy (2-line change)
Point your existing OpenAI client at TrustLoop. All tool calls are governed automatically, with zero changes to your agent code.
import OpenAI from 'openai';
import TrustLoop from 'trustloop';
// Before: new OpenAI({ apiKey: 'sk-...' })
// After:
const client = new OpenAI(
TrustLoop.openai('sk-your-openai-key', 'tl_your-trustloop-key')
);
// Your agent code is unchanged — governance is automatic
const response = await client.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: 'Transfer £50,000 to SG-7731' }],
tools: [/* your tools */],
});Get your TrustLoop API key at trustloop.live/signup — free, no credit card.
Option B — Manual Intercept
Check each tool call explicitly before running it:
import TrustLoop from 'trustloop';
const tl = new TrustLoop({ apiKey: 'tl_your-key' });
async function runTool(toolName, args) {
const check = await tl.intercept(toolName, args);
if (check.allowed) {
return await yourToolImplementation(toolName, args);
}
if (check.status === 'PENDING') {
return `Awaiting human approval (ID: ${check.approval_id})`;
}
throw new Error(`Blocked by TrustLoop: ${check.message}`);
}
// Usage
await runTool('send_email', { to: '[email protected]', subject: 'Wire Transfer' });Option C — MCP (Claude Desktop, Cline)
Add TrustLoop to your Claude Desktop config:
{
"mcpServers": {
"trustloop": {
"url": "https://trustloop-production.up.railway.app/sse?api_key=tl_your-key"
}
}
}Or use the helper:
import TrustLoop from 'trustloop';
console.log(TrustLoop.mcpUrl('tl_your-key'));
// https://trustloop-production.up.railway.app/sse?api_key=tl_your-keyGovernance Rules
Create rules in plain English. TrustLoop's AI evaluates every tool call against your rules in real time.
const tl = new TrustLoop({ apiKey: 'tl_your-key' });
// Block a class of tools outright
await tl.createRule({
rule_text: 'Block all delete_customer_data calls immediately',
action: 'block',
});
// Require human approval for high-value actions
await tl.createRule({
rule_text: 'Any wire transfer over £1,000 requires human approval',
action: 'approve',
approver_email: '[email protected]',
});
// Require approval for sensitive data exports
await tl.createRule({
rule_text: 'Any data export with include_pii=true requires approval',
action: 'approve',
});When a rule fires with action: 'approve', the tool call is held and your approver receives an email (plus Slack/Teams/Discord if configured) with one-click Approve and Deny links.
Kill Switch
Instantly block a tool by name — no rule evaluation, no delay:
// Emergency block
await tl.blockTool('drop_table', 'Emergency: destructive DB operations disabled');
await tl.blockTool('delete_all_records');
// List blocked tools
const blocked = await tl.getBlockedTools();
// Unblock when safe
await tl.unblockTool('drop_table');Audit Log
Every tool call is logged permanently with full arguments, status, and which rule matched:
// Get recent logs
const logs = await tl.getLogs({ limit: 100 });
// [{ tool_name, arguments, status, rule_matched, created_at }, ...]
// Filter by status
const blocked = await tl.getLogs({ status: 'BLOCKED' });
// Export as CSV (for compliance)
const csv = await tl.exportLogs();
fs.writeFileSync('audit.csv', csv);
// Get stats
const stats = await tl.getStats();
// { total: 1420, allowed: 1380, blocked: 32, pending: 8, usage: { plan: 'free', used: 1420, limit: 5000 } }Pending Approvals
// See what's waiting
const pending = await tl.getPendingApprovals();
// Approve or deny programmatically
await tl.decide(pending[0].id, 'approved');
await tl.decide(pending[1].id, 'denied');Notifications
Configure where approval requests are sent:
await tl.updateNotifications({
notify_email: '[email protected]',
slack_webhook_url: 'https://hooks.slack.com/services/...',
teams_webhook_url: 'https://yourcompany.webhook.office.com/...',
discord_webhook_url: 'https://discord.com/api/webhooks/...',
});Full API Reference
| Method | Description |
|--------|-------------|
| tl.intercept(toolName, args) | Check a tool call — returns ALLOWED, BLOCKED, or PENDING |
| tl.getLogs(options?) | Fetch audit log entries |
| tl.exportLogs() | Export full audit log as CSV |
| tl.getStats() | Dashboard stats and monthly usage |
| tl.getRules() | List governance rules |
| tl.createRule({ rule_text, action, approver_email }) | Create a governance rule |
| tl.deleteRule(ruleId) | Delete a rule |
| tl.getBlockedTools() | List kill-switched tools |
| tl.blockTool(toolName, reason?) | Block a tool immediately |
| tl.unblockTool(toolName) | Remove a tool from the block list |
| tl.getPendingApprovals() | List tool calls awaiting human approval |
| tl.decide(approvalId, action) | Approve or deny programmatically |
| tl.getNotifications() | Get notification settings |
| tl.updateNotifications(settings) | Update notification channels |
| TrustLoop.openai(openaiKey, tlKey) | Get config for OpenAI client |
| TrustLoop.mcpUrl(tlKey) | Get MCP SSE URL for Claude Desktop |
Error Handling
import TrustLoop, { TrustLoopError } from 'trustloop';
try {
const result = await tl.intercept('send_email', { to: '...' });
} catch (err) {
if (err instanceof TrustLoopError) {
console.error(`TrustLoop API error ${err.status}: ${err.message}`);
}
}TypeScript
Full TypeScript support included — no @types package needed.
import TrustLoop, { InterceptResult, Rule, Stats } from 'trustloop';
const tl = new TrustLoop({ apiKey: 'tl_your-key' });
const result: InterceptResult = await tl.intercept('my_tool', { param: 'value' });Why TrustLoop?
| | LangSmith / Arize | TrustLoop | |---|---|---| | What it monitors | LLM API layer (what the model said) | Tool execution layer (what the agent did) | | Kill switch | No | Yes | | Human approval workflow | No | Yes | | Blockchain audit trail | No | Yes | | EU AI Act compliance | No | Yes | | Works with any agent framework | No | Yes |
Links
- Sign up free: trustloop.live/signup
- Dashboard: app.trustloop.live
- Docs: trustloop.live/docs
- Website: trustloop.live
License
MIT © TrustLoop Ltd
