Skip to main content

Platform Intelligence Layer — context governance for autonomous agents

Project description

AutoPIL — Platform Intelligence Layer

Context governance middleware for autonomous AI agents.

AutoPIL sits between your agents and your data sources, enforcing who can retrieve what, under what conditions — and logging every access decision with an immutable audit trail.

Agent → @guard.protect(...) → Policy Engine → Data Source
                    ↓                ↓
              Audit Log       AlertEngine → webhook / email
                    ↓
              OTEL Spans + Metrics → Datadog / Grafana / Splunk

Why AutoPIL

As enterprises deploy multi-agent AI systems, the gap that emerges isn't in the LLMs — it's in what context they're allowed to retrieve. Most governance tools operate at the output layer (content filtering, hallucination detection). AutoPIL operates at the retrieval layer, before sensitive data ever enters the agent's context window.

Key problems it solves:

  • An underwriting agent accessing another customer's credit data
  • A customer service bot retrieving internal risk models it has no business seeing
  • One agent in a pipeline hijacking another agent's session context
  • No audit trail of what data was retrieved and when
  • No alerting when denial spikes or policy violations occur
  • No observability in existing monitoring tooling

Architecture

┌─────────────────────────────────────────────────────────┐
│                       Your Agent                        │
└────────────────────────┬────────────────────────────────┘
                         │  @guard.protect(...)
┌────────────────────────▼────────────────────────────────┐
│                    ContextGuard                         │
│  1. Cross-agent session isolation check                 │
│  2. Policy evaluation (allow / deny)          ◄──────── PolicyEngine
│  3. OTEL span + metrics emitted                         │
│  4. Execute retrieval (if allowed)                      │
│  5. Hash context for provenance                         │
│  6. Record immutable audit event              ──────────►  AlertEngine
└──────────────┬────────────────────────┬─────────────────┘
               │                        │
┌──────────────▼──────┐   ┌─────────────▼───────────────┐
│   Storage Backend   │   │   OTEL Collector             │
│   SQLite (default)  │   │   Datadog / Grafana / Splunk │
│   Postgres (prod)   │   └─────────────────────────────┘
└─────────────────────┘

Enforcement mechanisms:

Mechanism Description
Source allowlist Agent can only access explicitly permitted data sources
Source denylist Certain sources are always blocked, regardless of allowlist
Sensitivity ceiling Each role has a maximum data sensitivity level it can access
Task scoping Roles can be restricted to specific task types (allowed_tasks / denied_tasks)
Cross-agent isolation A session belongs to the first agent that used it — others are denied
Session lifecycle Sessions expire by TTL or can be revoked; expired/revoked sessions are denied
Default deny No matching policy = access denied

Integration modes:

Mode How it works Best for
Python decorator @guard.protect(...) wraps retrieval functions directly LangGraph, LangChain, custom Python agents
REST API POST /v1/context/evaluate from any language Polyglot stacks, TypeScript, Java, Go
MCP server evaluate_context / record_action as native MCP tools Claude Desktop, GPT-4, Gemini, any MCP-compatible agent
FastAPI / ASGI middleware AutoPILMiddleware intercepts requests at the API layer Enforcing governance without touching agent code
AWS Bedrock Agents BedrockGuard.wrap_invoke_agent() Bedrock-hosted agents
LangChain / LangGraph LangChainGuard.wrap_tool() LangChain tools and graphs
LlamaIndex LlamaIndexGuard.wrap_query_engine() LlamaIndex query engines
OpenAI Agents SDK OpenAIAgentsGuard@guard.function_tool() decorator OpenAI Assistants and function tools
Gemini GeminiGuard.call_if_allowed() Gemini-based agents

Integration channels — source_type values:

Channel Class source_type
REST API ContextGuard + FastAPI rest
MCP MCPGuard / mcp server mcp
Python SDK ContextGuard sdk
FastAPI / ASGI AutoPILMiddleware api
AWS Bedrock Agents BedrockGuard bedrock
LangChain / LangGraph LangChainGuard langchain
LlamaIndex LlamaIndexGuard llamaindex
OpenAI Agents SDK OpenAIAgentsGuard openai_agents
Gemini GeminiGuard gemini

Every audit event is stamped with the source_type of the channel that produced it. The /v1/audit/stats endpoint returns a by_source_type breakdown showing totals, allowed, and denied counts per channel.


Quickstart

Install

pip install -e .

For the REST server:

pip install -e ".[server]"

For OpenTelemetry (gRPC — Datadog, Splunk):

pip install -e ".[otel]"

For OpenTelemetry (HTTP — Grafana Cloud):

pip install -e ".[otel-http]"

For the MCP server (Claude Desktop, GPT-4, Gemini, any MCP-compatible agent):

pip install -e ".[mcp]"

For Postgres:

pip install -e ".[postgres]"

Define a policy

# policies/my_policy.yaml
policies:
  - name: analyst_policy
    agent_role: analyst
    allowed_sources:
      - reports
      - market_data
    denied_sources:
      - executive_comms
    max_sensitivity: high
    allowed_tasks:       # optional — restrict to specific task types
      - summarization
      - qa
    denied_tasks:        # optional — block specific task types
      - extraction

Wrap your retrieval functions

from autopil import ContextGuard, SensitivityLevel

guard = ContextGuard(
    policy_path="policies/my_policy.yaml",
    audit_db="autopil.db",
)

@guard.protect(
    agent_role="analyst",
    user_id="user_123",
    source_id="reports",
    sensitivity_level=SensitivityLevel.HIGH,
    session_id="session_abc",
)
def retrieve_reports(query: str) -> list:
    return vectorstore.search(query)

# Authorized — returns results
results = retrieve_reports("Q3 performance")

# Unauthorized — raises PermissionError, logs the denial
results = retrieve_reports_from_exec_comms("board notes")

For async agents, use protect_async instead:

@guard.protect_async(
    agent_role="analyst",
    user_id="user_123",
    source_id="reports",
    sensitivity_level=SensitivityLevel.HIGH,
    session_id="session_abc",
)
async def retrieve_reports_async(query: str) -> list:
    return await vectorstore.asearch(query)

protect_async uses contextvars.ContextVar for last_event_id, so concurrent asyncio Tasks never overwrite each other's state.

View the audit trail

events = guard.get_audit_trail("session_abc")
for e in events:
    print(e.decision, e.source_id, e.context_hash)

Framework Integrations

LangChain

from autopil import LangChainGuard

guard = LangChainGuard(policy_path="policies/", audit_db="autopil.db")
safe_tool = guard.wrap_tool(my_langchain_tool, agent_role="analyst", source_id="reports")

LlamaIndex

from autopil import LlamaIndexGuard

guard = LlamaIndexGuard(policy_path="policies/", audit_db="autopil.db")
safe_engine = guard.wrap_query_engine(query_engine, agent_role="analyst", source_id="docs")
result = await safe_engine.aquery("Q3 summary")

AWS Bedrock Agents

from autopil import BedrockGuard

guard = BedrockGuard(policy_path="policies/", audit_db="autopil.db")
safe_invoke = guard.wrap_invoke_agent(agent_role="analyst", source_id="bedrock_kb")
response = safe_invoke(agentId=..., sessionId=..., inputText="...")

FastAPI / ASGI Middleware

from autopil import AutoPILMiddleware, RouteRule

app.add_middleware(
    AutoPILMiddleware,
    guard=guard,
    rules=[RouteRule(path="/v1/retrieve/{doc_id}", agent_role="analyst",
                     source_id="reports", sensitivity_level="high")],
)

Denied requests receive a 403 JSON response. Set on_deny="log" on a RouteRule for shadow/dry-run mode — the request passes through but the denial is still recorded.


Running the API Server

First start

On first start, AutoPIL creates a default tenant and prints a one-time superadmin API key:

  AutoPIL API Server
  Policy   : policies/
  Database : sqlite @ autopil_audit.db

  ⚠  First start — created 'default' tenant and superadmin key:
     apl_<your-key-here>
     Save this — it will not be shown again.

  Docs     : http://localhost:8000/docs

Use this key in the X-API-Key header for all API requests.

Local development (two terminals)

Terminal 1 — backend:

cd packages/core
python3.11 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
python3 serve.py --policy policies/

Terminal 2 — dashboard:

cd packages/dashboard
npm install
npm run dev

Open http://localhost:5173 for the dashboard (Vite proxies API calls to :8000 automatically). Open http://localhost:8000/docs for the interactive API docs.

With OpenTelemetry

export OTEL_SERVICE_NAME=autopil
export OTEL_EXPORTER_OTLP_ENDPOINT=https://otel-collector.mycompany.com:4317
python3 serve.py --policy policies/

The server prints OTEL: <endpoint> on startup when OTEL is configured.

With Postgres

export DATABASE_URL=postgresql://user:pass@localhost:5432/autopil
python serve.py --policy policies/

Docker

docker compose up --build

The server starts on http://localhost:8000.

  • Dashboard: http://localhost:8000
  • API docs: http://localhost:8000/docs

Alerting

AutoPIL includes a rules engine that monitors the audit log and fires notifications when anomalies are detected. Rules are created via the REST API and evaluated synchronously on every audit event.

Rule types

Type Fires when
denial_spike X denials occur within N minutes
new_source A source_id is accessed that has never appeared in the audit log before
isolation_violation A cross-agent session isolation violation is recorded
high_deny_rate Denial percentage exceeds a threshold within a time window

Create an alert rule

curl -X POST http://localhost:8000/v1/alerts/rules \
  -H "X-API-Key: apl_yourkey" \
  -H "Content-Type: application/json" \
  -d '{
    "name":             "denial spike",
    "rule_type":        "denial_spike",
    "threshold":        10,
    "window_minutes":   15,
    "cooldown_minutes": 30,
    "webhook_url":      "https://hooks.slack.com/services/..."
  }'

Rules can deliver to a webhook URL (HTTP POST with JSON payload) or an email address (requires SMTP_HOST env var). Both can be set on the same rule.

Alert endpoints

POST   /v1/alerts/rules                — create alert rule
GET    /v1/alerts/rules                — list rules for this tenant
PUT    /v1/alerts/rules/{rule_id}      — update a rule
DELETE /v1/alerts/rules/{rule_id}      — delete a rule
GET    /v1/alerts/fired                — recent alert deliveries

OpenTelemetry

AutoPIL emits OTEL spans and metrics from every policy evaluation. When OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_TRACES_EXPORTER is set, the integration is active. When neither is set, there is zero overhead — all OTEL instruments are no-ops.

Span

Every evaluation emits an autopil.evaluate span with attributes:

Attribute Value
autopil.agent_role The role making the request
autopil.source_id The data source requested
autopil.tenant_id Tenant identifier
autopil.session_id Session identifier
autopil.sensitivity_level Sensitivity level (if provided)
autopil.decision ALLOW or DENY
autopil.policy_name Policy that matched
autopil.reason Human-readable decision reason
autopil.latency_ms Evaluation latency in milliseconds

DENY decisions set StatusCode.ERROR on the span.

Metrics

Metric Type Description
autopil.evaluate.count Counter Total evaluations, tagged with decision and tenant_id
autopil.evaluate.denied.count Counter Denied evaluations, tagged with decision
autopil.evaluate.duration Histogram (ms) Evaluation latency

Configuration

Variable Description
OTEL_SERVICE_NAME Service name in traces (default: autopil)
OTEL_EXPORTER_OTLP_ENDPOINT OTLP collector endpoint (grpc:// or https://)
OTEL_EXPORTER_OTLP_HEADERS Comma-separated key=value auth headers
OTEL_TRACES_EXPORTER Set to console for local span output
OTEL_METRICS_EXPORTER Set to console for local metrics output

SDKs

TypeScript / Node

npm install @vibrantcapital/autopil
import { AutoPilClient } from "@vibrantcapital/autopil";

const client = new AutoPilClient({
  baseUrl: "https://api.autopil.ai",
  apiKey:  process.env.AUTOPIL_API_KEY!,
});

const result = await client.context.evaluate({
  query:      "Q3 earnings summary",
  agent_role: "analyst",
  user_id:    "u_123",
  source_id:  "financial_reports",
});

if (result.decision === "DENY") {
  throw new Error(`Access denied: ${result.reason}`);
}

Zero runtime dependencies. Requires Node 18+. See sdk/typescript/ for the full reference.

Go

go get github.com/vibrantcapital/autopil-go

Stdlib only — no third-party dependencies. Covers all resources: Context, Audit, Sessions, Policies. See sdk/go/ for the full reference.

Java

<dependency>
  <groupId>ai.vibrantcapital</groupId>
  <artifactId>autopil-java</artifactId>
  <version>0.1.0</version>
</dependency>

Jackson only. Builder-pattern models for all resources. See sdk/java/ for the full reference.


MCP Server

AutoPIL ships an MCP (Model Context Protocol) server that exposes governance as native tools for any MCP-compatible agent — Claude, GPT-4, Gemini, or any custom agent that speaks MCP. No code changes required in the agent; the governance layer sits between the model and your data.

Install

pip install -e ".[mcp]"

Start the server

python mcp_serve.py --policy policies/ --db autopil.db
# or via the installed console script:
autopil-mcp --policy policies/ --db autopil.db

Claude Desktop configuration

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "autopil": {
      "command": "python",
      "args": ["/path/to/mcp_serve.py", "--policy", "/path/to/policies/"],
      "env": {}
    }
  }
}

Available tools

Tool Description
evaluate_context Policy check before retrieval — returns ALLOW or DENY with reason and event_id
record_action Link a downstream decision to the audit event that authorized it
query_audit_log Query recent audit events (filterable by role, decision, session)
get_audit_stats Aggregate stats — totals, deny rate, top roles
list_policies List active policies (filterable by industry, agent_role)
reload_policies Hot-reload policies from disk without restarting
get_session_status Session summary — owner, event count, sources accessed

System prompt pattern

Before accessing any data source, call evaluate_context with agent_role, user_id,
source_id, sensitivity_level, and session_id. Only proceed if decision is ALLOW.
After retrieval, call record_action with the event_id to log what you did.

See docs/mcp_integration.md for the full reference.


API Authentication

All /v1/* endpoints require an API key in the X-API-Key header:

curl -H "X-API-Key: apl_yourkey" http://localhost:8000/v1/policies

Key management

# Create a new key (scoped to your tenant)
curl -X POST http://localhost:8000/v1/keys \
  -H "X-API-Key: apl_yourkey" \
  -H "Content-Type: application/json" \
  -d '{"name": "production_agent"}'

# List keys for your tenant
curl http://localhost:8000/v1/keys \
  -H "X-API-Key: apl_yourkey"

# Revoke a key
curl -X DELETE http://localhost:8000/v1/keys/{key_id} \
  -H "X-API-Key: apl_yourkey"

Keys are hashed (SHA-256) at rest. The plaintext is returned once at creation and never stored.


Multi-Tenancy

AutoPIL supports multiple tenants with row-level data isolation. Each tenant's audit events, policies, alert rules, API keys, and stats are fully isolated.

Create a tenant (superadmin required)

curl -X POST http://localhost:8000/v1/admin/tenants \
  -H "X-API-Key: apl_superadminkey" \
  -H "Content-Type: application/json" \
  -d '{"name": "acme_corp"}'

Response includes tenant_id and admin_key — the initial key for that tenant. Save it; it won't be shown again.


Project Structure

This is a monorepo with three packages managed via npm workspaces.

autopil/
├── packages/
│   ├── core/                        # Python backend (FastAPI + policy engine)
│   │   ├── autopil/
│   │   │   ├── __init__.py          # Public API: ContextGuard, Decision, SensitivityLevel
│   │   │   ├── models.py            # Dataclasses: ContextRequest, AuditEvent, AgentAction, enums
│   │   │   ├── policy_engine.py     # YAML policy loader — file or recursive directory
│   │   │   ├── audit_log.py         # Shim → SQLiteAuditLog
│   │   │   ├── guard.py             # ContextGuard decorator — core enforcement + action lineage
│   │   │   ├── alerting.py          # AlertEngine — threshold rules + webhook/email delivery
│   │   │   ├── telemetry.py         # OpenTelemetry spans and metrics (optional)
│   │   │   ├── cli.py               # autopil-serve entry point
│   │   │   ├── mcp_server.py        # MCP server — dispatch_tool(), create_mcp_server(), run_stdio_server()
│   │   │   ├── db/
│   │   │   │   ├── __init__.py      # create_stores() factory (7-tuple)
│   │   │   │   ├── base.py          # Abstract base classes for all store types
│   │   │   │   ├── sqlite.py        # SQLite backend (default)
│   │   │   │   └── postgres.py      # Postgres backend (production)
│   │   │   └── api/
│   │   │       ├── app.py           # FastAPI application factory
│   │   │       ├── schemas.py       # Pydantic request/response models
│   │   │       └── static/          # Built dashboard assets (copied at Docker build time)
│   │   ├── policies/                        # 45 pre-built policies across 4 industries
│   │   │   ├── financial_services/
│   │   │   │   ├── consumer_banking.yaml    # loan_underwriter, customer_service, fraud_analyst, collections_agent
│   │   │   │   ├── wealth.yaml              # wealth_advisor, investment_analyst, kyc_agent, intake_agent
│   │   │   │   ├── risk_compliance.yaml     # compliance_officer, aml_investigator, credit_risk_analyst, compliance_agent
│   │   │   │   └── operations.yaml          # settlement_agent, ops_support, data_pipeline_agent, risk_agent
│   │   │   ├── healthcare/
│   │   │   │   ├── clinical_operations.yaml # clinical_summary_agent, medication_review_agent, care_gap_agent, triage_agent
│   │   │   │   ├── revenue_cycle.yaml       # prior_auth_agent, claims_coding_agent, denial_management_agent, patient_billing_agent
│   │   │   │   └── compliance_privacy.yaml  # hipaa_audit_agent, consent_management_agent, breach_detection_agent
│   │   │   ├── telecom/
│   │   │   │   ├── network_operations.yaml  # network_fault_agent, capacity_planning_agent, change_management_agent
│   │   │   │   ├── customer_experience.yaml # cx_support_agent, churn_prediction_agent, provisioning_agent
│   │   │   │   └── fraud_assurance.yaml     # subscription_fraud_agent, revenue_assurance_agent, wangiri_detection_agent
│   │   │   └── logistics/
│   │   │       ├── supply_chain.yaml        # demand_forecast_agent, procurement_agent, inventory_reconciliation_agent
│   │   │       ├── fleet_operations.yaml    # route_optimization_agent, driver_compliance_agent, maintenance_scheduling_agent
│   │   │       └── customs_compliance.yaml  # trade_compliance_agent, sanctions_screening_agent, import_export_agent
│   │   ├── scripts/
│   │   │   └── simulate_data.py             # Populate dashboard with realistic multi-industry demo data
│   │   ├── examples/
│   │   │   ├── langgraph_demo.py            # Single agent with LangGraph
│   │   │   └── multi_agent_demo.py          # Cross-agent isolation in action
│   │   ├── tests/
│   │   │   ├── conftest.py                  # Shared fixtures
│   │   │   ├── test_policy_engine.py        # 23 policy evaluation tests
│   │   │   ├── test_audit_log.py            # 14 audit persistence tests
│   │   │   ├── test_guard.py                # 16 ContextGuard enforcement tests
│   │   │   ├── test_api.py                  # 86 REST API endpoint tests
│   │   │   ├── test_auth.py                 # 15 API key authentication tests
│   │   │   ├── test_tenants.py              # 13 multi-tenancy and isolation tests
│   │   │   ├── test_alerting.py             # 21 alerting rules and delivery tests
│   │   │   ├── test_telemetry.py            # 17 OTEL span and metrics tests
│   │   │   ├── test_policy_editor.py        # 12 policy CRUD and versioning tests
│   │   │   ├── test_multi_industry.py       # 65 multi-industry tests
│   │   │   ├── test_mcp_server.py           # 42 MCP server tool dispatch tests
│   │   │   └── test_postgres.py             # 11 Postgres backend tests (skipped unless DATABASE_URL set)
│   │   ├── Dockerfile                       # 3-stage build: dashboard → Python builder → runtime
│   │   ├── pyproject.toml
│   │   ├── mcp_serve.py             # MCP server entry point (autopil-mcp console script)
│   │   └── serve.py
│   │
│   ├── dashboard/                   # React + TypeScript control plane UI
│   │   ├── src/
│   │   │   ├── components/          # UI components (tabs, layout, drawers, charts)
│   │   │   ├── hooks/               # usePoll — background data refresh
│   │   │   ├── lib/                 # api.ts (authenticated fetch), utils.ts
│   │   │   ├── types/               # api.ts — TypeScript interfaces for all API shapes
│   │   │   ├── App.tsx              # Root component — auth, tab routing, data loading
│   │   │   ├── main.tsx             # React 18 entry point
│   │   │   └── index.css            # Dark theme design system
│   │   ├── vite.config.ts           # Vite config — dev proxy to :8000, configurable outDir
│   │   └── package.json
│   │
│   └── website/                     # Marketing site (static HTML)
│
├── sdk/
│   ├── typescript/                  # @vibrantcapital/autopil — TypeScript/Node SDK
│   │   ├── src/
│   │   │   ├── client.ts            # AutoPilClient with typed resource groups
│   │   │   ├── types.ts             # TypeScript interfaces for all shapes
│   │   │   ├── errors.ts            # AutoPilError
│   │   │   └── index.ts             # Public exports
│   │   └── test/
│   │       └── client.test.ts
│   ├── go/                          # github.com/vibrantcapital/autopil-go — Go SDK (stdlib only)
│   └── java/                        # ai.vibrantcapital:autopil-java:0.1.0 — Java SDK (Jackson only)
├── docker-compose.yml               # Postgres + AutoPIL container (uses packages/core/Dockerfile)
└── package.json                     # npm workspaces root

Policy Reference

A policy file is a YAML document with a top-level policies list. Each entry maps to one agent role.

policies:
  - name: my_policy          # Unique identifier, appears in audit log
    agent_role: analyst      # Must match agent_role passed to guard.protect()
    allowed_sources:         # Empty list [] = allow all non-denied sources (admin wildcard)
      - reports
      - market_data
    denied_sources:          # Always blocked, takes priority over allowed_sources
      - executive_comms
    max_sensitivity: high    # Ceiling: low | medium | high | restricted
    allowed_tasks: []        # Optional — empty = allow all non-denied tasks
    denied_tasks: []         # Optional — blocks specific task_type values
    # industry and category are auto-injected from directory path when loading from a
    # policies/<industry>/<category>.yaml structure — no need to add them manually

When loading from a directory (--policy policies/), AutoPIL recursively finds all *.yaml files and injects industry and category from the path. Point the server at a directory to enable multi-industry support:

python serve.py --policy policies/

Evaluation order (first match wins):

  1. Is source_id in denied_sources? → DENY
  2. Is task_type in denied_tasks? → DENY
  3. Is allowed_tasks non-empty and task_type not in it? → DENY
  4. Is allowed_sources non-empty and source_id not in it? → DENY
  5. Does sensitivity_level exceed max_sensitivity? → DENY
  6. No issues found → ALLOW
  7. No policy matched for this agent_roleDENY (default deny)

Policies can also be managed via the REST API (POST /v1/policies, PUT /v1/policies/{name}) — changes are versioned and appear in GET /v1/policies/{name}/history.


REST API Reference

Base URL: http://localhost:8000

All /v1/* routes require X-API-Key header. /health is exempt.

Context

POST /v1/context/evaluate
{
  "query": "Q3 loss rates",
  "agent_role": "loan_underwriter",
  "user_id": "user_001",
  "source_id": "credit_scores",
  "sensitivity_level": "high",
  "session_id": "optional-uuid",
  "task_type": "optional-task-label"
}

Sessions

GET    /v1/sessions                         — list active sessions for this tenant
GET    /v1/sessions/{id}                    — session status (active | expired | revoked)
DELETE /v1/sessions/{id}                    — revoke a session immediately

Audit

GET /v1/audit/sessions/{session_id}         — full audit trail for a session
GET /v1/audit/events?decision=DENY&limit=100
GET /v1/audit/export?format=csv             — bulk export (CSV or JSON)
GET /v1/audit/stats
POST /v1/audit/lineage                      — record an agent action against an audit event
GET  /v1/audit/lineage/{event_id}           — retrieve event + all linked downstream actions

Policies

GET    /v1/policies                          — list (optional: ?industry=&category=)
POST   /v1/policies
PUT    /v1/policies/{name}
DELETE /v1/policies/{name}
GET    /v1/policies/{name}/history
POST   /v1/policies/reload

Alert rules

POST   /v1/alerts/rules
GET    /v1/alerts/rules
PUT    /v1/alerts/rules/{rule_id}
DELETE /v1/alerts/rules/{rule_id}
GET    /v1/alerts/fired

Keys

POST   /v1/keys
GET    /v1/keys
DELETE /v1/keys/{key_id}

Tenant management (superadmin)

POST   /v1/admin/tenants
GET    /v1/admin/tenants
DELETE /v1/admin/tenants/{id}

Storage Backends

SQLite (default)

Zero configuration. Used for development and single-instance deployments.

python serve.py --policy policies/ --db /data/autopil.db

Postgres (production)

pip install "autopil[postgres]"
export DATABASE_URL=postgresql://user:pass@host:5432/autopil
python3 serve.py --policy policies/

Schema is created automatically on first start. Supports horizontal scaling.

Docker Compose (Postgres)

docker compose up --build

The default docker-compose.yml starts AutoPIL with a postgres:16-alpine service wired via DATABASE_URL.


Docker Reference

Build

The Dockerfile is a 3-stage build: it compiles the React dashboard, installs the Python package, then assembles the runtime image with the dashboard assets served by the API.

docker build -f packages/core/Dockerfile -t autopil:0.1.0 .

Run

docker run -d \
  -p 8000:8000 \
  -v $(pwd)/packages/core/policies:/app/policies:ro \
  -v autopil-data:/data \
  -e AUTOPIL_POLICY=/app/policies \
  autopil:0.1.0

Environment variables

Variable Default Description
DATABASE_URL (unset) postgresql://... — uses Postgres if set, otherwise SQLite
AUTOPIL_POLICY /app/policies Policy file or directory path
AUTOPIL_DB /data/autopil_audit.db SQLite audit DB path
AUTOPIL_HOST 0.0.0.0 Bind host
AUTOPIL_PORT 8000 Listen port
OTEL_EXPORTER_OTLP_ENDPOINT (unset) OTLP collector URL — enables OTEL when set
OTEL_SERVICE_NAME autopil Service name in traces
AUTOPIL_SESSION_TTL_MINUTES (unset) Default session TTL in minutes. Unset = sessions never expire.
SMTP_HOST (unset) SMTP host for alert email delivery

Running the Examples

LangGraph demo — loan underwriting agent

python examples/langgraph_demo.py

Runs a 3-node LangGraph pipeline that makes 4 retrieval attempts (2 allowed, 2 denied) and prints the full audit trail.

Multi-agent demo — cross-agent isolation

python examples/multi_agent_demo.py

Runs a 4-agent wealth onboarding pipeline and demonstrates cross-agent isolation violations being blocked while the legitimate pipeline still reaches an APPROVED decision.


Running the Test Suite

Python

pip install -e ".[dev]"
pytest tests/ -v --ignore=tests/test_postgres.py

312 tests, all passing (11 skipped without Postgres):

File Tests What it covers
test_policy_engine.py 23 Allow/deny paths, sensitivity ceiling, admin wildcard, task scoping
test_audit_log.py 14 Persistence, session isolation, context hash
test_guard.py 16 Decorator enforcement, audit creation, cross-agent isolation
test_api.py 86 REST endpoints, filtering, export, lineage, session lifecycle, task scoping
test_auth.py 15 API key creation, listing, revocation, auth enforcement
test_tenants.py 13 Tenant lifecycle, data isolation, superadmin enforcement
test_alerting.py 21 Rule CRUD, all rule types, cooldown, delivery, API integration
test_telemetry.py 17 OTEL spans, metrics, guard integration, API integration
test_policy_editor.py 12 Policy CRUD, version history, restore, reload
test_multi_industry.py 65 Directory loading, path metadata, 45-policy real set, industry/category filters, multi-industry evaluate, task scoping
test_mcp_server.py 42 All 7 MCP tools — evaluate, audit query/stats, list policies, record action, reload, session status, server wiring
test_postgres.py 11 Postgres backend (runs when DATABASE_URL is set)

TypeScript SDK

cd sdk/typescript
npm install
npm test

28 tests covering all resource groups, error handling, query params, and URL normalisation.

Go SDK

cd sdk/go
go test ./...

Java SDK

cd sdk/java
mvn test

Sensitivity Levels

Ordered from least to most sensitive:

Level Value Example data
Low low Public product catalogs, FAQ knowledge bases
Medium medium Account summaries, transaction history
High high Credit scores, identity records, loan history
Restricted restricted Regulatory filings, internal risk models, audit logs

License

AutoPIL is licensed under the Business Source License 1.1.

What this means in practice:

  • Free to use for development, research, evaluation, and any non-commercial purpose
  • Free for internal production use — deploy it inside your own organization without restriction
  • Commercial restriction — you may not offer AutoPIL or a substantially similar product as a managed service or SaaS to third parties without a commercial license
  • Converts to MIT on March 25, 2030 — the full codebase becomes open source automatically on that date

For commercial licensing or enterprise deployments: anil@vibrantcapital.ai


Version

0.1.0 — initial release

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

autopil-0.1.2.tar.gz (172.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

autopil-0.1.2-py3-none-any.whl (125.8 kB view details)

Uploaded Python 3

File details

Details for the file autopil-0.1.2.tar.gz.

File metadata

  • Download URL: autopil-0.1.2.tar.gz
  • Upload date:
  • Size: 172.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for autopil-0.1.2.tar.gz
Algorithm Hash digest
SHA256 19e4e460b527fe5c9699061612eaa4f6237f4d12f6746387466b2ead7ce30846
MD5 919b00190b3e9b828671833fcba939ea
BLAKE2b-256 0fcbb08b6825a4c2e3622b357d8ddd2f590590c8cd46251a0cccbce459df5125

See more details on using hashes here.

Provenance

The following attestation bundles were made for autopil-0.1.2.tar.gz:

Publisher: publish.yml on anil-solleti/autopil

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file autopil-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: autopil-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 125.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for autopil-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 e25332ca1a915a7d2232817185b7cb761b00a4ccc912311493f710e3e3120652
MD5 f185ed1fbde79fb79a7c7d064143de16
BLAKE2b-256 00b482e161579dceab93ec05fe9cc6fca8169439ade39a0dd385c63264b4d5c4

See more details on using hashes here.

Provenance

The following attestation bundles were made for autopil-0.1.2-py3-none-any.whl:

Publisher: publish.yml on anil-solleti/autopil

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page