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 |
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ttt_otel-0.1.0.tar.gz.
File metadata
- Download URL: ttt_otel-0.1.0.tar.gz
- Upload date:
- Size: 13.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
48ed17ad1cc0ad42c09205c93c2aedfca18e5f317b709401d82d9962c73bce33
|
|
| MD5 |
070b121a6a2e4e6a1a9594501a67d1da
|
|
| BLAKE2b-256 |
eda25296da1d056f3340bec77b050006399d77ccbeb0fb9fcc7e6c393e8618c1
|
File details
Details for the file ttt_otel-0.1.0-py3-none-any.whl.
File metadata
- Download URL: ttt_otel-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8c258b3157cfac1badc5c71257361bc62cc8b92df3f5bb607a7bebd5d5ee96d9
|
|
| MD5 |
dce2451a1eb4699fdd0e5a39b50ff89c
|
|
| BLAKE2b-256 |
e760beb166e37a2c9352d57a51f1081aa8e4fbfdc6b5d96a90b3d9e694ca5a68
|