Metadata-Version: 2.4
Name: neutralai-sdk
Version: 0.1.0
Summary: Official NeutralAI Python SDK for masking sensitive prompt data before it reaches AI applications.
Author: NeutralAI
License-Expression: MIT
Project-URL: Homepage, https://neutralai.co.uk/developers
Project-URL: Repository, https://github.com/nazifsohtaoglu/neutralai-gateway
Project-URL: Issues, https://github.com/nazifsohtaoglu/neutralai-gateway/issues
Keywords: neutralai,pii,prompt-security,ai-privacy,sdk
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
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: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.31.0
Provides-Extra: async
Requires-Dist: httpx>=0.27.0; extra == "async"
Dynamic: license-file

# NeutralAI Python SDK

## Package Status

Final public package name: `neutralai-sdk`.

Public PyPI publication is in progress. Do not show `python -m pip install neutralai-sdk`
on public website pages until the release workflow has published the package and
the registry verification step passes.

## Install (local workspace)

```bash
pip install -e .
```

For async web services and batch workers, install the async extra:

```bash
pip install -e ".[async]"
```

After public PyPI publication is complete:

```bash
python -m pip install "neutralai-sdk[async]"
```

## Usage (sync)

```python
from neutralai_sdk import NeutralAIClient

client = NeutralAIClient(base_url="http://localhost:8001", api_key="test-key")
res = client.mask("My email is user@example.com", reversible=False)
print(res.masked_text)
```

## Usage (async)

```python
import asyncio
from neutralai_sdk import AsyncNeutralAIClient

async def main():
    async with AsyncNeutralAIClient(base_url="http://localhost:8001", api_key="test-key") as client:
        res = await client.mask("Call me at +90 555 123 45 67")
        print(res.masked_text)

asyncio.run(main())
```

The async client keeps one `httpx.AsyncClient` open for connection pooling and retries transient `408`, `429`, and `5xx` responses by default.

## Usage (async streaming)

```python
import asyncio
from neutralai_sdk import AsyncNeutralAIClient

async def main():
    async with AsyncNeutralAIClient(
        base_url="http://localhost:8001",
        service_token="signed-service-token",
    ) as client:
        async for event in client.chat_stream(
            session_id="session-123",
            prompt="Summarize this text",
            provider="openai",
            model="gpt-4-turbo",
        ):
            if event.type == "token":
                print(event.token, end="")

asyncio.run(main())
```

## Integration registry

The SDK includes a small dependency-free adapter registry for framework wrappers.
The default registry exposes `langchain`, and teams can register their own
adapters without adding optional framework dependencies to the core package.

```python
from neutralai_sdk import NeutralAIClient, create_integration

client = NeutralAIClient(base_url="http://localhost:8001", agent_token="agent-token")
guard = create_integration("langchain", client, target_agent_id="agent-target")
safe_input = guard.sanitize_input({"input": "Email alice@example.com"})
```

## Supported Endpoints
- `POST /v1/shield/mask`
- `POST /v1/shield/unmask`
- `POST /v1/agents/mask`
- `POST /v1/chat/stream`

`POST /v1/shield/unmask` requires tenant-scoped authentication via API key or service token and only restores reversible vault tokens that still match the stored scope and TTL.

## Async Throughput

Use `asyncio.gather` with one shared `AsyncNeutralAIClient` to run many requests concurrently while reusing pooled connections:

```python
async with AsyncNeutralAIClient(base_url="https://api.neutralai.co.uk", api_key="...") as client:
    results = await asyncio.gather(*(client.mask(prompt) for prompt in prompts))
```

In internal local benchmarks with mocked 100 ms network latency, 50 concurrent async requests complete about 10x faster than the same requests issued sequentially through the sync client because the async version overlaps network wait time.

To reproduce the local latency benchmark shape:

```bash
python sdk/python/examples/async_benchmark.py
```

## Observability Hooks

You can pass `observability_hook` to capture SDK request lifecycle events:
- `request_start`
- `request_success`
- `request_error`

Diagnostics are redacted by default:
- API keys/tokens are reported as `<REDACTED>`
- prompt/tokenized values are summarized as `<REDACTED len=N>`

## License

MIT — see [LICENSE](./LICENSE). This SDK is a thin, dependency-light HTTP client
for the NeutralAI Gateway API; all PII detection and masking happens server-side.
