Cryptographically signed AI tool responses for preventing hallucinations
Project description
TrustChain v2.3.1
Cryptographic verification layer for AI agents - "SSL for AI"
💡 AI either hallucinates facts or gets them from tools. TrustChain signs every fact from real tools. Signature = trust.
TrustChain adds Ed25519 cryptographic signatures to AI tool responses, enabling:
- Proof of execution - data came from a real tool, not hallucinated
- Chain of Trust - cryptographically linked operation sequences
- Replay attack protection - nonce-based anti-replay
- Key rotation - seamless key management with persistence
- Audit trails - beautiful HTML reports for compliance
- Integrations - OpenAI, Anthropic, LangChain, MCP, FastAPI, Pydantic, OpenTelemetry
Installation
We recommend using uv for lightning-fast installation:
uv pip install trustchain
Or using standard pip:
pip install trustchain
Optional extras:
uv pip install trustchain[integrations] # LangChain + MCP support
uv pip install trustchain[ai] # OpenAI + Anthropic + LangChain
uv pip install trustchain[mcp] # MCP Server only
uv pip install trustchain[redis] # Distributed nonce storage
uv pip install trustchain[fastapi] # FastAPI middleware
uv pip install trustchain[all] # Everything
Quick Start
from trustchain import TrustChain
tc = TrustChain()
@tc.tool("weather")
def get_weather(city: str) -> dict:
return {"city": city, "temp": 22}
# Calling the function returns a SignedResponse
result = get_weather("Moscow")
print(result.data) # {'city': 'Moscow', 'temp': 22}
print(result.signature) # Ed25519 signature (Base64)
# Verify authenticity
assert tc.verify(result) == True
Features
Chain of Trust
Link operations cryptographically to prove execution order:
step1 = tc._signer.sign("search", {"query": "balance"})
step2 = tc._signer.sign("analyze", {"result": 100}, parent_signature=step1.signature)
step3 = tc._signer.sign("report", {"text": "Done"}, parent_signature=step2.signature)
# Verify the entire chain
assert tc.verify_chain([step1, step2, step3]) == True
Key Management
from trustchain import TrustChain, TrustChainConfig
# Persistent keys with auto-save
tc = TrustChain(TrustChainConfig(
key_file="keys.json",
enable_nonce=True
))
tc.save_keys()
# Key rotation (generates new keys)
old_key = tc.get_key_id()
new_key = tc.rotate_keys() # Also saves if key_file is configured
print(f"Rotated from {old_key[:16]} to {new_key[:16]}")
# Export for external verification
public_key = tc.export_public_key()
Multi-Tenant (Agent Isolation)
from trustchain.v2.tenants import TenantManager
manager = TenantManager()
research_agent = manager.get_or_create("research_agent")
code_agent = manager.get_or_create("code_agent")
# Each agent has isolated keys - cannot verify each other's signatures
result = research_agent._signer.sign("data", {"value": 42})
assert research_agent.verify(result) == True
assert code_agent.verify(result) == False # Different keys!
OpenAI / Anthropic Schema Export
# Get OpenAI-compatible function schema
schema = tc.get_tools_schema()
# Anthropic format
schema = tc.get_tools_schema(format="anthropic")
MCP Server (Claude Desktop)
from trustchain.integrations.mcp import serve_mcp
@tc.tool("calculator")
def add(a: int, b: int) -> int:
return a + b
serve_mcp(tc) # Starts MCP server for Claude Desktop
LangChain Integration
from trustchain.integrations.langchain import to_langchain_tools
lc_tools = to_langchain_tools(tc)
# Use with LangChain AgentExecutor
LangChain Callback Handler (v2.3.1)
Auto-sign all tool calls in LangChain agents:
from trustchain.integrations.langsmith import TrustChainCallbackHandler
handler = TrustChainCallbackHandler(sign_inputs=True, sign_outputs=True)
result = agent.invoke("What's the weather?", config={"callbacks": [handler]})
# Get signed chain of all tool calls
for response in handler.get_signed_chain():
print(f"{response.tool_id}: {response.signature[:24]}...")
AsyncTrustChain (v2.3.1)
Native async/await support for FastAPI and other async frameworks:
from trustchain.v2.async_core import AsyncTrustChain
async with AsyncTrustChain() as atc:
response = await atc.sign_async("db_query", {"result": 42})
assert atc.verify(response)
Pydantic v2 Integration (v2.3.1)
Auto-signing Pydantic models:
from trustchain.integrations.pydantic_v2 import TrustChainModel, SignedField
class UserProfile(TrustChainModel):
user_id: str = SignedField(...)
balance: float = SignedField(0.0)
user = UserProfile(user_id="U-123", balance=1000.0)
assert user.verify() # True
user.balance = 999999 # Tampering!
assert user.verify() # False - detected!
OpenTelemetry Integration (v2.3.1)
Add TrustChain signatures to OTel spans:
from trustchain.integrations.opentelemetry import TrustChainSpanProcessor
from opentelemetry.sdk.trace import TracerProvider
provider = TracerProvider()
provider.add_span_processor(TrustChainSpanProcessor())
# All spans now include trustchain.signature attribute
pytest Plugin (v2.3.1)
Built-in fixtures for testing:
# In conftest.py: pytest will auto-discover fixtures
from trustchain.pytest_plugin import tc, async_tc, signed_chain
def test_my_tool(tc):
response = tc.sign("my_tool", {"result": 42})
assert tc.verify(response)
Merkle Trees for Large Documents
from trustchain.v2.merkle import MerkleTree, verify_proof
pages = ["Page 1...", "Page 2...", ...]
tree = MerkleTree.from_chunks(pages)
# Verify single page without loading entire document
proof = tree.get_proof(42)
assert verify_proof(pages[42], proof, tree.root)
CloudEvents Format
from trustchain.v2.events import TrustEvent
event = TrustEvent.from_signed_response(result, source="/agent/bot")
kafka_headers = event.to_kafka_headers()
Audit Trail UI
from trustchain.ui.explorer import ChainExplorer
explorer = ChainExplorer(chain, tc)
explorer.export_html("audit_report.html")
# Export formats
json_data = explorer.to_json() # Returns list of responses
stats = explorer.get_stats() # Summary statistics
Why TrustChain? (Before / After)
❌ Without TrustChain:
# LLM hallucinates a tool response
result = {"balance": 1000000} # Fake! Tool was never called
agent.send_to_user(result) # User gets wrong data
✅ With TrustChain:
# Every tool response is signed
result = get_balance("user_123") # Returns SignedResponse
# Verification catches fakes
if not tc.verify(result):
raise SecurityError("Invalid signature - possible hallucination!")
Security Model
TrustChain protects against:
- ✅ LLM hallucinations (model invents tool output without calling it)
- ✅ Replay attacks (reusing old signed responses)
- ✅ Chain tampering (modifying execution order)
TrustChain does NOT protect against:
- ❌ Compromised infrastructure (if attacker has your private key)
- ❌ Prompt injection that tricks the real tool into returning malicious data
Best practices:
- Store private keys in KMS/Vault/HSM, not in code
- Use Redis nonce storage for production (in-memory = single instance only)
- Rotate keys periodically with
tc.rotate_keys()
Performance
| Operation | Latency | Throughput |
|---|---|---|
| Sign | 0.11 ms | 9,100 ops/sec |
| Verify | 0.22 ms | 4,500 ops/sec |
| Merkle (100 pages) | 0.18 ms | 5,400 ops/sec |
Storage overhead: ~124 bytes per operation.
Interactive Examples
See the examples/ directory:
| Notebook | Description |
|---|---|
| trustchain_tutorial.ipynb | Basic tutorial + all v2.3.1 integrations |
| trustchain_advanced.ipynb | Key persistence, multi-agent, Redis |
| trustchain_llm.ipynb | LLM integration examples |
Python examples:
mcp_claude_desktop.py- MCP Server for Claudelangchain_agent.py- LangChain integrationsecure_rag.py- RAG with Merkle verificationdatabase_agent.py- SQL with Chain of Trustapi_agent.py- HTTP client with CloudEvents
Architecture
trustchain/
v2/
core.py # Main TrustChain class
signer.py # Ed25519 signatures
schemas.py # OpenAI/Anthropic schema generation
merkle.py # Merkle tree implementation
events.py # CloudEvents format
tenants.py # Multi-tenant isolation
nonce_storage.py # Memory/Redis nonce storage
async_core.py # AsyncTrustChain
server.py # REST API
integrations/
langchain.py # LangChain adapter
langsmith.py # LangChain callback handler
pydantic_v2.py # Pydantic integration
opentelemetry.py # OTel span processor
mcp.py # MCP Server
pytest_plugin/ # pytest fixtures
ui/
explorer.py # HTML audit reports
Use Cases
| Industry | Application |
|---|---|
| AI Agents | Prove tool outputs are real, not hallucinations |
| FinTech | Audit trail for financial operations |
| LegalTech | Document verification with Merkle proofs |
| Healthcare (HIPAA) | Compliant AI data handling |
| Enterprise | SOC2-ready AI deployments |
Documentation
| Language | Guide |
|---|---|
| 🇷🇺 Russian | GUIDE_RU.md |
| 🇺🇸 English | GUIDE_EN.md |
| 🇨🇳 Chinese | GUIDE_ZH.md |
| 🇪🇸 Spanish | GUIDE_ES.md |
| 🇫🇷 French | GUIDE_FR.md |
| 🇩🇪 German | GUIDE_DE.md |
| 🇯🇵 Japanese | GUIDE_JA.md |
| 🇰🇷 Korean | GUIDE_KO.md |
| 🇧🇷 Portuguese | GUIDE_PT.md |
- Roadmap - Development roadmap
- MCP Security Spec - MCP integration details
- GitHub Wiki - Full API reference
License
MIT
Author
Ed Cherednik
Version
2.3.1
Project details
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 trustchain-2.3.2.tar.gz.
File metadata
- Download URL: trustchain-2.3.2.tar.gz
- Upload date:
- Size: 153.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e88b93b75c0b24807a44614ff4d3c7a5b24c54e49bff27890aa58cbcd762d2e2
|
|
| MD5 |
20cdf0e5288dd4ad01bf8ea6cbb0d485
|
|
| BLAKE2b-256 |
04c3e48df80ba9edc467503a407b0912cf9946de041f6225b6f55f63570cf642
|
Provenance
The following attestation bundles were made for trustchain-2.3.2.tar.gz:
Publisher:
publish.yml on petro1eum/trust_chain
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
trustchain-2.3.2.tar.gz -
Subject digest:
e88b93b75c0b24807a44614ff4d3c7a5b24c54e49bff27890aa58cbcd762d2e2 - Sigstore transparency entry: 923809130
- Sigstore integration time:
-
Permalink:
petro1eum/trust_chain@5ba93815f8a5611f411fe88766e08aee32558213 -
Branch / Tag:
refs/tags/v2.3.2 - Owner: https://github.com/petro1eum
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5ba93815f8a5611f411fe88766e08aee32558213 -
Trigger Event:
push
-
Statement type:
File details
Details for the file trustchain-2.3.2-py3-none-any.whl.
File metadata
- Download URL: trustchain-2.3.2-py3-none-any.whl
- Upload date:
- Size: 74.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5f3b65e58e92feb3c364fdfcf6c7dccec678f8146a4b9c88c8e40ec2c6becbae
|
|
| MD5 |
46956c46bd3cd35661f3bf14836a6653
|
|
| BLAKE2b-256 |
dc6860ff6654e0f88b190f5d39b4543a6c4ad00001397bcd2ae80abc081da919
|
Provenance
The following attestation bundles were made for trustchain-2.3.2-py3-none-any.whl:
Publisher:
publish.yml on petro1eum/trust_chain
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
trustchain-2.3.2-py3-none-any.whl -
Subject digest:
5f3b65e58e92feb3c364fdfcf6c7dccec678f8146a4b9c88c8e40ec2c6becbae - Sigstore transparency entry: 923809205
- Sigstore integration time:
-
Permalink:
petro1eum/trust_chain@5ba93815f8a5611f411fe88766e08aee32558213 -
Branch / Tag:
refs/tags/v2.3.2 - Owner: https://github.com/petro1eum
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5ba93815f8a5611f411fe88766e08aee32558213 -
Trigger Event:
push
-
Statement type: