# Paved

**The governance layer for AI agents.** Connect LLMs and integrations, enforce policies on every action, and get full observability — without changing your agent code.

Paved sits between your AI agents and the APIs they call. Every LLM request, tool execution, and data access flows through Paved's policy engine, so you get security, compliance, and audit trails out of the box.

**Dashboard**: [app.hipaved.com](https://app.hipaved.com) | **Docs**: [docs.hipaved.com](https://docs.hipaved.com) | **Website**: [hipaved.com](https://hipaved.com)

---

## How It Works

```
Your Agent ──> Paved Gateway ──> Policy Engine (OPA) ──> LLM / Integration API
                    │                    │
                    │              allow / deny / flag
                    │
              Credential Injection     Audit Log
              (secrets never leave     (every request
               the platform)           recorded)
```

1. **Connect** your LLM providers and SaaS integrations in the dashboard
2. **Define policies** — what's allowed, what's blocked, what gets flagged
3. **Route traffic** through Paved using the SDK, API, or drop-in wrappers
4. **Monitor everything** — audit logs, cost tracking, policy violations, alerts

---

## Install

```bash
pip install pvd
```

```python
from pvd import Agent

agent = Agent(
    agent_id="my-agent",
    api_key="pvd_live_...",   # or set PAVED_API_KEY env var
)
```

---

## Agentic Gateway

The headline feature. Give the LLM access to your connected integrations, and Paved handles the rest: tool conversion, credential injection, per-action policy checks, and a full execution trace.

```python
result = agent.agent(
    messages=[{"role": "user", "content": "Get me my top 5 Salesforce accounts"}],
    integrations=["salesforce"],
    model="gpt-4o",
)

print(result.content)
# "Here are your top 5 accounts: 1. Acme Corp..."

print(result.finish_reason)   # "stop" | "max_rounds" | "policy_denied"
print(result.rounds_used)     # 1
print(result.tool_executions) # Full trace of every tool call
print(result.usage)           # {"prompt_tokens": 2512, "completion_tokens": 235}
```

Under the hood, Paved:
- Converts each integration's action catalog into OpenAI-format tool definitions
- Calls the LLM with tools enabled
- When the LLM makes a tool call, executes it through the credential-injecting proxy
- Checks policy **per tool call** (a read may be allowed while a delete is denied)
- Feeds the result back to the LLM
- Repeats until the LLM returns a final answer or hits `max_rounds`

### Multi-Integration Sessions

Wire up multiple integrations in a single agent call:

```python
result = agent.agent(
    messages=[{
        "role": "user",
        "content": "Find the Acme Corp deal in Salesforce and create a follow-up issue in GitHub"
    }],
    integrations=["salesforce", "github"],
    model="gpt-4o",
    max_rounds=10,
)
```

### Delegated Access

Pass end-user identity so policies can enforce per-user rules (department restrictions, role-based access, clearance levels):

```python
result = agent.agent(
    messages=[{"role": "user", "content": "Show me the finance dashboard data"}],
    integrations=["salesforce"],
    on_behalf_of={
        "user_id": "u_123",
        "role": "analyst",
        "department": "finance",
        "clearance": 2,
    },
)
```

### AgentResult

```python
result.content            # Final LLM text response
result.finish_reason      # "stop", "max_rounds", or "policy_denied"
result.rounds_used        # Number of tool-use loop iterations
result.tool_executions    # Full trace per tool call
result.usage              # {prompt_tokens, completion_tokens, total_tokens}
result.latency_ms         # Total wall-clock time in ms
result.request_id         # Unique ID for audit trail lookup
result.model              # Model used

result.successful_tools   # Tool calls that succeeded
result.denied_tools       # Tool calls denied by policy

str(result)               # Returns result.content
```

### curl

```bash
curl -X POST https://app.hipaved.com/v1/gateway/agent \
  -H "Authorization: Bearer pvd_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o",
    "messages": [{"role": "user", "content": "Get my top 5 Salesforce accounts"}],
    "integrations": ["salesforce"],
    "max_rounds": 5
  }'
```

---

## Governed Proxy

Make direct API calls through connected integrations. Paved injects credentials server-side and checks policy before forwarding — secrets never leave the platform.

```python
# Read from GitHub
repos = agent.proxy("github", "GET", "/user/repos")

# Write to GitHub
agent.proxy("github", "POST", "/repos/acme/app/issues", body={
    "title": "Bug: login broken",
    "body": "Steps to reproduce...",
})

# Query Salesforce with SOQL
accounts = agent.proxy(
    "salesforce", "GET",
    "/services/data/v59.0/query",
    query={"q": "SELECT Id, Name FROM Account LIMIT 10"},
)

# Delegated access — policy engine sees the end-user's role
agent.proxy(
    "stripe", "GET", "/v1/charges",
    on_behalf_of={"role": "support", "department": "cs"},
)
```

Every proxy call returns the upstream response plus governance metadata:

```python
{
    "status_code": 200,
    "body": [...],           # Upstream response
    "decision": "allow",     # Policy decision
    "reasons": [],           # Why (if flagged/denied)
    "request_id": "...",     # Audit trail ID
    "latency_ms": 142,
}
```

---

## LLM Gateway

Route LLM calls through Paved for policy enforcement, cost tracking, and audit logging. Three integration options — pick the one that fits your stack.

### Drop-in OpenAI Wrapper

Zero code changes. Replace the import, everything else stays the same:

```python
# Before
from openai import OpenAI
client = OpenAI()

# After
from pvd.openai import OpenAI
client = OpenAI(agent_id="my-agent", paved_api_key="pvd_live_...")

# Same API — now with policy enforcement
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Summarize our Q3 results"}],
)
```

### Drop-in Anthropic Wrapper

```python
from pvd.anthropic import Anthropic

client = Anthropic(agent_id="my-agent", paved_api_key="pvd_live_...")

response = client.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Analyze this contract"}],
)
```

### LiteLLM Wrapper (100+ Providers)

Use any model from any provider through a single interface:

```python
from pvd.litellm import LiteLLM

client = LiteLLM(agent_id="my-agent", api_key="pvd_live_...")

# OpenAI
client.completion(model="gpt-4o", messages=[...])

# Anthropic
client.completion(model="claude-sonnet-4-5-20250929", messages=[...])

# Google
client.completion(model="gemini/gemini-2.0-flash", messages=[...])

# Embeddings
client.embedding(model="text-embedding-3-small", input="Hello world")
```

### curl (OpenAI-Compatible)

Point any OpenAI-compatible client at Paved:

```bash
curl -X POST https://app.hipaved.com/v1/gateway/chat/completions \
  -H "Authorization: Bearer pvd_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o",
    "messages": [{"role": "user", "content": "Hello"}]
  }'
```

Anthropic Messages API is also supported at `/v1/gateway/v1/messages`.

---

## Policies

Paved uses a **three-decision model**: every check returns `allow`, `deny`, or `flag`. Denied actions are blocked. Flagged actions proceed but are logged for review. Priority: deny > flag > allow.

### Built-in Policy Templates

| Policy | What It Does |
|--------|-------------|
| **PII Detection** | Blocks SSNs, credit cards, phone numbers, emails in prompts/responses |
| **Prompt Injection Guard** | Detects SQL injection, prompt injection, jailbreak attempts |
| **Semantic Analysis** | AI-powered topic firewall — block specific subjects |
| **Token Budget** | Limit tokens per request or per session |
| **Cost Limits** | Budget caps per user, project, or time period |
| **Rate Limiting** | Requests per minute/hour per user or project |
| **Model Restrictions** | Whitelist/blacklist specific models |
| **Tool Restrictions** | Control which tools agents can execute |
| **Output Filter** | Content filtering on LLM responses |
| **Resource Access** | Per-integration action controls (allow reads, deny deletes) |
| **Access Control** | RBAC — restrict by user role, department, clearance level |
| **HTTP Firewall** | Block requests to specific domains or paths |
| **Custom Rules** | Write your own rules in Python or Rego |

### Policy Presets

Apply a preset to get started quickly:

| Preset | Description |
|--------|-------------|
| **Strict** | All policies enabled and enforced — production security |
| **Standard** | Balanced — PII, injection, output filter, rate limits |
| **Development** | Minimal — PII and injection in flag-only mode |
| **Shadow** | All policies in flag-only — monitor without blocking |

### SDK Policy Checks

Run explicit policy checks in your agent code:

```python
from pvd import Agent, PolicyDeniedError

agent = Agent(agent_id="my-agent", api_key="pvd_live_...")

# Check before performing an action
try:
    agent.check("send_email", {
        "to": ["ceo@company.com"],
        "subject": "Q3 Report",
        "body": "Revenue was $4.2M...",
    })
    # If we get here, the action is allowed (or flagged)
    send_email(...)
except PolicyDeniedError as e:
    print(f"Blocked: {e}")
    # e.decision contains full details and reasons
```

### Dry Run

Test your policies against sample content before deploying:

```bash
curl -X POST https://app.hipaved.com/v1/policy-management/dry-run \
  -H "Authorization: Bearer pvd_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "project_id": "...",
    "content": "My SSN is 123-45-6789",
    "phase": "input"
  }'
```

### Custom Rego Rules

For advanced use cases, write custom OPA Rego policies that run alongside the built-in templates:

```rego
package custom

deny[msg] {
    input.resource_action == "DELETE"
    input.integration_slug == "production-db"
    msg := "DELETE operations on production database are not allowed"
}

flag[msg] {
    input.estimated_cost_usd > 1.0
    msg := sprintf("High cost request: $%.2f", [input.estimated_cost_usd])
}
```

---

## Integrations

Connect once in the dashboard, use everywhere. Paved handles OAuth flows, token refresh, key rotation, and credential injection.

### Supported Integrations

**AI Providers**: OpenAI, Anthropic, Google (Gemini), Mistral, Cohere

**SaaS**: Salesforce, GitHub, Slack, Jira, HubSpot, Zendesk, Stripe

**Databases**: PostgreSQL, MongoDB, Snowflake

**Cloud**: AWS, GCP, Azure

Each integration comes with an **actions catalog** that defines available operations with risk levels:

```json
{
  "actions": {
    "accounts": {
      "label": "List Accounts",
      "method": "GET", "path": "/accounts",
      "verb": "read", "risk": "low"
    },
    "create-contact": {
      "label": "Create Contact",
      "method": "POST", "path": "/contacts",
      "verb": "write", "risk": "medium"
    },
    "delete-account": {
      "label": "Delete Account",
      "method": "DELETE", "path": "/accounts/{id}",
      "verb": "admin", "risk": "critical"
    }
  }
}
```

The policy engine uses these risk levels and verbs to make per-action decisions. A single agent session can allow reads while blocking deletes — automatically.

### Resource Governance

Each connected integration becomes a **resource** with its own governance configuration:

- **Allowed/blocked actions** — granular control per operation
- **Risk thresholds** — auto-block actions above a certain risk level
- **Environment tags** — different policies for staging vs production
- **Per-user access control** — restrict by role, department, or clearance via `on_behalf_of`

---

## Observability

### Audit Logs

Every request through Paved is logged with full context:

- Request and response payloads
- Policy decisions with reasons
- Token usage and cost
- Latency breakdown
- User and project attribution
- Tool execution traces (for agent sessions)

Query logs in the dashboard or via API:

```bash
curl "https://app.hipaved.com/v1/logs?decision=deny&project_id=..." \
  -H "Authorization: Bearer pvd_live_..."
```

### Cost Tracking

Real-time cost tracking across all LLM providers:

- Per-request cost calculation
- Daily/weekly/monthly summaries
- Breakdown by model, project, and user
- Budget alerts when thresholds are exceeded

### Alerts & Webhooks

Get notified when policies fire:

```
Policy Deny  ──>  Webhook  ──>  Slack / PagerDuty / Custom URL
Policy Flag  ──>  Alert Rule  ──>  Email / Webhook
Cost Limit   ──>  Notification
```

Configure alert rules and webhook endpoints in the dashboard under Settings > Alerts.

### Governance Summary

Track your agent's compliance programmatically:

```python
summary = agent.get_governance_summary()

print(summary["total_checks"])      # 47
print(summary["allowed_actions"])   # 42
print(summary["denied_actions"])    # 3
print(summary["flagged_actions"])   # 2
print(summary["overall_decision"])  # "deny" (if any action was denied)
```

---

## Multi-Tenancy & RBAC

### Organizations

Every account belongs to an organization. Resources, policies, and audit logs are isolated per org.

### Projects

Organize work into projects. Each project has its own:
- Connected integrations (resources)
- Policy configuration
- API keys
- Audit logs and usage metrics

### Team Roles

| Role | Permissions |
|------|------------|
| **Owner** | Full access, billing, delete org |
| **Admin** | Manage members, policies, integrations |
| **Developer** | Create/modify resources, view logs |
| **Viewer** | Read-only access to dashboard and logs |

### API Key Scopes

Restrict API keys to specific projects or resources:

```python
# Key scoped to one project
agent = Agent(api_key="pvd_live_...")  # scoped at creation time

# Key scoped to specific resources
# Only Salesforce + GitHub, no access to Stripe
```

---

## Tool Registry

Paved automatically classifies every tool your agents use:

- **AI classification** — risk level, category, capabilities
- **Manual overrides** — admins can reclassify tools
- **Organization-wide registry** — shared across all projects
- **Confidence scoring** — transparency on classification certainty

Browse the registry in the dashboard at Inventory > Tool Registry, or query via API.

---

## Architecture

```
┌─────────────────────────────────────────────────┐
│                  Your Agent Code                 │
│                                                  │
│  pvd.openai  │  pvd.anthropic  │  pvd.Agent     │
└──────────────┼─────────────────┼────────────────┘
               │                 │
               v                 v
┌─────────────────────────────────────────────────┐
│              Paved Gateway (FastAPI)             │
│                                                  │
│  /chat/completions  │  /proxy  │  /agent         │
│                                                  │
│  ┌──────────────┐  ┌────────────────────────┐   │
│  │ Policy Engine │  │ Credential Injection   │   │
│  │   (OPA)       │  │ (OAuth2, JWT, API Key) │   │
│  └──────────────┘  └────────────────────────┘   │
│                                                  │
│  ┌──────────────┐  ┌────────────────────────┐   │
│  │ Audit Logger  │  │ Cost Tracker           │   │
│  └──────────────┘  └────────────────────────┘   │
└─────────────────────────────────────────────────┘
               │                 │
               v                 v
        ┌────────────┐   ┌──────────────┐
        │ LLM APIs   │   │ SaaS APIs    │
        │ OpenAI     │   │ Salesforce   │
        │ Anthropic  │   │ GitHub       │
        │ Google     │   │ Stripe       │
        │ ...        │   │ ...          │
        └────────────┘   └──────────────┘
```

---

## Self-Hosting

Paved runs on a single server. The full stack is Docker Compose:

| Service | Purpose |
|---------|---------|
| **Backend** | FastAPI application server |
| **Frontend** | React dashboard |
| **Guard API** | Policy evaluation service |
| **Semantic** | AI-powered policy analysis |
| **OPA** | Open Policy Agent (Rego rules) |
| **PostgreSQL** | Primary database |
| **Redis** | Caching, rate limiting, token deduplication |
| **Caddy** | Reverse proxy with automatic TLS |

Minimum requirements: 4 CPU, 8 GB RAM. See deployment docs for setup instructions.

---

## Environment Variables

| Variable | Description | Default |
|----------|-------------|---------|
| `PAVED_API_KEY` | API key for authentication | — |
| `PAVED_API_URL` | Platform API base URL | `https://app.hipaved.com` |

---

## Links

- **Dashboard**: [app.hipaved.com](https://app.hipaved.com)
- **Documentation**: [docs.hipaved.com](https://docs.hipaved.com)
- **Website**: [hipaved.com](https://hipaved.com)
- **PyPI**: [pypi.org/project/pvd](https://pypi.org/project/pvd/)
