Metadata-Version: 2.4
Name: pvd
Version: 0.2.0
Summary: Paved SDK
Author: Paved (https://hipaved.com)
License: Proprietary
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: click>=8.1
Requires-Dist: PyYAML>=6.0.1
Requires-Dist: requests>=2.31
Provides-Extra: cli
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Requires-Dist: black; extra == "dev"
Provides-Extra: openai
Requires-Dist: openai>=1.0.0; extra == "openai"
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.18.0; extra == "anthropic"
Provides-Extra: litellm
Requires-Dist: litellm>=1.0.0; extra == "litellm"
Provides-Extra: langchain
Requires-Dist: langchain-core>=0.1.0; extra == "langchain"
Provides-Extra: langgraph
Requires-Dist: langgraph>=0.1.0; extra == "langgraph"
Requires-Dist: langchain-core>=0.1.0; extra == "langgraph"
Provides-Extra: langfuse
Requires-Dist: langfuse>=2.0.0; extra == "langfuse"
Provides-Extra: all
Requires-Dist: openai>=1.0.0; extra == "all"
Requires-Dist: anthropic>=0.18.0; extra == "all"
Requires-Dist: litellm>=1.0.0; extra == "all"
Requires-Dist: langchain-core>=0.1.0; extra == "all"
Requires-Dist: langgraph>=0.1.0; extra == "all"
Requires-Dist: langfuse>=2.0.0; extra == "all"

# Paved SDK

Python SDK for the [Paved](https://hipaved.com) platform — the governance layer for AI agents. Policy checks, credential-injecting proxy, and agentic tool execution all route through the Paved Platform API.

## Install

```bash
pip install pvd
```

## Quick Start

```python
from pvd import Agent

agent = Agent(
    agent_id="my-agent",
    api_key="pvd_live_...",          # or set PAVED_API_KEY env var
    base_url="https://app.hipaved.com",  # default
)
```

## Agentic Gateway

Run a governed agentic loop: the LLM picks tools from your connected integrations, Paved executes each tool call through the credential-injecting proxy with per-action policy checks, and returns the final answer with 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)       # Final LLM response
print(result.finish_reason)  # "stop" | "max_rounds" | "policy_denied"
print(result.rounds_used)    # Number of tool-use rounds
print(result.tool_executions) # Full trace of every tool call
print(result.usage)          # {"prompt_tokens": ..., "completion_tokens": ...}
```

### Multi-integration

Connect multiple integrations in a single session:

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

### Delegated Access

Pass end-user context for per-user policy evaluation via OPA:

```python
result = agent.agent(
    messages=[{"role": "user", "content": "Get my account details"}],
    integrations=["salesforce"],
    on_behalf_of={
        "user_id": "u_123",
        "role": "sales_rep",
        "department": "sales",
        "clearance": 2,
    },
)
```

### AgentResult

The `agent()` method returns an `AgentResult` object:

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

result.successful_tools  # list[dict] — Tools that succeeded
result.denied_tools      # list[dict] — Tools denied by policy

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

Each tool execution trace contains:

```python
{
    "round": 1,
    "tool_call_id": "call_abc123",
    "tool_name": "salesforce__api_request",
    "integration_slug": "salesforce",
    "action_key": "api_request",
    "method": "GET",
    "path": "/services/data/v59.0/query?q=SELECT+Id,Name+FROM+Account+LIMIT+5",
    "arguments": {"method": "GET", "path": "..."},
    "status_code": 200,
    "response_body": {"totalSize": 5, "records": [...]},
    "decision": "allow",
    "reasons": [],
    "error": None,
    "latency_ms": 492,
}
```

## Proxy

Make governed API calls through connected integrations. Paved injects credentials server-side — secrets never leave the platform.

```python
# GET request
repos = agent.proxy("github", "GET", "/user/repos")
print(repos["body"])

# POST with body
issue = agent.proxy("github", "POST", "/repos/owner/repo/issues", body={
    "title": "Bug report",
    "body": "Details here",
})

# Delegated access
accounts = agent.proxy(
    "salesforce", "GET", "/services/data/v59.0/query",
    query={"q": "SELECT Id, Name FROM Account LIMIT 10"},
    on_behalf_of={"role": "analyst", "department": "finance"},
)
```

## LLM Wrappers

Drop-in replacements that route through Paved's gateway with policy enforcement.

### OpenAI

```python
from pvd.openai import OpenAI

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

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello"}],
)
```

### Anthropic

```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": "Hello"}],
)
```

### LiteLLM (100+ providers)

```python
from pvd.litellm import LiteLLM

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

response = client.completion(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello"}],
)
```

## Policy Checks

Explicit policy checks for custom actions:

```python
from pvd import Agent, PolicyDeniedError

agent = Agent(agent_id="my-agent")

try:
    agent.check("send_email", {
        "to": ["user@example.com"],
        "subject": "Report",
        "body": "...",
    })
except PolicyDeniedError as e:
    print(f"Blocked: {e}")
```

### Governance Summary

```python
summary = agent.get_governance_summary()
print(summary["total_checks"])
print(summary["allowed_actions"])
print(summary["denied_actions"])
print(summary["flagged_actions"])
print(summary["overall_decision"])  # "allow", "flag", or "deny"
```

## CLI

```bash
pvd login                              # Authenticate
pvd init my-agent --template llm       # Scaffold project
pvd build . -o my-agent.tar.gz         # Package
pvd deploy my-agent.tar.gz --name my-agent  # Deploy
pvd list                               # List agents
pvd invoke <agent-id> --payload '{}'   # Run
pvd logs <invocation-id> --follow      # Stream logs
```
