# Clampd Python SDK

Runtime security for AI agents. Guard every tool call — OpenAI, Anthropic, LangChain, Google ADK — in 1 line. Prompt and response scanning enabled by default.

## Installation

```bash
pip install clampd
```

With framework extras:

```bash
pip install clampd[langchain]    # LangChain callback handler
pip install clampd[mcp]          # MCP server support
pip install clampd[all]          # Everything
```

## Quick Start

```python
import clampd
from openai import OpenAI

# Configure once at startup
clampd.init(
    agent_id="my-agent",
    secret="ags_...",              # from dashboard → Agent → Secret
    gateway_url="http://localhost:8080",
    api_key="ag_live_...",
)

# Wrap your OpenAI client — done
client = clampd.openai(OpenAI())

# Use it exactly like before. Clampd intercepts every tool call.
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Look up active users"}],
    tools=[...],
)
# Dangerous tool calls → blocked before execution
# Safe tool calls → proceed normally
# Prompts scanned before LLM, responses scanned after
```

## What's New in 0.4.0

- **`scan_input` and `scan_output` now default to `True`** — prompts are scanned before the LLM call, responses are scanned after. Set `scan_input=False` to opt out.
- 50 detection rules across 20 languages
- 7 compliance frameworks (HIPAA, GDPR, PCI-DSS, CCPA, SOC 2, EU AI Act, NIST AI RMF)

## Configuration

Three ways to configure (pick one):

```python
# Option 1: Environment variables
# export CLAMPD_GATEWAY_URL=http://localhost:8080
# export CLAMPD_API_KEY=ag_live_...
# export CLAMPD_AGENT_ID=my-agent
# export JWT_SECRET=ags_...

# Option 2: Global init (recommended)
clampd.init(agent_id="my-agent", secret="ags_...", gateway_url="...", api_key="...")

# Option 3: Inline per-call
@clampd.guard("db.query", agent_id="my-agent", secret="ags_...", gateway_url="...", api_key="...")
def query(sql): ...
```

## Anthropic / Claude

```python
import clampd
from anthropic import Anthropic

clampd.init(agent_id="my-agent", secret="ags_...")
client = clampd.anthropic(Anthropic())

response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    messages=[{"role": "user", "content": "..."}],
    tools=[...],
)
```

## LangChain

```python
import clampd

handler = clampd.langchain(agent_id="my-agent", secret="ags_...")

result = executor.invoke(
    {"input": "Look up active users"},
    config={"callbacks": [handler]},
)
```

## Google ADK

```python
import clampd
from google.adk import Agent

agent = Agent(
    tools=[...],
    before_tool_callback=clampd.adk(agent_id="my-agent", secret="ags_..."),
)
```

## Direct Guard (any function)

```python
import clampd

clampd.init(agent_id="my-agent", secret="ags_...")

@clampd.guard("database.query")
def run_query(sql: str):
    return db.execute(sql)

# With response checking (opt-in)
@clampd.guard("file_read", check_response=True)
def read_file(path: str):
    return open(path).read()

run_query("SELECT * FROM users")     # allowed
run_query("DROP TABLE users")        # raises ClampdBlockedError
```

## Scanning Options

```python
# Defaults (v0.4.0+): scan_input=True, scan_output=True
client = clampd.openai(OpenAI(), agent_id="my-agent")

# Opt out of scanning
client = clampd.openai(OpenAI(),
    agent_id="my-agent",
    scan_input=False,   # skip prompt scanning
    scan_output=False,  # skip response scanning
)
```

## Error Handling

```python
from clampd import ClampdBlockedError

try:
    run_query("DROP TABLE users")
except ClampdBlockedError as e:
    print(f"Blocked: {e}")
    # e.risk_score, e.denial_reason, e.request_id
```

## API Reference

| Function | Description |
|----------|-------------|
| `clampd.init(...)` | Configure global client (once at startup) |
| `clampd.openai(client, **opts)` | Wrap OpenAI client (scan_input/scan_output on by default) |
| `clampd.anthropic(client, **opts)` | Wrap Anthropic client (scan_input/scan_output on by default) |
| `clampd.guard(tool_name, **opts)` | Decorator for any function |
| `clampd.langchain(...)` | LangChain callback handler |
| `clampd.adk(...)` | Google ADK before_tool_callback |

## Requirements

- Python 3.10+
- A running [Clampd](https://clampd.dev) gateway

## License

BUSL-1.1
