Metadata-Version: 2.5
Name: truerecord-sdk
Version: 0.1.2
Summary: Python SDK for the TrueRecord LLM Governance Platform
Author-email: "Exploring Data B.V." <support@truerecord.eu>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: cryptography>=41.0.0
Requires-Dist: httpx>=0.24.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Description-Content-Type: text/markdown

# TrueRecord SDK for Python

[TrueRecord](https://truerecord.eu) keeps a record of every interaction with an AI system in your app. This SDK sends those records. Each message is encrypted before it leaves your process, so only TrueRecord can process it. See the [TrueRecord SDK docs](https://truerecord.eu/docs/sdk) for setup and guides.

Requires Python 3.9+.

## Install

```
pip install truerecord-sdk
```

## Quick start

```python
from truerecord_sdk import TrueRecordClient, TrueRecordError

client = TrueRecordClient(
    api_key="tr_sk_...",
    public_key=open("truerecord_public.pem").read(),
    application_guid="...",
    interaction_guid="...",
)

try:
    # Send the message your user sends to the LLM
    client.send(user_message, "user", conversation_ref="session-42")

    # Send a message from the LLM to the user
    client.send(llm_message, "llm", conversation_ref="session-42")
except TrueRecordError as e:
    print(e)
```

## What to send

Each call to `send` creates a record of one message, either what the user sent (`"user"`) or what the LLM sent (`"llm"`). Use the same `conversation_ref` for both so TrueRecord can pair them.

```python
client.send(message, origin, message_datetime=None, conversation_ref=None)
```

| Argument | Required | Description |
|---|---|---|
| `message` | Yes | The message a user sent to the AI or the AI sent to the user. Can be any value that converts to JSON (string, dict, list, etc.). |
| `origin` | Yes | `"user"` if this is a message sent to the LLM, `"llm"` if it's the LLM's response, `"agent"` if it comes from an agent. |
| `message_datetime` | No | When the message happened, as an ISO 8601 string (e.g. `"2025-01-15T10:30:00Z"`). When not set defaults to the current time. |
| `conversation_ref` | No | A reference you choose (like a session ID or chat ID) to link related messages together. Pass the same value for a user message and its AI response so TrueRecord can pair them. |

## Implementation details

### Non-blocking (recommended)

Sending data to TrueRecord runs in the background so the rest of your code continues without waiting for TrueRecord to respond.

#### Synchronous apps

For apps using Flask, Django or scripts and CLI tools. Use a thread pool to send in the background.

```python
from concurrent.futures import ThreadPoolExecutor

executor = ThreadPoolExecutor(max_workers=4)

executor.submit(client.send, user_message, "user", conversation_ref="session-42")
executor.submit(client.send, llm_message, "llm", conversation_ref="session-42")
```

#### Asynchronous apps

For apps using FastAPI, Starlette, aiohttp or functions defined with `async`. Use `asyncio.create_task` to send in the background.

```python
import asyncio

asyncio.create_task(client.asend(user_message, "user", conversation_ref="session-42"))
asyncio.create_task(client.asend(llm_message, "llm", conversation_ref="session-42"))
```

### Blocking

Sending data to TrueRecord waits for TrueRecord to respond before the rest of your code continues.

#### Synchronous apps

```python
client.send(user_message, "user", conversation_ref="session-42")
client.send(llm_message, "llm", conversation_ref="session-42")
```

#### Asynchronous apps

```python
await client.asend(user_message, "user", conversation_ref="session-42")
await client.asend(llm_message, "llm", conversation_ref="session-42")
```

## Errors

All errors extend `TrueRecordError`, so you can catch them in one place.

| Error | When |
|---|---|
| `ValidationError` | A required argument is missing or the message can't be serialised to JSON. |
| `EncryptionError` | The public key isn't a valid RSA key. |
| `NetworkError` | TrueRecord couldn't be reached after retries. |
| `AuthenticationError` | The API key was rejected. |
| `APIError` | Any other server error. Has `status_code` and `detail`. |

## License

MIT
