Observed since 20 Oct, 18:25 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Per-agent scoped tokens with revocation. Implements ACRF-02 defense pattern.
Per-agent scoped tokens with revocation. Implements the ACRF-02 (No Standard Agent Identity) defense pattern.
Part of the ACRF framework: https://github.com/kannasekar-alt/ACRF PyPI: https://pypi.org/project/acrf-tokens/ Presented at RSA Conference 2026.
No Docker. No setup. Just Python 3.10+.
Step 1 - Install:
pip install acrf-tokens
Step 2 - Generate an issuer (one-time setup):
from acrf_tokens import TokenIssuer
issuer = TokenIssuer.generate(issuer_name="acme-auth")
issuer.save("issuer_private.json") # KEEP SECRET
issuer.save_public("issuer_public.json") # share with validators
Step 3 - Mint a token for each agent:
from acrf_tokens import TokenIssuer
issuer = TokenIssuer.load("issuer_private.json")
token = issuer.issue(
agent_name="PricingAgent",
scopes=["pricing:read", "trades:propose"],
ttl_seconds=3600,
)
# token is a string - send it to the agent
Step 4 - Validate before allowing any action:
from acrf_tokens import TokenValidator
validator = TokenValidator.load("issuer_public.json")
agent_token = validator.validate(token, required_scope="trades:propose")
# raises TokenError subclass if invalid, expired, revoked, or missing scope
Step 5 - Revoke compromised tokens instantly:
validator.revoke(agent_token.token_id)
validator.save_revocations("revocations.json")
Most agent platforms today share a single API token across many agents. There is no per-agent identity, no scope, no expiration, no revocation. When that token leaks, every agent in the system is compromised.
This is ACRF-02: no standard agent identity.
acrf-tokens gives every agent its own short-lived, scoped, revocable token signed by a central issuer using Ed25519. Compromised tokens are revoked instantly. Stolen tokens expire on their own. No more shared secrets.
Ed25519 signed tokens Industry-standard cryptography. Issuer signs with private key, validator verifies with public key. No shared secret between issuer and validator.
Per-agent identity Every token names exactly one agent. No more "one key for all agents."
Explicit scope list Every token carries the exact set of permissions it grants. The validator enforces that the required scope is present before allowing the action.
Short-lived tokens Every token has an expires_at. Stolen tokens become useless on their own.
Instant revocation Compromised tokens can be revoked by token id (jti). Future validations fail immediately, regardless of expiration.
Public-key validation Validators only need the issuer public card. They never see the private key. You can have hundreds of validators with zero shared secrets.
Audit trail Every validation produces an audit record (success or failure) with token id, agent name, issuer, timestamp, and outcome.
Set the validator paths once:
export ACRF_TOKENS_PUBLIC=/etc/acrf/issuer_public.json
export ACRF_TOKENS_REVOCATIONS=/etc/acrf/revocations.json
Generate an issuer:
acrf-tokens generate-issuer acme-auth
Mint a scoped token:
acrf-tokens issue \
--issuer acme-auth_private.json \
--agent PricingAgent \
--scopes pricing:read,trades:propose \
--ttl 3600
Validate a token:
acrf-tokens validate <token-string> --scope trades:propose
Revoke a token:
acrf-tokens revoke <token-id>
List revoked tokens:
acrf-tokens list
The issuer private file contains the Ed25519 private key. Treat it like any other production secret:
What NOT to do:
Wrap your agent action handler with one validation call:
from acrf_tokens import TokenValidator
from acrf_tokens.exceptions import TokenError
import os
VALIDATOR = TokenValidator.load_with_revocations(
os.environ["ACRF_TOKENS_PUBLIC"],
os.environ["ACRF_TOKENS_REVOCATIONS"],
)
def handle_request(request):
token_string = request.headers["X-Agent-Token"]
try:
agent_token = VALIDATOR.validate(token_string, required_scope=request.required_scope)
except TokenError as exc:
return {"error": "unauthorized", "reason": str(exc)}, 401
# request authorized; proceed using agent_token.agent_name and agent_token.scopes
return process(request, agent_token)
That is it. Every action handler is now per-agent authorized with revocation, expiration, and scope enforcement.
SI-1 Every agent has a cryptographically verifiable identity distinct from user identity
SI-2 Tokens scoped per agent and per endpoint
SI-3 Identity material rotatable and revocable without impacting other agents
It only ensures that an agent action is authorized by a token that was issued by a trusted issuer, names a specific agent, has not expired, has not been revoked, and contains the required scope. That is the ACRF-02 defense pattern.
LangChain, CrewAI, AutoGen, MCP-based systems, custom agents. If your agents call APIs or each other, you can use this library.
Ravi Karthick Sankara Narayanan, Kanna Sekar
Apache 2.0
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.1.0 | 5 May 2026 | 1 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 18:25 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:71a39c7608665c3431b9a165b43f2718fc6016ef5e82e8d51bbe772344a85b67