# Surfinguard Python SDK

The trust layer for AI agents. Protect your AI agents from executing dangerous actions — phishing URLs, destructive commands, prompt injection, and sensitive file access.

## Installation

```bash
pip install surfinguard
```

With framework integrations:

```bash
pip install surfinguard[langchain]   # LangChain
pip install surfinguard[crewai]      # CrewAI
pip install surfinguard[autogen]     # AutoGen
```

## Quick Start

```python
from surfinguard import Guard

guard = Guard(api_key="sg_live_...")

# Check a URL
result = guard.check_url("https://paypa1.com/login")
print(result.level)    # DANGER
print(result.score)    # 9
print(result.reasons)  # ['Brand impersonation: paypal']

# Check a command
result = guard.check_command("rm -rf /")
print(result.allow)    # False
print(result.level)    # DANGER

# Check text for prompt injection
result = guard.check_text("Ignore all previous instructions")
print(result.level)    # DANGER

# Check file operations
result = guard.check_file_read("~/.ssh/id_rsa")
print(result.primitive)  # EXFILTRATION
```

## Policy Enforcement

The SDK can automatically block dangerous actions:

```python
from surfinguard import Guard, Policy, NotAllowedError

# MODERATE (default): blocks DANGER, allows SAFE and CAUTION
guard = Guard(api_key="sg_live_...", policy=Policy.MODERATE)

# STRICT: blocks CAUTION and DANGER, only allows SAFE
guard = Guard(api_key="sg_live_...", policy=Policy.STRICT)

# PERMISSIVE: never blocks, returns results only
guard = Guard(api_key="sg_live_...", policy=Policy.PERMISSIVE)

try:
    guard.check_command("rm -rf /")
except NotAllowedError as e:
    print(f"Blocked: {e.result.level} (score={e.result.score})")
```

## Decorator

Use `@guard.protect` to automatically check function arguments:

```python
@guard.protect("command")
def execute(cmd: str) -> str:
    import subprocess
    return subprocess.check_output(cmd, shell=True, text=True)

execute("ls -la")       # Allowed
execute("rm -rf /")     # Raises NotAllowedError
```

## All Check Methods

| Method | Action Type | Input |
|--------|------------|-------|
| `check_url(url)` | URL | URL string |
| `check_command(command)` | Command | Shell command |
| `check_text(text)` | Text | Free text / prompt |
| `check_file_read(path)` | File Read | File path |
| `check_file_write(path, content?)` | File Write | Path + optional content |
| `check(type, value, **metadata)` | Any | Universal check |

## CheckResult

Every check returns a `CheckResult`:

```python
class CheckResult:
    allow: bool              # Should the action be allowed?
    score: int               # 0-10 risk score
    level: RiskLevel         # SAFE, CAUTION, or DANGER
    primitive: RiskPrimitive # DESTRUCTION, EXFILTRATION, ESCALATION, PERSISTENCE, MANIPULATION
    primitive_scores: list   # Per-primitive breakdown
    reasons: list[str]       # Human-readable explanations
    alternatives: list[str]  # Safer alternatives (if any)
    latency_ms: float        # Analysis time
```

## Framework Integrations

### LangChain

```python
from surfinguard import Guard
from surfinguard.integrations.langchain import SurfinguardToolGuard

guard = Guard(api_key="sg_live_...")
tool_guard = SurfinguardToolGuard(guard)

# Wrap a single tool
safe_tool = tool_guard.wrap(shell_tool)

# Wrap all tools
safe_tools = tool_guard.wrap_all([shell_tool, file_tool, web_tool])
```

### CrewAI

```python
from surfinguard import Guard
from surfinguard.integrations.crewai import SurfinguardCrewGuard

guard = Guard(api_key="sg_live_...")
crew_guard = SurfinguardCrewGuard(guard)

# As a tool decorator
@crew_guard.check_tool("command")
def execute_command(command: str) -> str:
    ...

# As a step callback
crew = Crew(..., step_callback=crew_guard.step_callback)
```

### AutoGen

```python
from surfinguard import Guard
from surfinguard.integrations.autogen import SurfinguardAutoGenGuard

guard = Guard(api_key="sg_live_...")
ag_guard = SurfinguardAutoGenGuard(guard)

# Wrap functions
@ag_guard.wrap_function("command")
def execute(command: str) -> str:
    ...

# Check messages
ag_guard.check_message(message)
```

## Error Handling

```python
from surfinguard.exceptions import (
    AuthenticationError,  # Invalid API key (401)
    RateLimitError,       # Rate limit exceeded (429) — has .retry_after
    APIError,             # Server error (4xx/5xx) — has .status_code
    NotAllowedError,      # Policy blocked action — has .result
)
```

## Context Manager

```python
with Guard(api_key="sg_live_...") as guard:
    result = guard.check_url("https://example.com")
```

## API Reference

### Risk Levels

| Level | Score | Meaning |
|-------|-------|---------|
| SAFE | 0-2 | No risk detected |
| CAUTION | 3-6 | Potential risk, review recommended |
| DANGER | 7-10 | High risk, action should be blocked |

### Risk Primitives

| Primitive | Description |
|-----------|-------------|
| DESTRUCTION | Data loss, system damage |
| EXFILTRATION | Data theft, credential access |
| ESCALATION | Privilege escalation |
| PERSISTENCE | Backdoor installation, startup modification |
| MANIPULATION | Phishing, prompt injection, deception |
