Metadata-Version: 2.4
Name: glidepaths
Version: 0.1.0
Summary: Python SDK for the Glidepaths AI governance API
Home-page: https://github.com/jossiekc/lucid-ai-laws
Author: Glidepaths
Author-email: jon@glidepaths.com
Keywords: ai governance compliance audit glidepaths
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.24.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
Requires-Dist: respx>=0.20; extra == "dev"
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# Glidepaths Python SDK

AI governance infrastructure for Python-based agents. Log decisions and evaluate actions against your org's governance policies in real time.

## Installation

```bash
pip install glidepaths
```

## Quick start

```python
from glidepaths import GlidepathsClient

client = GlidepathsClient(api_key="glp_your_api_key")
```

Get your API key from the [Glidepaths dashboard](https://glidepaths.com/tools/agent-registry).

---

## evaluate() — pre-action governance check

Call this **before** your agent takes an action. Returns a decision you must honour.

```python
from glidepaths import GlidepathsClient, PolicyViolationError

client = GlidepathsClient(api_key="glp_...")

decision = client.evaluate(
    action_type="approve_insurance_claim",
    action_payload={
        "claim_id": "CLM-9821",
        "amount": 125000,
        "claimant_id": "C-4421",
    },
    context={
        "delegation_tier": 2,
        "department": "claims",
    },
    agent_id="claims-agent-v3",
)

if decision.can_proceed:
    approve_claim()
elif decision.requires_escalation:
    notify_human_reviewer(decision.escalation_path, reason=decision.reason)
elif decision.is_blocked:
    reject_with_explanation(decision.reason)
```

`EvaluateResponse` fields:

| Field | Type | Description |
|---|---|---|
| `decision` | `str` | `"proceed"` \| `"escalate"` \| `"block"` |
| `reason` | `str` | Human-readable explanation |
| `policy_id` | `str \| None` | ID of the policy that triggered the decision |
| `latency_ms` | `int` | Server-side evaluation time |
| `escalation_path` | `str \| None` | Where to route escalations |
| `can_proceed` | `bool` | Convenience property |
| `requires_escalation` | `bool` | Convenience property |
| `is_blocked` | `bool` | Convenience property |

---

## log() — post-action audit trail

Call this **after** your agent acts to write an immutable decision log.

```python
result = client.log(
    agent_name="underwriting-agent-v2",
    decision_type="policy_approval",
    decision_summary="Approved homeowners policy for applicant A-8821. Risk score 34/100. No exclusions applied.",
    risk_level="medium",           # "low" | "medium" | "high" | "critical"
    delegation_tier=2,
    model_version="gpt-4o-2024-11",
    compliance_tags=["NAIC", "actuarial-fairness"],
    input_hash="sha256:abc123...", # enables safe retries — duplicate hashes are skipped
    source_system="underwriting-platform",
    session_id="sess_8821",
    metadata={"applicant_state": "CO", "coverage_amount": 450000},
)

print(f"Ingested: {result.ingested}, Duplicates skipped: {result.duplicates}")
```

### Idempotent retries

Supply `input_hash` to make log() safely retryable. If the same hash is
sent twice, the second call is a no-op and returns `duplicates=1`.

```python
import hashlib, json

def stable_hash(payload: dict) -> str:
    return "sha256:" + hashlib.sha256(
        json.dumps(payload, sort_keys=True).encode()
    ).hexdigest()

client.log(
    agent_name="claims-agent",
    decision_type="payout_approved",
    decision_summary="...",
    input_hash=stable_hash({"claim_id": "CLM-9821", "amount": 125000}),
)
```

### Batch logging

```python
result = client.log_batch([
    {"agent_name": "agent-a", "decision_type": "lookup", "decision_summary": "...", "risk_level": "low"},
    {"agent_name": "agent-b", "decision_type": "approval", "decision_summary": "...", "risk_level": "high"},
])
```

Up to 100 events per batch.

---

## Async usage

Use `AsyncGlidepathsClient` with `asyncio`, FastAPI, LangChain, or any async framework.

```python
import asyncio
from glidepaths import AsyncGlidepathsClient

async def run_agent():
    async with AsyncGlidepathsClient(api_key="glp_...") as client:
        # Evaluate before acting
        decision = await client.evaluate(
            action_type="send_denial_letter",
            action_payload={"applicant_id": "A-9921", "reason": "high_risk_score"},
            context={"delegation_tier": 3},
        )

        if decision.can_proceed:
            await send_letter()

        # Log after acting
        await client.log(
            agent_name="underwriting-agent-v2",
            decision_type="denial_sent",
            decision_summary="Denial letter sent to applicant A-9921. Reason: high risk score (78/100).",
            risk_level="high",
            escalation_triggered=False,
        )

asyncio.run(run_agent())
```

---

## Error handling

```python
from glidepaths import (
    GlidepathsClient,
    AuthenticationError,
    RateLimitError,
    PolicyViolationError,
    ValidationError,
    GlidepathsError,
)
import time

client = GlidepathsClient(api_key="glp_...")

try:
    result = client.log(agent_name="my-agent", decision_type="action", decision_summary="...")
except AuthenticationError:
    print("Invalid or expired API key")
except RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after}s")
    time.sleep(e.retry_after)
except PolicyViolationError as e:
    print(f"All events blocked: {e.blocked_details}")
except ValidationError as e:
    print(f"Bad request: {e}")
except GlidepathsError as e:
    print(f"API error {e.status_code}: {e}")
```

---

## Configuration

```python
client = GlidepathsClient(
    api_key="glp_...",
    base_url="https://glidepaths.com",  # default
    timeout=10.0,                        # seconds, default 10
)
```

For self-hosted or staging environments, set `base_url` to your deployment URL.

---

## log() parameter reference

| Parameter | Type | Default | Description |
|---|---|---|---|
| `agent_name` | `str` | required | Agent identifier |
| `decision_type` | `str` | required | Category of decision |
| `decision_summary` | `str` | required | Human-readable description |
| `risk_level` | `str` | `"low"` | `"low"` \| `"medium"` \| `"high"` \| `"critical"` |
| `delegation_tier` | `int` | `1` | Authority level (1–5) |
| `agent_id` | `str` | `None` | UUID of registered agent |
| `input_hash` | `str` | `None` | Hash for idempotent retries |
| `model_version` | `str` | `None` | Model identifier (e.g. `"gpt-4o-2024-11"`) |
| `authority_scope` | `list[str]` | `None` | What the agent was authorised to do |
| `override_triggered` | `bool` | `False` | Whether a human override occurred |
| `override_rationale` | `str` | `None` | Explanation of override |
| `human_review_status` | `str` | `"not_required"` | Review status |
| `escalation_triggered` | `bool` | `False` | Whether escalation occurred |
| `escalation_path` | `str` | `None` | Where it was escalated |
| `data_lineage` | `str` | `None` | Source of input data |
| `compliance_tags` | `list[str]` | `None` | Regulatory framework tags |
| `metadata` | `dict` | `None` | Arbitrary additional fields |
| `source_system` | `str` | `None` | Calling system identifier |
| `session_id` | `str` | `None` | Session grouping key |
| `decision_timestamp` | `str` | server now | ISO 8601 timestamp |
