Skip to content
This repository was archived by the owner on Apr 4, 2026. It is now read-only.

BigHandsDan/moltpermit

Repository files navigation

MoltPermit

License: Apache 2.0 npm version

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)

What is MoltPermit?

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.

Quick Start

npm install moltpermit
import { 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'

Deploy

Deploy on Railway

You can also deploy to Render or DigitalOcean App Platform using the included config files.

Architecture

┌─────────────┐     ┌──────────────┐     ┌─────────────────┐
│   AI Agent   │────▶│  MoltPermit  │────▶│  MCP Server /   │
│              │     │  (Policy     │     │  Tool Endpoint  │
│              │◀────│   Engine)    │◀────│                 │
└─────────────┘     └──────┬───────┘     └─────────────────┘
                           │
              ┌────────────┼────────────┐
              ▼            ▼            ▼
       ┌────────────┐ ┌─────────┐ ┌──────────┐
       │  MoltDoor   │ │  Audit  │ │  Budget  │
       │  (Trust &   │ │  Log    │ │  Tracker │
       │  Reputation)│ │ (SQLite)│ │ (SQLite) │
       └────────────┘ └─────────┘ └──────────┘

Core Concepts

Trust Tiers

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

Cedar Policies

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"
};

Action Requests

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',
  },
}

Audit Logging

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,
});

Action Budgets

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 },
  },
});

JIT Scoped Credentials

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');
}

Transport-Agnostic Interceptor

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
}

Actionable Rollbacks

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);
}

MCP Integration

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' });
});

MoltDoor Integration

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 }

CLI Reference

# 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/

Standalone Server API

Start with moltpermit serve or programmatically:

import { MoltPermit, createServer } from 'moltpermit';

const permit = new MoltPermit({ /* config */ });
const server = createServer(permit, { port: 3001 });
server.start();

Endpoints

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

Policy Writing Guide

Basic Structure

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"
};

Key Rules

  1. Default deny: If no permit matches, the action is denied
  2. Forbid overrides permit: If both match, the action is denied
  3. Conditions use &&: All conditions in a when block must be true

Example: Tiered Access

// 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
};

Example: Weather API with Trust Tiers

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

Links

License

Apache 2.0 — see LICENSE for details.

About

⚠️ ARCHIVED — Moved to https://github.com/BigHandsDan/molt (packages/permit)

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors