Metadata-Version: 2.4
Name: autopil
Version: 0.1.0
Summary: Platform Intelligence Layer — context governance for autonomous agents
Author-email: Anil Solleti <anil@vibrantcapital.ai>
License: Business Source License 1.1
        
        License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.
        "Business Source License" is a trademark of MariaDB Corporation Ab.
        
        Parameters
        
        Licensor:             Anil Solleti / VibrantCapital.ai
        Licensed Work:        AutoPIL 0.1.0 and later versions
                              The Licensed Work is (c) 2026 Anil Solleti / VibrantCapital.ai
        Additional Use Grant: You may use the Licensed Work for any purpose other than
                              a Production Use that is a Competing Use. A "Competing Use"
                              means offering the Licensed Work or a substantially similar
                              product as a commercial managed service or SaaS product to
                              third parties.
        Change Date:          2030-03-25
        Change License:       MIT License
        
        For information about alternative licensing arrangements, contact:
        anil@vibrantcapital.ai
        
        ---
        
        Business Source License 1.1
        
        Terms
        
        The Licensor hereby grants you the right to copy, modify, create derivative
        works, redistribute, and make non-production use of the Licensed Work. The
        Licensor may make an Additional Use Grant, above, permitting limited production
        use.
        
        Effective on the Change Date, or the fourth anniversary of the first publicly
        available distribution of a specific version of the Licensed Work under this
        License, whichever comes first, the Licensor hereby grants you rights under
        the terms of the Change License, and the rights granted in the paragraph
        above terminate.
        
        If your use of the Licensed Work does not comply with the requirements
        currently in effect as described in this License, you must purchase a
        commercial license from the Licensor, its affiliated entities, or authorized
        resellers, or you must refrain from using the Licensed Work.
        
        All copies of the original and modified Licensed Work, and derivative works
        of the Licensed Work, are subject to this License. This License applies
        separately for each version of the Licensed Work and the Change Date may vary
        for each version of the Licensed Work released by Licensor.
        
        You must conspicuously display this License on each original or modified copy
        of the Licensed Work. If you receive the Licensed Work in original or modified
        form from a third party, the terms and conditions set forth in this License
        apply to your use of that work.
        
        Any use of the Licensed Work in violation of this License will automatically
        terminate your rights under this License for the current and all future
        versions of the Licensed Work.
        
        This License does not grant you any right in any trademark or logo of Licensor
        or its affiliates (provided that you may use a trademark or logo of Licensor
        as expressly required by this License).
        
        TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
        AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
        EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
        MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
        TITLE.
        
Project-URL: Homepage, https://autopil.ai
Project-URL: Repository, https://github.com/anil-solleti/autopil
Project-URL: Issues, https://github.com/anil-solleti/autopil/issues
Project-URL: Changelog, https://github.com/anil-solleti/autopil/releases
Keywords: ai,agents,governance,context,policy,langgraph,langchain,audit,enterprise
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Operating System :: OS Independent
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pyyaml>=6.0
Provides-Extra: server
Requires-Dist: fastapi>=0.115; extra == "server"
Requires-Dist: uvicorn>=0.30; extra == "server"
Provides-Extra: langgraph
Requires-Dist: langgraph>=0.2; extra == "langgraph"
Requires-Dist: langchain-core>=0.3; extra == "langgraph"
Requires-Dist: langchain-community>=0.3; extra == "langgraph"
Provides-Extra: postgres
Requires-Dist: psycopg2-binary>=2.9; extra == "postgres"
Provides-Extra: all
Requires-Dist: fastapi>=0.115; extra == "all"
Requires-Dist: uvicorn>=0.30; extra == "all"
Requires-Dist: langgraph>=0.2; extra == "all"
Requires-Dist: langchain-core>=0.3; extra == "all"
Requires-Dist: langchain-community>=0.3; extra == "all"
Requires-Dist: psycopg2-binary>=2.9; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: httpx>=0.27; extra == "dev"
Requires-Dist: fastapi>=0.115; extra == "dev"
Requires-Dist: uvicorn>=0.30; extra == "dev"
Dynamic: license-file

# 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 (SQLite / Postgres)
```

---

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

---

## Architecture

```
┌─────────────────────────────────────────────────────────┐
│                       Your Agent                        │
└────────────────────────┬────────────────────────────────┘
                         │  @guard.protect(...)
┌────────────────────────▼────────────────────────────────┐
│                    ContextGuard                         │
│  1. Cross-agent session isolation check                 │
│  2. Policy evaluation (allow / deny)                    │
│  3. Execute retrieval (if allowed)                      │
│  4. Hash context for provenance                         │
│  5. Record immutable audit event                        │
└──────────────┬────────────────────────┬─────────────────┘
               │                        │
┌──────────────▼──────┐   ┌─────────────▼───────────────┐
│   PolicyEngine      │   │     Storage Backend          │
│   YAML-based rules  │   │   SQLite (default)           │
│   Deny by default   │   │   Postgres (production)      │
└─────────────────────┘   └─────────────────────────────┘
```

**Five 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 |
| Cross-agent isolation | A session belongs to the first agent that used it — others are denied |
| Default deny | No matching policy = access denied |

---

## Quickstart

### Install

```bash
pip install -e .
```

For Postgres support:

```bash
pip install -e ".[postgres]"
```

### Define a policy

```yaml
# policies/my_policy.yaml
policies:
  - name: analyst_policy
    agent_role: analyst
    allowed_sources:
      - reports
      - market_data
    denied_sources:
      - executive_comms
    max_sensitivity: high
```

### Wrap your retrieval functions

```python
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")
```

### View the audit trail

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

---

## 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/financial_services.yaml
  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

```bash
python serve.py --policy policies/financial_services.yaml
```

### With Postgres

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

### Docker

```bash
docker compose up --build
```

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

- **Dashboard**: http://localhost:8000
- **API docs**: http://localhost:8000/docs

---

## API Authentication

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

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

### Key management

```bash
# 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, API keys, and stats are fully isolated.

### Create a tenant (superadmin required)

```bash
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.

### Tenant admin routes

| Method | Path | Description |
|---|---|---|
| `POST` | `/v1/admin/tenants` | Create tenant + initial admin key |
| `GET` | `/v1/admin/tenants` | List all tenants |
| `DELETE` | `/v1/admin/tenants/{id}` | Deactivate a tenant |

All admin routes require a superadmin key (`is_superadmin=true`).

---

## Project Structure

```
autopil/
├── autopil/
│   ├── __init__.py          # Public API: ContextGuard, Decision, SensitivityLevel
│   ├── models.py            # Dataclasses: ContextRequest, AuditEvent, enums
│   ├── policy_engine.py     # YAML policy loader and evaluator
│   ├── audit_log.py         # Shim → SQLiteAuditLog
│   ├── guard.py             # ContextGuard decorator — core enforcement
│   ├── db/
│   │   ├── __init__.py      # create_stores() factory
│   │   ├── base.py          # AuditLogBase, KeyStoreBase, TenantStoreBase ABCs
│   │   ├── sqlite.py        # SQLite backend (default)
│   │   └── postgres.py      # Postgres backend (production)
│   └── api/
│       ├── app.py           # FastAPI application factory
│       ├── key_store.py     # Shim → SQLiteKeyStore
│       ├── schemas.py       # Pydantic request/response models
│       └── static/
│           └── index.html   # Control plane dashboard UI
├── policies/
│   ├── financial_services.yaml   # Loan underwriting roles
│   └── wealth_onboarding.yaml    # 4-agent onboarding pipeline roles
├── 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     # 14 policy evaluation tests
│   ├── test_audit_log.py         # 14 audit persistence tests
│   ├── test_guard.py             # 16 ContextGuard enforcement tests
│   ├── test_api.py               # 20 REST API endpoint tests
│   ├── test_auth.py              # 15 API key authentication tests
│   ├── test_tenants.py           # 13 multi-tenancy and isolation tests
│   └── test_postgres.py          # 11 Postgres backend tests (skipped unless DATABASE_URL set)
├── Dockerfile
├── docker-compose.yml
└── serve.py
```

---

## Policy Reference

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

```yaml
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
```

**Evaluation order** (first match wins):

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

---

## REST API Reference

Base URL: `http://localhost:8000`

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

### Evaluate a context request

```
POST /v1/context/evaluate
X-API-Key: apl_yourkey
```

```json
{
  "query": "Q3 loss rates",
  "agent_role": "loan_underwriter",
  "user_id": "user_001",
  "source_id": "credit_scores",
  "sensitivity_level": "high",
  "session_id": "optional-uuid"
}
```

Response:

```json
{
  "decision": "ALLOW",
  "policy_name": "loan_underwriter_policy",
  "reason": "Access granted",
  "event_id": "uuid",
  "session_id": "uuid",
  "timestamp": "2026-03-25T06:00:00"
}
```

### Key management

```
POST   /v1/keys              — create key (scoped to calling tenant)
GET    /v1/keys              — list keys for calling tenant
DELETE /v1/keys/{key_id}     — revoke a key
```

### Tenant management (superadmin)

```
POST   /v1/admin/tenants         — create tenant + initial admin key
GET    /v1/admin/tenants         — list all tenants
DELETE /v1/admin/tenants/{id}    — deactivate tenant
```

### Audit

```
GET /v1/audit/sessions/{session_id}
GET /v1/audit/events?decision=DENY&agent_role=analyst&limit=100
GET /v1/audit/stats
```

### Policies

```
GET  /v1/policies
POST /v1/policies/reload
```

---

## Storage Backends

### SQLite (default)

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

```bash
python serve.py --policy policies/financial_services.yaml --db /data/autopil.db
```

### Postgres (production)

```bash
pip install autopil[postgres]
export DATABASE_URL=postgresql://user:pass@host:5432/autopil
python serve.py
```

Schema is created automatically on first start. Supports horizontal scaling — multiple instances can share one Postgres database.

### Docker Compose (Postgres)

```bash
docker compose up --build
```

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

---

## Docker Reference

### Build

```bash
docker build -t autopil:0.1.0 .
```

### Run with environment overrides

```bash
docker run -d \
  -p 8000:8000 \
  -v $(pwd)/policies:/app/policies:ro \
  -v autopil-data:/data \
  -e AUTOPIL_POLICY=/app/policies/wealth_onboarding.yaml \
  autopil:0.1.0
```

### Environment variables

| Variable | Default | Description |
|---|---|---|
| `DATABASE_URL` | _(unset)_ | `postgresql://...` — uses Postgres if set, otherwise SQLite |
| `AUTOPIL_POLICY` | `/app/policies/financial_services.yaml` | Policy file path inside container |
| `AUTOPIL_DB` | `/data/autopil_audit.db` | SQLite audit DB path (ignored if `DATABASE_URL` is set) |
| `AUTOPIL_HOST` | `0.0.0.0` | Bind host |
| `AUTOPIL_PORT` | `8000` | Listen port |

---

## Running the Examples

### LangGraph demo — loan underwriting agent

```bash
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

```bash
python examples/multi_agent_demo.py
```

Runs a 4-agent wealth onboarding pipeline (intake → KYC → risk → compliance) and demonstrates 4 isolation violations being blocked while the legitimate pipeline still reaches an APPROVED decision.

---

## Running the Test Suite

```bash
pip install -e ".[dev]"
pytest tests/ -v
```

92 tests, all passing. Coverage:

| File | Tests | What it covers |
|---|---|---|
| `test_policy_engine.py` | 14 | Allow/deny paths, sensitivity ceiling, admin wildcard, policy reload |
| `test_audit_log.py` | 14 | Persistence, session isolation, session owner, context hash |
| `test_guard.py` | 16 | Decorator enforcement, audit creation, context hash, cross-agent isolation |
| `test_api.py` | 20 | All REST endpoints, filtering, stats, policy reload |
| `test_auth.py` | 15 | API key creation, listing, revocation, auth enforcement |
| `test_tenants.py` | 13 | Tenant lifecycle, data isolation, superadmin enforcement |

Postgres tests (11) run automatically when `DATABASE_URL` is set.

---

## 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](LICENSE).

**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

BSL is not an OSI-approved open source license. It is a source-available license designed to allow broad community use while protecting against cloud vendors and competitors commoditizing the work before the project can sustain itself commercially.

For commercial licensing, partnership inquiries, or enterprise deployments: **anil@vibrantcapital.ai**

---

## Version

`0.1.0` — initial release
