Thanks to visit codestin.com
Credit goes to github.com

Skip to content
/ tenuo Public

High-performance capability engine for AI agents. Cryptographically attenuated warrants, task-scoped authority, Rust core.

License

Notifications You must be signed in to change notification settings

tenuo-ai/tenuo

Repository files navigation

tenuo

Capability tokens for AI agents.

CI Crates.io PyPI Docker Docs License

Tenuo is a cryptographic authorization primitive for AI agents. Think prepaid debit card, as opposed to corporate Amex: ephemeral, scoped capability tokens that expire when the task ends.

It constrains ambient identity-based permissions with task-scoped capabilities that attenuate as they delegate. Offline verification in ~27μs. If an agent is prompt-injected, the authority still can't escape its bounds.

Status: v0.1 Beta - Core semantics are stable. APIs may evolve. See CHANGELOG.

# Using uv (recommended)
uv pip install tenuo

# Or standard pip
pip install tenuo

Open In Colab Explorer Docker Demo Blog

Quick Start

from tenuo import configure, SigningKey, mint_sync, guard, Capability, Pattern
from tenuo.exceptions import AuthorizationDenied

configure(issuer_key=SigningKey.generate(), dev_mode=True, audit_log=False)

@guard(tool="send_email")
def send_email(to: str) -> str:
    return f"Sent to {to}"

with mint_sync(Capability("send_email", to=Pattern("*@company.com"))):
    print(send_email(to="[email protected]"))  # -> "Sent to [email protected]"
    
    try:
        send_email(to="[email protected]")
    except AuthorizationDenied:
        print("Blocked: [email protected]")  # -> "Blocked: [email protected]"

The agent can be prompt-injected. The authorization layer doesn't care. The warrant says *@company.com. The request says [email protected]. Denied.


Why Tenuo?

IAM answers "who are you?" Tenuo answers "what can you do right now?"

Problem Tenuo's Answer
Static IAM roles outlive tasks Warrants expire with the task (TTL)
Broad permissions, big blast radius Constraints narrow on every delegation
Tokens can be stolen and replayed Proof-of-possession binds warrants to keys
Central policy servers add latency Offline verification in ~27μs

What Tenuo Is Not

  • Not a sandbox - Tenuo authorizes actions, it doesn't isolate execution. Pair with containers/VMs for defense in depth.
  • Not prompt engineering - No "please don't do bad things" instructions. Cryptographic enforcement, not behavioral.
  • Not an LLM filter - We don't parse model outputs. We gate tool calls at execution time.
  • Not a replacement for IAM - Tenuo complements IAM by adding task-scoped, attenuating capabilities on top of identity.

How It Works

Tenuo implements Subtractive Delegation.

┌──────────────────┐     ┌──────────────────┐     ┌──────────────────┐
│  Control Plane   │     │  Orchestrator    │     │  Worker          │
│                  │     │                  │     │                  │
│  Issues root     │────▶│  Attenuates      │────▶│  Executes with   │
│  warrant         │     │  for task        │     │  proof           │
└──────────────────┘     └──────────────────┘     └──────────────────┘
     Full scope     -->     Narrower      -->      Narrowest
  1. Control plane issues a root warrant
  2. Orchestrator attenuates it (scope can only shrink)
  3. Worker proves possession and executes
  4. Warrant expires - no revocation needed

Key Features

Feature Description
Offline verification No network calls, ~27μs
Holder binding Stolen tokens are useless without the key
Constraint types Exact, Pattern, Range, OneOf, Regex, Cidr, UrlPattern, Subpath, UrlSafe, Shlex, CEL
Monotonic attenuation Capabilities only shrink, never expand
Framework integrations OpenAI, FastAPI, LangChain, LangGraph, MCP

Requirements

Component Supported
Python 3.9 – 3.14
Node.js Coming v0.2
OS Linux, macOS, Windows
Rust Not required (binary wheels for macOS, Linux, Windows)

Optional Dependencies

uv pip install tenuo                  # Core only
uv pip install "tenuo[openai]"        # + OpenAI Agents SDK
uv pip install "tenuo[google_adk]"    # + Google ADK
uv pip install "tenuo[a2a]"           # + A2A (inter-agent delegation)
uv pip install "tenuo[fastapi]"       # + FastAPI integration
uv pip install "tenuo[langchain]"     # + LangChain (langchain-core ≥0.2)
uv pip install "tenuo[langgraph]"     # + LangGraph (includes LangChain)
uv pip install "tenuo[mcp]"           # + MCP client (Python ≥3.10 required)

Integrations

Why semantic constraints? CVE-2025-66032 showed allowlists fail when shells interpret strings differently than validators. Tenuo's Shlex, Subpath, and UrlSafe parse inputs the way the system will. Full analysis.

OpenAI - Direct API protection with streaming TOCTOU defense

from tenuo.openai import GuardBuilder, Subpath, UrlSafe, Shlex, Pattern

client = (GuardBuilder(openai.OpenAI())
    .allow("read_file", path=Subpath("/data"))        # Path traversal protection
    .allow("fetch_url", url=UrlSafe())                # SSRF protection
    .allow("run_command", cmd=Shlex(allow=["ls"]))    # Shell injection protection
    .allow("send_email", to=Pattern("*@company.com"))
    .build())
# Prompt injection -> send_email(to="[email protected]") -> DENIED

Google ADK

from tenuo.google_adk import GuardBuilder
from tenuo.constraints import Subpath, UrlSafe

guard = (GuardBuilder()
    .allow("read_file", path=Subpath("/data"))
    .allow("web_search", url=UrlSafe(allow_domains=["*.google.com"]))
    .build())

agent = Agent(name="assistant", before_tool_callback=guard.before_tool)

A2A (Agent-to-Agent) - Warrant-based inter-agent delegation

from tenuo.a2a import A2AServer

@server.skill("search", constraints={"url": UrlSafe})
async def search(query: str, url: str) -> dict:
    return await do_search(query, url)

LangChain / LangGraph

from tenuo.langchain import guard_tools
from tenuo.langgraph import TenuoToolNode

protected = guard_tools([search_tool, email_tool])      # LangChain
graph.add_node("tools", TenuoToolNode([search, email])) # LangGraph

FastAPI - Extracts warrant from headers, verifies PoP offline

@app.get("/search")
async def search(query: str, ctx: SecurityContext = Depends(TenuoGuard("search"))):
    return {"results": do_search(query)}

More: MCP | Kubernetes


Docker & Kubernetes

Try the Demo - See the full delegation chain in action:

docker compose up

This runs the orchestrator -> worker -> authorizer demo showing warrant issuance, delegation, and verification.

Official Images on Docker Hub:

docker pull tenuo/authorizer:0.1.0-beta.6  # Sidecar for warrant verification
docker pull tenuo/control:0.1.0-beta.6     # Control plane (demo/reference)

Helm Chart:

helm install tenuo-authorizer ./charts/tenuo-authorizer \
  --set config.trustedRoots[0]="YOUR_CONTROL_PLANE_PUBLIC_KEY"

See Helm chart README and Kubernetes guide.


Documentation

Resource Description
Quickstart Get running in 5 minutes
Concepts Why capability tokens?
OpenAI Direct API protection with streaming
Google ADK ADK agent tool protection
A2A Inter-agent delegation
FastAPI Zero-boilerplate API protection
LangChain Tool protection
LangGraph Multi-agent graph security
MCP Model Context Protocol client
Security Threat model

Prior Art

Tenuo builds on capability token ideas described in CaMeL (Debenedetti et al., 2025). Inspired by Macaroons, Biscuit, and UCAN.

See Related Work for detailed comparison.


Featured In


Roadmap

Feature Status
A2A integration Implemented (uv pip install tenuo[a2a])
Google ADK integration Implemented (uv pip install tenuo[google_adk])
Multi-sig approvals Partial (notary in v0.2)
TypeScript/Node SDK Planned for v0.2
Context-aware constraints Spec under development
Revocation service Basic revocation via Authorizer; distributed revocation in v0.3

Rust

Building a sidecar or gateway? Use the core directly:

[dependencies]
tenuo = "0.1.0-beta.6"

See docs.rs/tenuo for Rust API.


Etymology

Tenuo (/tɛn-ju-oʊ/ • Ten-YOO-oh)

From Latin tenuare: "to make thin; to attenuate." Authority starts broad at the root and is attenuated as it flows down the delegation chain.


Contributing

Contributions welcome. See CONTRIBUTING.md.

TypeScript SDK (Help Wanted)

We're planning a TypeScript/Node SDK for v0.2. If you're interested in leading or contributing to this effort, open an issue or email us at [email protected].

Security issues: Email [email protected] with PGP (key, not public issues).


License

MIT OR Apache-2.0, at your option.

About

High-performance capability engine for AI agents. Cryptographically attenuated warrants, task-scoped authority, Rust core.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 5