Metadata-Version: 2.4
Name: llmgateways
Version: 0.1.0
Summary: Protect OpenAI and Anthropic API calls from prompt injection, jailbreaks, and data-extraction attacks.
Project-URL: Homepage, https://llmgateways.com
Project-URL: Documentation, https://llmgateways.com/docs
Project-URL: Repository, https://github.com/Eirene2015/llmgateways-python-sdk
Project-URL: Bug Tracker, https://github.com/Eirene2015/llmgateways-python-sdk/issues
Author-email: LLM Gateways <hello@llmgateways.com>
License: MIT
License-File: LICENSE
Keywords: ai-safety,anthropic,llm,openai,prompt-injection,security
Classifier: Development Status :: 4 - Beta
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
Requires-Dist: httpx>=0.27
Provides-Extra: all
Requires-Dist: anthropic>=0.25; extra == 'all'
Requires-Dist: openai>=1.0; extra == 'all'
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.25; extra == 'anthropic'
Provides-Extra: dev
Requires-Dist: httpx>=0.27; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Provides-Extra: openai
Requires-Dist: openai>=1.0; extra == 'openai'
Description-Content-Type: text/markdown

# llmgateways

**Python SDK for [LLM Gateways](https://llmgateways.com)** — protect OpenAI and Anthropic API calls from prompt injection, jailbreaks, and data-extraction attacks.

[![PyPI](https://img.shields.io/pypi/v/llmgateways)](https://pypi.org/project/llmgateways/)
[![Python](https://img.shields.io/pypi/pyversions/llmgateways)](https://pypi.org/project/llmgateways/)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)

## Installation

```bash
pip install llmgateways            # core only
pip install "llmgateways[openai]"  # + OpenAI
pip install "llmgateways[anthropic]"  # + Anthropic
pip install "llmgateways[all]"     # + both
```

## Quick start

### OpenAI

```python
from llmgateways import wrap, PromptBlockedError
from openai import OpenAI

client = wrap(OpenAI(), api_key="lgk_...")

try:
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": "Hello!"}],
    )
    print(response.choices[0].message.content)
except PromptBlockedError as e:
    print(f"Blocked! Threats: {e.result.threats}")
    print(f"Risk score: {e.result.risk_score:.2f}")
```

### Anthropic

```python
from llmgateways import wrap, PromptBlockedError
from anthropic import Anthropic

client = wrap(Anthropic(), api_key="lgk_...")

try:
    response = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        system="You are a helpful assistant.",
        messages=[{"role": "user", "content": "Hello!"}],
        max_tokens=1024,
    )
    print(response.content[0].text)
except PromptBlockedError as e:
    print(f"Blocked! Threats: {e.result.threats}")
```

### Async

Both OpenAI and Anthropic async clients are supported:

```python
from llmgateways import wrap, PromptBlockedError
from openai import AsyncOpenAI

client = wrap(AsyncOpenAI(), api_key="lgk_...")

async def main():
    try:
        response = await client.chat.completions.create_async(
            model="gpt-4o",
            messages=[{"role": "user", "content": "Hello!"}],
        )
    except PromptBlockedError as e:
        print("Blocked:", e.result.threats)
```

## How it works

Every call to `chat.completions.create` or `messages.create` is intercepted:

1. The prompt is sent to the LLM Gateways detection engine
2. **L1** — pattern matching (instant, <1 ms)
3. **L2** — semantic similarity via MiniLM embedding model
4. **L3** — LLM judge (DeepSeek) for ambiguous cases
5. If blocked → `PromptBlockedError` is raised before the model is called
6. If allowed → the original call proceeds unchanged

## API reference

### `wrap(client, *, api_key, base_url="", timeout=10.0)`

Returns a protected proxy with the same interface as the original client.

| Parameter | Type | Description |
|-----------|------|-------------|
| `client` | `OpenAI` \| `Anthropic` | The LLM client to protect |
| `api_key` | `str` | Your `lgk_...` key from the [dashboard](https://llmgateways.com/dashboard) |
| `base_url` | `str` | Override for self-hosted deployments |
| `timeout` | `float` | Gateway request timeout in seconds (default: 10) |

### `PromptBlockedError`

```python
except PromptBlockedError as e:
    e.result.risk_score   # float 0.0–1.0
    e.result.action       # "block"
    e.result.threats      # list[str], e.g. ["jailbreak", "injection"]
    e.result.layer_used   # int (1, 2, or 3)
    e.result.reasoning    # str | None (populated by L3 LLM judge)
    e.result.latency_ms   # int
```

### `LLMGatewaysClient`

Use directly if you want to call the scan API without wrapping a client:

```python
from llmgateways import LLMGatewaysClient

gw = LLMGatewaysClient(api_key="lgk_...")
result = gw.scan("Hello!", system_prompt="You are helpful", model="gpt-4o")
print(result.action)  # "allow" or "block"

# Async
result = await gw.scan_async("Hello!")
```

## Get an API key

Sign up at [llmgateways.com](https://llmgateways.com) → Dashboard → API Keys → Create key.

## License

MIT
