ttt-otel
OpenTelemetry SpanProcessor that seals every LLM trace span into the
Proof-of-Time (PoT) chain via api.kenosian.com.
Install it alongside any OTel-compatible LLM framework (Langfuse, Phoenix, OpenLLMetry, …) to get cryptographic, tamper-evident audit trails for every agent interaction — without modifying your existing tracing code.
How it works
LLM agent span ends
│
▼
TTTSpanProcessor.on_end() ← non-blocking, span is never mutated
│
▼
Canonical fields extracted
(trace_id, span_id, name, model,
blake3(input), blake3(output), timestamps)
│
▼
content_hash = blake3(canonical_json)
│
▼
POST /pot/generate ← background thread, never blocks export
body: {eventId: content_hash,
prevEventId: <last_hash>}
│
▼
Server returns {pot_hash, signature, timestamp_ns}
Seal stored in-memory (+ optional file persist)
Privacy: raw prompt / completion text is never sent to the PoT server. Only the blake3 hash of each field travels over the wire.
Quick start
from opentelemetry.sdk.trace import TracerProvider
from ttt_otel import TTTSpanProcessor
provider = TracerProvider()
provider.add_span_processor(
TTTSpanProcessor(api_key="<YOUR_TTT_API_KEY>") # or os.environ["TTT_API_KEY"]
)
Tamper detection
from ttt_otel import verify
from ttt_otel._hash import canonical_fields_from_span
# Re-derive the hash from the original span and check it on the server
result = verify(
canonical_fields_from_span(span),
api_key="<YOUR_TTT_API_KEY>",
)
print(result["valid"]) # True → seal matches
print(result["chain_intact"]) # True → causal chain unbroken
If the span's output was modified after sealing, content_hash will differ
from the sealed event_id on the server, so verify() returns valid=False.
See examples/tamper_demo.py for a self-contained 30-second demo.
Environment variables
| Variable | Default | Description |
|---|---|---|
TTT_API_KEY |
(required) | API key (kns-…) for api.kenosian.com |
TTT_SERVER_URL |
https://api.kenosian.com |
Override for self-hosted deployments |
Installation
pip install ttt-otel # once published to PyPI
# or, from source:
pip install .
Running tests
pytest
Works with any OpenTelemetry backend
TTTSpanProcessor is a standard SpanProcessor. It attaches to any
TracerProvider alongside an OTLP exporter — the two processors run
independently. You only need to swap the exporter's endpoint and auth header.
| Backend | OTLP/HTTP endpoint | Auth header |
|---|---|---|
| Langfuse ✅ | https://cloud.langfuse.com/api/public/otel/v1/traces |
Authorization: Basic base64(pk:sk) |
| Arize Phoenix ✅ | Local: http://localhost:6006/v1/traces · Cloud: https://app.phoenix.arize.com/v1/traces |
Cloud: Authorization: Bearer <api-key> |
| MLflow 3.6+ ✅ | http://<tracking-server>/v1/traces |
x-mlflow-experiment-id: <id> |
| Any OTLP-compatible collector | Per-collector docs | Per-collector docs |
Helicone note: Helicone is an LLM proxy/gateway, not an OTLP backend. It does not expose an OTLP
/v1/tracesingest endpoint. Use Arize Phoenix or MLflow if you need a direct OTLP-compatible observability backend.
Examples
| File | What it shows |
|---|---|
examples/tamper_demo.py |
3-span agent session, one span tampered, tamper detected |
examples/langfuse_otel.py |
Langfuse OTLP pipeline + TTTSpanProcessor |
examples/phoenix_otel.py |
Arize Phoenix OTLP pipeline + TTTSpanProcessor (local & cloud) |
examples/mlflow_otel.py |
MLflow 3.6+ OTLP pipeline + TTTSpanProcessor |
Metadata
Release files for ttt-otel 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ttt_otel-0.1.0.tar.gz | 13.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ttt_otel-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 24.1 kB
Release files / ttt_otel-0.1.0.tar.gz
| Download URL | ttt_otel-0.1.0.tar.gz |
|---|---|
| Size | 13.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
48ed17ad1cc0ad42c09205c93c2aedfca18e5f317b709401d82d9962c73bce33
|
|
BLAKE2b-256 checksum How to use checksums |
eda25296da1d056f3340bec77b050006399d77ccbeb0fb9fcc7e6c393e8618c1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|
Release files / ttt_otel-0.1.0-py3-none-any.whl
| Download URL | ttt_otel-0.1.0-py3-none-any.whl |
|---|---|
| Size | 10.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8c258b3157cfac1badc5c71257361bc62cc8b92df3f5bb607a7bebd5d5ee96d9
|
|
BLAKE2b-256 checksum How to use checksums |
e760beb166e37a2c9352d57a51f1081aa8e4fbfdc6b5d96a90b3d9e694ca5a68
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|