langchain-fairseal
LangSmith tells you what the agent did. FairSeal proves it actually happened — on-chain.
langchain-fairseal is a LangChain callback handler that notarizes every tool call
on FairSeal: a cryptographic receipt layer anchored to Base mainnet.
Receipts are independently verifiable at verify.fairseal.io
by any party without trusting LangChain, AWS, or your infrastructure.
Quick Start
pip install langchain-fairseal
import os
from langchain_fairseal import FairSealCallbackHandler
# Handler: notarize every tool call, write receipt to LangSmith spans
handler = FairSealCallbackHandler(
api_key=os.environ["FAIRSEAL_NOTARY_API_KEY"], # fsn_... key
agent_id="my-agent/prod-v1", # stable agent identifier
sample_rate=1.0, # 100% notarized; 0.1 = 10% sampled
fail_open=True, # notarize failures never block agent
attach_to_langsmith=True, # write receipt_id to LangSmith spans
)
# Pass to any LangChain chain / agent / tool via config
result = my_chain.invoke(
{"input": "What is the weather in Taipei?"},
config={"callbacks": [handler]},
)
# Inspect receipts
print(handler.summary())
# {'total_notarized': 2, 'successful': 2, 'failed': 0, 'receipt_ids': ['nr_...', 'nr_...']}
last = handler.last_receipt
print(f"Latest receipt: {last.receipt_id}")
print(f"Verify: {last.verify_url}")
Architecture
LangChain Agent / Chain
│
▼
on_tool_start() ──────────────────────────────────────────────────────┐
│ │
│ sha256(inputs) → input_hash │
│ (raw inputs NEVER leave agent runtime) │
▼ │
[tool executes] │
│ │
▼ │
on_tool_end() │
│ │
│ sha256(output) → decision_hash │
│ │
▼ │
POST api.fairseal.io/v1/notarize │
{ schema: "agent_decision", │
metadata: { agent_id, input_hash, decision_hash, decided_at } } │
│ │
▼ │
receipt_id = "nr_..." ◄──────────────────────────────────────────────┘
│
├──► LangSmith run span metadata (fairseal_receipt_id)
└──► handler.receipts [in-memory list]
verify.fairseal.io/nr_... ← independent verification, no LangChain/AWS trust
Extension Point Note (LangChain 0.3.30)
The LangChain/AgentCore Payments blog post (2026-08-18) refers to an
AgentMiddleware.wrap_tool_call interface. This class does not exist in LangChain
0.3.30 / langchain-core 0.3.86 (confirmed by import inspection).
This package uses the stable, documented callback system:
BaseCallbackHandler.on_tool_start— capture tool name + input hashBaseCallbackHandler.on_tool_end— capture output hash + fire notarizeBaseCallbackHandler.on_tool_error— fail-open cleanup + error notarize
When/if AgentMiddleware ships as a stable API, the handler can be refactored
to use it without changing the public interface.
Configuration
| Parameter | Type | Default | Description |
|---|---|---|---|
api_key |
str | env FAIRSEAL_NOTARY_API_KEY |
FairSeal notary key (fsn_...) |
agent_id |
str | env FAIRSEAL_AGENT_ID or "langchain-agent" |
Stable agent identifier |
sample_rate |
float | 1.0 |
Fraction of tool calls to notarize (0.0–1.0) |
fail_open |
bool | True |
If True, notarize errors never block the agent |
attach_to_langsmith |
bool | True |
Write receipt to LangSmith run span metadata |
model |
str | None | Optional model tag in receipt metadata |
operator |
str | None | Optional operator tag in receipt metadata |
Environment Variables
FAIRSEAL_NOTARY_API_KEY=fsn_... # Primary auth key
FAIRSEAL_API_KEY=fsn_... # Fallback (also accepted)
FAIRSEAL_AGENT_ID=my-agent/prod # Default agent_id
FAIRSEAL_API_URL=https://api.fairseal.io # Override API base (for testing)
FAIRSEAL_TIMEOUT_S=10 # HTTP timeout in seconds
LANGCHAIN_API_KEY=ls_... # For LangSmith span attachment
PII Safety
Only SHA-256 hashes of tool inputs and outputs are transmitted to FairSeal.
Raw payload text never leaves the agent runtime. This is enforced in
langchain_fairseal.notarize.sha256_of() and tested in tests/test_notarize.py.
LangSmith Integration
When attach_to_langsmith=True and LANGCHAIN_API_KEY is set, each successful
receipt is written to the LangSmith run span as:
{
"fairseal_receipt_id": "nr_...",
"fairseal_verify_url": "https://verify.fairseal.io/nr_...",
"fairseal_tool_name": "search_tool",
"fairseal_agent_id": "my-agent/prod-v1"
}
Visible in the LangSmith trace UI under run metadata.
Development
pip install -e ".[dev]"
pytest -v # unit tests (mocked HTTP)
pytest tests/test_e2e.py -v # e2e (requires FAIRSEAL_NOTARY_API_KEY)
Positioning
| Concern | LangSmith | FairSeal |
|---|---|---|
| What did the agent do? | ✅ Full trace | ❌ Not designed for this |
| Prove it actually happened? | ❌ Internal log only | ✅ On-chain, third-party verifiable |
| Third-party verification? | ❌ Requires LangChain trust | ✅ Independent, no trust needed |
| Real-time observability? | ✅ | ❌ Batch anchoring (~2 min) |
Use both: LangSmith for debugging and observability, FairSeal for compliance and non-repudiation.
License
MIT © 2026 FairSeal
Release files for langchain-fairseal 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 | |
|---|---|---|---|
| langchain_fairseal-0.1.0.tar.gz | 18.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| langchain_fairseal-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 31.8 kB
Release files / langchain_fairseal-0.1.0.tar.gz
| Download URL | langchain_fairseal-0.1.0.tar.gz |
|---|---|
| Size | 18.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b95c53f63e6fcea0f6af47bb009655631506783972bf3c5ad4588851cfd7c3f0
|
|
BLAKE2b-256 checksum How to use checksums |
80d224fa8a6de871c5730dd0e044390a7a17de1293fb460676a548d3c0cd1b1f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|
Release files / langchain_fairseal-0.1.0-py3-none-any.whl
| Download URL | langchain_fairseal-0.1.0-py3-none-any.whl |
|---|---|
| Size | 13.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ea257fe9c7979300f812167b4936bef6b4709e8051a54283d6f88b82440a6a58
|
|
BLAKE2b-256 checksum How to use checksums |
b652ecb834dc19f2dbc6e2b207f9f4a66ea9446543806640acf1a4d349c41c19
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|