Note: MoltPermit is in early development (0.x). APIs may change between minor versions. Production use is not recommended yet.
Permissions and policy control plane for autonomous AI agents.
Part of the Molt ecosystem:
- MoltDoor — Agent reputation and review platform
- MoltCaptcha — AI verification via semantic-mathematical challenges
- MoltPermit — Permissions and policy enforcement (this project)
MoltPermit sits between AI agents and tool-calling endpoints (MCP servers, APIs, etc.) to enforce scoped, auditable, and reversible actions based on Cedar policies and agent trust tiers.
npm install moltpermitimport { MoltPermit } from 'moltpermit';
const permit = new MoltPermit({
policies: './policies/default.cedar',
audit: { store: 'sqlite', path: './audit.db' },
});
const decision = await permit.evaluate({
agent: { id: 'agent-123', verificationTier: 'moltcaptcha' },
action: { type: 'read', resource: 'invoices', parameters: {} },
context: { timestamp: new Date().toISOString(), environment: 'production' },
});
console.log(decision.decision); // 'allow' or 'deny'You can also deploy to Render or DigitalOcean App Platform using the included config files.
┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
│ AI Agent │────▶│ MoltPermit │────▶│ MCP Server / │
│ │ │ (Policy │ │ Tool Endpoint │
│ │◀────│ Engine) │◀────│ │
└─────────────┘ └──────┬───────┘ └─────────────────┘
│
┌────────────┼────────────┐
▼ ▼ ▼
┌────────────┐ ┌─────────┐ ┌──────────┐
│ MoltDoor │ │ Audit │ │ Budget │
│ (Trust & │ │ Log │ │ Tracker │
│ Reputation)│ │ (SQLite)│ │ (SQLite) │
└────────────┘ └─────────┘ └──────────┘
MoltPermit uses a progressive trust model based on agent verification:
| Tier | Requirements | Access Level |
|---|---|---|
| Unverified | None | Read-only, rate-limited |
| MoltCaptcha Verified | Passed MoltCaptcha challenge | Scoped API access |
| Blockchain Verified | ERC-8004 on-chain identity | Broader scopes, longer sessions |
| Reputation-Backed | All above + MoltDoor rating >= 4.0 | Full autonomous operation |
MoltPermit uses Amazon Cedar policy syntax for authorization rules:
// Allow reputation-backed agents to perform admin actions
permit(
principal is Agent,
action == MoltPermit::Action::"admin",
resource
)
when {
principal.verificationTier == "reputation" &&
principal.reputationScore >= 4
};
// Deny unverified agents from write operations
forbid(
principal is Agent,
action == MoltPermit::Action::"write",
resource
)
when {
principal.verificationTier == "unverified"
};
Every operation goes through MoltPermit as an ActionRequest:
{
agent: {
id: 'agent-123',
verificationTier: 'moltcaptcha',
reputationScore: 4,
},
action: {
type: 'billing.refund_invoice',
resource: 'invoice-456',
parameters: { amount: 50 },
},
context: {
timestamp: '2024-01-15T10:00:00Z',
environment: 'production',
humanSponsor: 'user@company.com',
},
}Every policy decision is logged to SQLite with full request/response context:
const logs = permit.queryLogs({
agentId: 'agent-123',
decision: 'deny',
since: '2024-01-01',
limit: 50,
});Rate-limit agents per action type with configurable windows:
const permit = new MoltPermit({
budgets: {
'tools/call': { perAgent: 100, perHour: 50 },
'tools/dangerous': { perAgent: 10, perHour: 5 },
'billing.refund': { perAgent: 20, maxValuePerAction: 100 },
},
});On allow decisions, MoltPermit mints short-lived, single-use tokens:
const decision = await permit.evaluate(request);
if (decision.decision === 'allow') {
// decision.scopedCredential contains:
// { token, expiresAt, scopes, restrictions }
const result = await executeWithToken(decision.scopedCredential.token);
await permit.recordOutcome(decision.auditId, 'success');
}For SSE, stdio, or any non-HTTP transport, use the toolCallInterceptor() directly:
import { MoltPermit } from 'moltpermit';
const permit = new MoltPermit({
policies: './policies/default.cedar',
});
// For any transport (SSE, stdio, HTTP):
const interceptor = permit.toolCallInterceptor();
// Before executing any tool call:
const result = await interceptor.interceptToolCall({
agentId: 'agent-123',
toolName: 'weather',
toolArguments: { city: 'NYC' },
});
if (!result.allowed) {
// deny the tool call
}Register rollback callbacks when evaluating actions, so they can be undone later:
const decision = await permit.evaluateWithRollback(
request,
async () => {
// Undo the action
await reverseRefund(request.action.parameters.invoiceId);
}
);
// Later, if something goes wrong:
const result = await permit.rollback(decision.auditId);
if (!result.success) {
console.error('Rollback failed:', result.error);
}Use MoltPermit as Express middleware to protect MCP servers:
import express from 'express';
import { MoltPermit } from 'moltpermit';
const app = express();
const permit = new MoltPermit({
policies: './policies/default.cedar',
audit: { store: 'sqlite', path: './audit.db' },
});
// Apply MCP authorization middleware
app.use('/mcp', permit.mcpMiddleware());
// Your MCP handler
app.post('/mcp', (req, res) => {
// Request has been authorized by MoltPermit
// req.policyDecision contains the decision details
res.json({ result: 'ok' });
});MoltPermit automatically enriches agent trust data from MoltDoor:
const permit = new MoltPermit({
moltdoor: {
baseUrl: 'https://moltdoor.net',
cacheSeconds: 300,
},
});
// Agent attributes are fetched and cached from MoltDoor
const attrs = await permit.getAgentAttributes('agent-123');
// { verificationTier, reputationScore, hasOnChainId, badges }# Test a policy against an action
moltpermit test --policy ./policies/default.cedar \
--agent '{"id":"agent-1","verificationTier":"moltcaptcha"}' \
--action '{"type":"read","resource":"data"}'
# Validate Cedar policy files
moltpermit validate ./policies/
# Query audit logs
moltpermit logs --db ./audit.db --agent agent-1 --decision deny --since 2024-01-01
# Start standalone server
moltpermit serve --port 3001 --policies ./policies/Start with moltpermit serve or programmatically:
import { MoltPermit, createServer } from 'moltpermit';
const permit = new MoltPermit({ /* config */ });
const server = createServer(permit, { port: 3001 });
server.start();| Method | Path | Description |
|---|---|---|
POST |
/evaluate |
Evaluate an ActionRequest |
POST |
/onboard |
Onboard agent via MoltCaptcha |
GET |
/logs |
Query audit logs |
GET |
/budget/:agentId |
Check remaining budget |
POST |
/rollback/:auditId |
Rollback a reversible action |
POST |
/reload |
Reload policies from disk |
GET |
/health |
Health check |
Cedar policies consist of permit and forbid rules:
// Permit rules grant access
permit(
principal is Agent, // Who
action == Action::"read", // What
resource // On what (any resource)
)
when {
// Conditions (optional)
principal.verificationTier == "moltcaptcha"
};
// Forbid rules deny access (override permits)
forbid(
principal is Agent,
action == Action::"delete",
resource
)
when {
resource.sensitivity == "high"
};
- Default deny: If no permit matches, the action is denied
- Forbid overrides permit: If both match, the action is denied
- Conditions use
&&: All conditions in awhenblock must be true
// Read: all agents
permit(principal is Agent, action == Action::"read", resource);
// Write: verified agents only
permit(principal is Agent, action == Action::"write", resource)
when { principal.verificationTier != "unverified" };
// Admin: reputation-backed only
permit(principal is Agent, action == Action::"admin", resource)
when {
principal.verificationTier == "reputation" &&
principal.reputationScore >= 4
};
See examples/mcp-weather-agent/ for a complete working example that demonstrates:
- Three agents with different trust tiers (unverified, moltcaptcha, reputation)
- Policy enforcement on read/write/delete operations
- Audit logging, budget tracking, and reversible actions
- Full request/response flow with console output
cd examples/mcp-weather-agent && npm install && npm start
# In another terminal:
npm run agent- MoltDoor — Agent reputation platform
- MoltDoor GitHub — MoltDoor source code
- Amazon Cedar — Policy language specification
Apache 2.0 — see LICENSE for details.