Metadata-Version: 2.4
Name: useagentguard
Version: 0.2.0
Summary: The Security & Cost Control Layer for AI Agents — Guard, Shield, and Sentinel tiers: budget control, per-agent credential isolation, OAuth scope enforcement, MCP policy enforcement, and compliance reporting.
License: MIT
Project-URL: Homepage, https://useagentguard.com
Project-URL: Repository, https://github.com/useagentguard/agentguard-sdk
Keywords: ai,agents,security,credentials,vault,oauth
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.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: cryptography>=41.0.0
Requires-Dist: pyyaml>=6.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"

# AgentGuard SDK

**The Security & Cost Control Layer for AI Agents.**

AgentGuard adds per-agent credential isolation, OAuth scope enforcement, an agent identity registry, permission drift detection, MCP policy enforcement, compliance reporting, and a full audit trail to any AI agent workflow — with zero cloud dependencies.

---

## Features

| Tier | Feature |
|------|---------|
| Guard | Budget enforcement (`$0.50/run`) with graceful stop or hard raise |
| Shield | Per-agent encrypted credential vault (Fernet/AES-128) |
| Shield | Agent identity registry with metadata |
| Shield | OAuth scope enforcement with `ScopeViolation` exceptions |
| Shield | Permission drift detection (baseline snapshots + diff) |
| Shield | Full JSON-lines audit trail per agent |
| **Sentinel** | **MCP tool-call interception with policy evaluation** |
| **Sentinel** | **Declarative policy engine (allow/deny lists, rate limits, predicates)** |
| **Sentinel** | **YAML policy file support** |
| **Sentinel** | **Audit-ready compliance reports (EU AI Act, NIST AI RMF, ISO 42001)** |

---

## Install

```bash
pip install agentguard
```

> **Requires Python 3.9+**, `cryptography`, and `pyyaml` (installed automatically).

---

## Quick Start

### 1. The `guard()` wrapper — Guard + Shield + Sentinel

```python
import openai
from agentguard import guard

client = guard(
    openai.OpenAI(),
    budget="$0.50/run",              # Guard tier — hard budget cap
    auth="isolated",                  # Shield tier — use per-agent vault
    agent_id="support-bot",           # Shield / Sentinel tier — identity
    scopes={"openai": ["chat.completions"]},  # Shield tier — allowed scopes
    mcp_policy="policies.yaml",       # Sentinel tier — MCP policy file
    on_violation="block",             # Sentinel tier — block | warn | log
    fallback="gpt-4o-mini",           # Cheaper fallback near budget limit
    on_limit="graceful_stop",         # Return sentinel instead of raising
)

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

if not response:
    print(f"Budget exceeded — spent ${client.spent:.4f}")
```

---

### 2. Per-Agent Credential Vault

```python
from agentguard.vault import AgentVault

vault = AgentVault("support-bot")

# Store an API key with allowed scopes
vault.store("openai", "sk-...", scopes=["chat.completions"])

# Retrieve it
cred = vault.get("openai")
print(cred.scopes)      # ["chat.completions"]
# Raw key is available but never logged/printed automatically
api_key = cred.get_key()

# Rotate with automatic audit log entry
vault.rotate("openai", new_key="sk-new-...")

# List services in this vault
print(vault.list_services())  # ["openai"]
```

Credentials are stored encrypted at `~/.agentguard/vaults/{agent_id}/credentials.enc`.
The master key lives at `~/.agentguard/master.key` (mode 0600, never logged).

---

### 3. Agent Identity Registry

```python
from agentguard.registry import Registry

registry = Registry()

registry.register(
    agent_id="support-bot",
    owner="team-cs",
    capabilities=["chat", "search"],
    created_by="kevin@company.com",
)

profile = registry.get("support-bot")
print(profile.owner)           # "team-cs"
print(profile.capabilities)   # ["chat", "search"]

# All registered agents
for p in registry.list():
    print(p.agent_id, p.owner)

# Full audit log for an agent
events = registry.audit_log("support-bot")
```

---

### 4. OAuth Scope Enforcement

```python
from agentguard.scopes import ScopeManager, ScopeViolation

scopes = ScopeManager()

# Define allowed scopes
scopes.set("support-bot", {
    "openai": ["chat.completions"],
    "github": ["repos.read"],
})

# Runtime check — OK
scopes.check("support-bot", "openai", "chat.completions")

# Runtime check — raises ScopeViolation
try:
    scopes.check("support-bot", "openai", "fine-tuning")
except ScopeViolation as e:
    print(f"Blocked: {e}")

# Non-raising check
if scopes.is_allowed("support-bot", "github", "repos.write"):
    ...  # won't reach here
```

---

### 5. Permission Drift Detection

```python
from agentguard.drift import DriftDetector

drift = DriftDetector()

# Save baseline
drift.snapshot("support-bot")

# ... later, scopes or capabilities change ...

changes = drift.check("support-bot")
for c in changes:
    print(c.change_type, c.category, c.field)
    # e.g.: added  scope  openai.fine-tuning
```

---

### 6. Sentinel — MCP Policy Enforcement

#### Define policies in Python

```python
from agentguard.policies import Policy, PolicyEngine, RateLimit
from agentguard.mcp_interceptor import MCPInterceptor

engine = PolicyEngine()

# Block PII table queries for all agents
engine.add_policy(Policy(
    name="no-pii-queries",
    description="Agents cannot run queries that select from PII tables",
    agent_ids=["*"],
    tools=["database_query"],
    deny_if=lambda params: any(
        t in params.get("query", "").lower()
        for t in ["users", "credentials", "payments"]
    ),
))

# Read-only filesystem for support-bot
engine.add_policy(Policy(
    name="read-only-filesystem",
    description="Support bot can only read files, not write",
    agent_ids=["support-bot"],
    tools=["file_write", "file_delete"],
    action="deny",
))

# Rate limit: max 100 API calls per minute per agent
engine.add_policy(Policy(
    name="rate-limit-api",
    description="Max 100 API calls per minute per agent",
    agent_ids=["*"],
    tools=["*"],
    rate_limit=RateLimit(max_calls=100, window_seconds=60),
))

interceptor = MCPInterceptor(policies=engine, on_violation="block")

result = interceptor.evaluate(
    agent_id="support-bot",
    tool="database_query",
    params={"query": "SELECT * FROM users"},
    context={"user": "kevin@company.com"},
)
print(result.allowed)    # False
print(result.reason)     # "Policy 'no-pii-queries' denied this action..."
print(result.audit_id)   # "evt_abc123..."
```

#### Or load from YAML

```yaml
# policies.yaml
policies:
  - name: no-pii-queries
    description: "Agents cannot query PII tables"
    agents: ["*"]
    tools: ["database_query"]
    deny_params:
      query:
        contains_any: ["users", "credentials", "payments"]

  - name: read-only-fs
    description: "Support bot is read-only"
    agents: ["support-bot"]
    tools: ["file_write", "file_delete"]
    action: deny

  - name: rate-limit
    description: "100 calls/min per agent"
    agents: ["*"]
    tools: ["*"]
    rate_limit:
      max_calls: 100
      window_seconds: 60
```

```python
from agentguard.policies import PolicyEngine
from agentguard.mcp_interceptor import MCPInterceptor

engine = PolicyEngine.from_yaml("policies.yaml")
interceptor = MCPInterceptor(policies=engine)
```

**Supported `deny_params` constraints:** `contains_any`, `contains_all`, `matches` (regex), `equals`, `not_equals`.

---

### 7. Sentinel — Compliance Reports

```python
from agentguard.compliance import ComplianceReport
from agentguard.registry import Registry
from agentguard.policies import PolicyEngine

registry = Registry()
engine = PolicyEngine.from_yaml("policies.yaml")

report = ComplianceReport(registry=registry, policy_engine=engine)

# Per-agent activity summary
summary = report.agent_summary("support-bot", since="2026-03-01")
print(summary["mcp_calls"])     # total MCP tool calls
print(summary["denied_calls"])  # blocked calls

# All denied actions
violations = report.violations(since="2026-03-01")
for v in violations:
    print(v["timestamp"], v["agent_id"], v["tool"], v["policy"])

# Compliance posture mapping (EU AI Act, NIST AI RMF, ISO 42001)
posture = report.compliance_posture()
for fw, controls in posture["frameworks"].items():
    print(f"\n{fw}")
    for ctrl in controls:
        print(f"  [{ctrl['status']}] {ctrl['control']}")

# Export to Markdown
report.export_markdown("compliance-report.md")

# Export to JSON
report.export_json("compliance-report.json")
```

---

### 8. Audit Trail

```python
from agentguard import audit_query
from agentguard.audit import log_event

# Query events for an agent
events = audit_query("support-bot", since="2026-03-01")
for event in events:
    print(event["timestamp"], event["action"], event["outcome"])

# Filter by action or outcome
denied = audit_query("support-bot", action="scope_check", outcome="denied")

# Log a custom event
log_event(
    agent_id="support-bot",
    action="custom_action",
    details={"info": "something happened"},
    outcome="allowed",
)
```

Audit logs are written to `~/.agentguard/audit/{agent_id}/{date}.jsonl`.
Sensitive fields (`key`, `secret`, `token`, `password`) are automatically redacted.

---

## File Layout

```
~/.agentguard/
├── master.key                          # Fernet master key (mode 0600)
├── registry.json                       # Agent identity registry
├── scopes.json                         # Scope policies per agent
├── vaults/
│   └── {agent_id}/
│       └── credentials.enc             # Encrypted credential store
├── snapshots/
│   └── {agent_id}.json                 # Drift baseline snapshots
└── audit/
    └── {agent_id}/
        └── 2026-03-27.jsonl            # JSON-lines audit log

src/agentguard/
├── audit.py             # Audit trail (all tiers)
├── compliance.py        # Sentinel — compliance reports
├── drift.py             # Shield — drift detection
├── guard.py             # Guard + Shield + Sentinel wrapper
├── mcp_interceptor.py   # Sentinel — MCP tool-call interceptor
├── policies.py          # Sentinel — policy engine
├── policy_loader.py     # Sentinel — YAML policy loader
├── registry.py          # Shield — agent identity registry
├── scopes.py            # Shield — OAuth scope enforcement
└── vault.py             # Shield — credential vault
```

---

## Configuration

`AGENTGUARD_HOME` env var overrides the default `~/.agentguard` directory.

```bash
AGENTGUARD_HOME=/var/run/agentguard python my_agent.py
```

---

## Development

```bash
git clone https://github.com/useagentguard/agentguard-sdk
cd agentguard-sdk/sdk
pip install -e ".[dev]"
pytest
```

---

## License

MIT © [AgentGuard](https://useagentguard.com)
