@sovr/gate
v0.1.0
Published
SOVR Gate SDK - AI Execution Control Plane. Intercept, audit, and control AI agent actions before they execute.
Maintainers
Readme
@sovr/gate
AI Execution Control Plane — Intercept, audit, and control AI agent actions before they execute.
Why SOVR Gate?
AI agents are powerful but dangerous. They can:
- Send emails without review
- Process payments without approval
- Delete data without confirmation
- Execute irreversible actions automatically
SOVR Gate is the missing control layer between AI decision and real-world execution.
Without SOVR Gate:
AI Agent → Direct Execution → 💥 Irreversible Error
With SOVR Gate:
AI Agent → SOVR Gate → Human Approval → Safe Execution ✓Installation
npm install @sovr/gate
# or
yarn add @sovr/gate
# or
pnpm add @sovr/gateQuick Start
import { createGate } from '@sovr/gate';
// Create a gate instance
const gate = createGate({
defaultDeny: true, // Block unregistered actions
irreversibleActions: [
'send_email',
'process_payment',
'delete_user',
],
});
// Before executing any action, check with the gate
async function executeAction(action) {
const result = await gate.check({
type: action.type,
resource: action.resource,
params: action.params,
});
if (result.allowed) {
// ✅ Safe to execute
return performAction(action);
}
if (result.requiresApproval) {
// ⏳ Needs human approval
console.log(`Waiting for approval: ${result.pendingApprovalId}`);
return { status: 'pending_approval', id: result.pendingApprovalId };
}
// ❌ Blocked
throw new Error(`Action blocked: ${result.reason}`);
}Core Concepts
1. Action Types
Every action has a type that determines how it's handled:
| Type | Example | Default Behavior |
|------|---------|------------------|
| Read | get_user, list_orders | ✅ Always allowed |
| Write | create_order, update_user | ⚠️ Logged |
| Irreversible | delete_user, process_payment | 🛑 Requires approval |
2. Gate Verdicts
| Verdict | Meaning |
|---------|---------|
| ALLOW | Action can proceed |
| DENY | Action is blocked |
| PENDING_APPROVAL | Waiting for human approval |
3. Kill Switch
Emergency stop all AI actions:
// Something went wrong? Stop everything immediately
gate.enableKillSwitch('Security incident detected');
// All actions are now blocked
const result = await gate.check({ type: 'any_action', resource: 'any' });
// result.allowed === false
// result.reason === 'Kill switch enabled: Security incident detected'
// Resume when safe
gate.disableKillSwitch();LangChain Integration
Wrap Individual Tools
import { createGate, wrapTool } from '@sovr/gate';
import { SerpAPI } from 'langchain/tools';
const gate = createGate();
const searchTool = wrapTool(new SerpAPI(), gate);
// Tool calls are now gatedCallback Handler (Recommended)
import { createGate, createCallbackHandler } from '@sovr/gate';
import { AgentExecutor } from 'langchain/agents';
const gate = createGate({
defaultDeny: true,
approvalRequired: ['send_email', 'execute_code'],
});
const handler = createCallbackHandler(gate, {
blockOnDeny: true,
contextProvider: async () => ({
userId: getCurrentUserId(),
tenantId: getTenantId(),
}),
});
const agent = new AgentExecutor({
// ... your agent config
callbacks: [handler],
});LCEL Middleware
import { createGate, gateMiddleware } from '@sovr/gate';
import { RunnableSequence } from 'langchain/runnables';
const gate = createGate();
const chain = RunnableSequence.from([
gateMiddleware(gate, 'process_data'),
myDataProcessor,
gateMiddleware(gate, 'send_notification'),
notificationSender,
]);Human Approval Flow
const gate = createGate({
irreversibleActions: ['process_refund'],
webhooks: {
onPendingApproval: 'https://your-app.com/webhooks/approval',
},
});
// 1. Check action (will return PENDING_APPROVAL)
const result = await gate.check({
type: 'process_refund',
resource: 'payment',
params: { amount: 1000, orderId: 'ord_123' },
});
console.log(result.requiresApproval); // true
console.log(result.pendingApprovalId); // 'apr_abc123'
// 2. Human reviews and approves
await gate.approve(result.pendingApprovalId, '[email protected]', 'Verified refund request');
// 3. Now the action can proceedConfiguration
const gate = createGate({
// Tenant/organization ID
tenantId: 'my-company',
// Enable/disable the gate (kill switch)
enabled: true,
// Block actions not in allowList (zero-trust mode)
defaultDeny: true,
// Actions that bypass all checks
allowList: ['get_status', 'list_items'],
// Actions that are always blocked
blockList: ['delete_database', 'shutdown_server'],
// Actions requiring human approval
approvalRequired: ['send_bulk_email', 'publish_content'],
// Irreversible actions (always require approval)
irreversibleActions: [
'process_payment',
'delete_user',
'send_email',
],
// Risk thresholds
riskThresholds: {
maxAmount: 100000, // Block amounts above this
highRiskAmount: 10000, // Flag amounts above this
blockedCountries: ['XX', 'YY'],
},
// Webhooks
webhooks: {
onPendingApproval: 'https://your-app.com/webhooks/approval',
onDecision: 'https://your-app.com/webhooks/decision',
},
});Custom Storage
By default, SOVR Gate uses in-memory storage. For production, implement your own:
import { createGate, StorageAdapter } from '@sovr/gate';
class PostgresStorage implements StorageAdapter {
async saveDecision(decision) {
await db.insert('sovr_decisions', decision);
}
async getDecision(decisionId) {
return db.findOne('sovr_decisions', { id: decisionId });
}
// ... implement other methods
}
const gate = createGate({
storage: new PostgresStorage(),
});Evidence Trail
Every decision creates an immutable evidence bundle:
const result = await gate.check({ type: 'send_email', resource: 'email' });
console.log(result.evidence);
// {
// id: 'evt_abc123',
// chain: [
// {
// id: 'rec_xyz',
// type: 'gate_decision',
// contentHash: 'sha256:...',
// prevHash: '0000...',
// timestamp: '2024-01-01T00:00:00Z',
// }
// ],
// integrityHash: 'sha256:...',
// }API Reference
createGate(config?)
Create a new gate instance.
gate.check(action, context?)
Check if an action is allowed.
gate.approve(approvalId, approvedBy, reason?)
Approve a pending action.
gate.reject(approvalId, rejectedBy, reason?)
Reject a pending action.
gate.enableKillSwitch(reason)
Emergency stop all actions.
gate.disableKillSwitch()
Resume normal operation.
gate.listPendingApprovals(tenantId?)
List all pending approvals.
License
MIT © SOVR
Questions? docs.sovrapp.com | Discord | [email protected]
