Metadata-Version: 2.4
Name: clampd
Version: 0.3.0
Summary: Runtime security SDK for AI agents — guard tool calls in 1 line
Project-URL: Homepage, https://clampd.dev
Project-URL: Repository, https://github.com/clampd/clampd
Author-email: Clampd <mehul.soni89@gmail.com>
License: BUSL-1.1
Keywords: agents,ai,anthropic,crewai,function-calling,langchain,openai,proxy,security
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic>=2.0
Provides-Extra: all
Requires-Dist: crewai>=0.80; extra == 'all'
Requires-Dist: langchain-core>=0.3; extra == 'all'
Requires-Dist: mcp>=1.0; extra == 'all'
Provides-Extra: crewai
Requires-Dist: crewai>=0.80; extra == 'crewai'
Provides-Extra: dev
Requires-Dist: mypy>=1.0.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
Requires-Dist: pytest>=7.0.0; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Provides-Extra: langchain
Requires-Dist: langchain-core>=0.3; extra == 'langchain'
Provides-Extra: mcp
Requires-Dist: mcp>=1.0; extra == 'mcp'
Description-Content-Type: text/markdown

# Clampd Python SDK

Runtime security for AI agents. Guard every tool call — OpenAI, Anthropic, LangChain, Google ADK — in 1 line.

## 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
```

## 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 CLAMPD_AGENT_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
```

## 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)` | Wrap OpenAI client |
| `clampd.anthropic(client)` | Wrap Anthropic client |
| `clampd.guard(tool_name)` | 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
