Skip to main content

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.

CI Python 3.10+ License: MIT

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

TrustChain Architecture


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:

Chain of Trust

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

Merkle Tree Verification

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 Claude
  • langchain_agent.py - LangChain integration
  • secure_rag.py - RAG with Merkle verification
  • database_agent.py - SQL with Chain of Trust
  • api_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

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

trustchain-2.3.2.tar.gz (153.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

trustchain-2.3.2-py3-none-any.whl (74.9 kB view details)

Uploaded Python 3

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

Hashes for trustchain-2.3.2.tar.gz
Algorithm Hash digest
SHA256 e88b93b75c0b24807a44614ff4d3c7a5b24c54e49bff27890aa58cbcd762d2e2
MD5 20cdf0e5288dd4ad01bf8ea6cbb0d485
BLAKE2b-256 04c3e48df80ba9edc467503a407b0912cf9946de041f6225b6f55f63570cf642

See more details on using hashes here.

Provenance

The following attestation bundles were made for trustchain-2.3.2.tar.gz:

Publisher: publish.yml on petro1eum/trust_chain

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for trustchain-2.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 5f3b65e58e92feb3c364fdfcf6c7dccec678f8146a4b9c88c8e40ec2c6becbae
MD5 46956c46bd3cd35661f3bf14836a6653
BLAKE2b-256 dc6860ff6654e0f88b190f5d39b4543a6c4ad00001397bcd2ae80abc081da919

See more details on using hashes here.

Provenance

The following attestation bundles were made for trustchain-2.3.2-py3-none-any.whl:

Publisher: publish.yml on petro1eum/trust_chain

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page