Identity for AI agents in one decorator. Native LangChain, CrewAI, AutoGen, and MCP middleware with attestation, delegation, and behavioral baselines.
Project description
tokendna-sdk
Identity for AI agents in one decorator.
Drop @identified on your LangChain / CrewAI / AutoGen / plain-Python agent — or attach TokenDNAMiddleware natively — and every action becomes a signed, replayable, audit-trail-ready event with zero infrastructure on your side.
from tokendna_sdk import identified, tool
@identified("research-bot", scope=["docs:read", "summarize"])
class ResearchAgent:
@tool("fetch_doc", target="document")
def fetch_doc(self, url: str) -> str: ...
@tool("summarize")
def summarize(self, text: str) -> str: ...
That's it. No HTTP setup, no schemas, no middleware to write. Every method call ships a signed UIS event under research-bot's identity and lands as a hop in a workflow trace.
Why?
Your agents are calling tools, escalating privileges, and pivoting through your infrastructure. You can't audit what you can't identify. Most observability tools treat agents as anonymous workers. TokenDNA gives them names, scopes, and cryptographic provenance.
After a couple of decorators, your agents have:
- Provable identity — every action signed under the agent's declared identity and scope
- Workflow attestation — multi-hop chains (Agent A → tool → Agent B) recorded as signed DAGs you can replay
- Delegation receipts — cryptographic proof that authority flowed from a human to the agent through every intermediate
- Behavioral baselines — alerts when an agent's behavior diverges from its norm
- Compliance posture — signed evidence packs for SOC 2 / ISO 42001 / NIST AI RMF / EU AI Act
Install
# Core (zero runtime deps)
pip install tokendna-sdk
# With native framework middleware
pip install "tokendna-sdk[langchain]"
pip install "tokendna-sdk[crewai]"
pip install "tokendna-sdk[autogen]"
pip install "tokendna-sdk[mcp]"
pip install "tokendna-sdk[all]"
Python 3.9+. The core uses only the stdlib (urllib); framework adapters are opt-in extras.
Two ways to use it
1. Classic — decorators (works with anything)
from tokendna_sdk import identified, tool
@identified("research-bot", scope=["docs:read"])
class ResearchAgent:
@tool("fetch_doc")
def fetch_doc(self, url): ...
2. Native framework middleware (LangChain shown — same idea for CrewAI / AutoGen)
# pip install "tokendna-sdk[langchain]"
from tokendna_sdk.integrations.langchain import TokenDNAMiddleware
agent = create_react_agent(
model="gpt-4o",
tools=[search_web, send_email],
middleware=[TokenDNAMiddleware(agent_id="research-bot",
scope=["web:read", "email:send"])],
)
The middleware adapter implements the LangChain v0.3 wrap_model_call / wrap_tool_call / after_agent hooks so you get attestation, behavioral scoring, and workflow traces without changing your agent code.
Sprint 2 ships native
TokenDNAMiddleware,TokenDNACrewCallback, andTokenDNAAutoGenMiddleware. Sprint 3 ships theTokenDNAMCPProxyMCP interceptor. The decorator wedge above works today.
Local mode (no server required)
If you don't set TOKENDNA_URL, the SDK runs in local mode: signed JSONL events are appended to ~/.tokendna/events.jsonl with a host-local HMAC key. Useful for trying it out, for tests, and for air-gapped environments.
from tokendna_sdk import make_client
client = make_client() # auto-picks remote if TOKENDNA_URL set, else local
print(client.health()) # {'status': 'ok', 'mode': 'local', ...}
client.normalize({"event_id": "demo-1", "agent_id": "research-bot"})
Inspect the trail:
tail -1 ~/.tokendna/events.jsonl | python -m json.tool
Configure (remote mode)
Two ways. Code takes precedence over env.
Environment
export TOKENDNA_URL="https://api.tokendna.io"
export TOKENDNA_API_KEY="..."
export TOKENDNA_TENANT_ID="..."
(The legacy TOKENDNA_API_BASE still works.)
Code
from tokendna_sdk import configure
configure(
url="https://api.tokendna.io",
api_key="...",
tenant_id="...",
timeout_seconds=5.0,
offline_buffer_path="/var/run/tokendna/buffer.jsonl", # optional
)
Disabled
configure(enabled=False) # decorators / middleware become no-ops — useful in CI
The high-level client
from tokendna_sdk import make_client
client = make_client()
# Health check
client.health()
# Best-effort event stream (buffered, batched)
client.normalize({"event_id": "...", "agent_id": "...", ...})
# Synchronous policy check — raises TokenDNAVerificationError on deny
verdict = client.verify("research-bot", "send_email", target="bob@example.com")
# Issue an attestation receipt for a completed workflow
att = client.attest("research-bot", hops=[{"actor": "...", "action": "..."}])
The decorators (classic surface — still supported)
@identified(agent_id, scope=..., description=..., delegation_receipt_id=...)
Class decorator. Stamps __tokendna_meta__ on the class with the declared identity. Non-invasive — does not modify methods, __init__, or attribute lookup.
@tool(name=None, target=None, capture_args=False)
Method decorator. Per call: push a hop onto the per-thread workflow trace, ship a UIS event, then call the wrapped method.
Cannot fail your program. Network failures buffer locally; transport errors retry on client.flush(). capture_args=False by default — opt in only for non-sensitive code; argument values land in the event when on.
get_agent_metadata()
Read the current thread's accumulated workflow trace.
Offline-safe by design
The SDK never blocks your code on TokenDNA availability. If the API is unreachable, events buffer (memory; disk if offline_buffer_path is set). Call client.flush() to drain when connectivity returns.
This is the wedge: you can adopt the SDK before you trust the platform, because adoption costs nothing on the bad days.
CLI
tokendna --help
tokendna config show # active config (key redacted)
tokendna policy plan ./bundle.json
tokendna policy apply <bundle_id>
tokendna replay <decision_id>
Sprint 3 adds: tokendna verify, tokendna demo, tokendna status, tokendna baseline show <agent_id>.
Examples
The examples/ directory in the repo:
examples/langchain_research_agent/— LangChain agent with attested tool callsexamples/quickstart/— Sprint 3 quickstart demos (LangChain / CrewAI / MCP / local mode)
What's the catch?
None for the SDK itself — Apache 2.0, zero runtime deps, works against any TokenDNA tenant or in offline-only mode. The value of the events you ship lives on the platform: trust graph, blast radius scoring, intent correlation, the network flywheel. The SDK is the on-ramp; the platform is where your agents become provably trustworthy.
Status
Beta (v0.2.x). The core surface — @identified / @tool, TokenDNAClient, TokenDNALocalClient, make_client — is stable. Framework middleware adapters land in v0.2.x as they're released. Pin the version while we're pre-1.0.
License
Apache 2.0. See LICENSE.
Links
TokenDNA — runtime identity & risk engine for AI agents.
Project details
Release history Release notifications | RSS feed
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 tokendna_sdk-0.2.0.tar.gz.
File metadata
- Download URL: tokendna_sdk-0.2.0.tar.gz
- Upload date:
- Size: 237.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
88a7bdfdc84eaab567a21af9a22e7baa1914f3d7a92abf7b34c6eb42e2ec5670
|
|
| MD5 |
bf03a72513590e33f94712a8214a33ff
|
|
| BLAKE2b-256 |
c21044bc315f2dbff94cb9bf7a11f6d521904afb344501f33f065c752074058b
|
Provenance
The following attestation bundles were made for tokendna_sdk-0.2.0.tar.gz:
Publisher:
publish.yml on Bobcatsfan33/TokenDNA
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tokendna_sdk-0.2.0.tar.gz -
Subject digest:
88a7bdfdc84eaab567a21af9a22e7baa1914f3d7a92abf7b34c6eb42e2ec5670 - Sigstore transparency entry: 1567473021
- Sigstore integration time:
-
Permalink:
Bobcatsfan33/TokenDNA@d2b1bf11cba61afee2529b2838a74bc2f74a2423 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Bobcatsfan33
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d2b1bf11cba61afee2529b2838a74bc2f74a2423 -
Trigger Event:
push
-
Statement type:
File details
Details for the file tokendna_sdk-0.2.0-py3-none-any.whl.
File metadata
- Download URL: tokendna_sdk-0.2.0-py3-none-any.whl
- Upload date:
- Size: 55.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
22918caa8154399667dedc94ee72d92388cca205e1622bfae9c6398becb25d34
|
|
| MD5 |
3044f0e661a2eed8768c311f880cd2ad
|
|
| BLAKE2b-256 |
39c0b337b7a5c7ee7d3a5183f4b8c2d9345d62937051ccc4a65183df6bc15107
|
Provenance
The following attestation bundles were made for tokendna_sdk-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on Bobcatsfan33/TokenDNA
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tokendna_sdk-0.2.0-py3-none-any.whl -
Subject digest:
22918caa8154399667dedc94ee72d92388cca205e1622bfae9c6398becb25d34 - Sigstore transparency entry: 1567473041
- Sigstore integration time:
-
Permalink:
Bobcatsfan33/TokenDNA@d2b1bf11cba61afee2529b2838a74bc2f74a2423 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Bobcatsfan33
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d2b1bf11cba61afee2529b2838a74bc2f74a2423 -
Trigger Event:
push
-
Statement type: