Skip to content

samvardhan03/AgentID

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AgentID

Every AI agent in production today authenticates with hardcoded API keys. That's the equivalent of shipping a web app with password: admin. AgentID fixes this.

AgentID gives every AI agent a cryptographic identity — an Ed25519 keypair that acts as the agent's passport. Any service can verify "this request came from agent X, with scopes Y, and has not been tampered with" in under 0.1 ms, with zero network calls, zero key servers, zero JWT libraries.

cargo add agentid-core

Why not JWTs?

JWT was designed for human browser sessions. For machine-to-machine agent traffic, it's the wrong tool:

JWT (RS256) AgentID Token
Size ~800 bytes ~173 bytes
Verification ~0.4 ms (RSA) <0.1 ms (Ed25519)
Rate limits ❌ Not in spec ✅ Baked into the signed payload
Scopes String claim (not enforced) ✅ Cryptographically bound
Key discovery JWK endpoint required ✅ Offline, no network
Agent-native

The AgentID binary wire format (0xA9 0x1D magic) packs a complete token — issuer pubkey, scopes, TTL, call quota, and Ed25519 signature — into 173 bytes. Deserialisation and signature verification complete in a single cache-hot pass.


Quick Start

Rust

use agentid_core::{AgentIdentity, TokenBuilder, verify_token};

// Derive a deterministic identity from name + project.
// Same inputs → same keypair, every time, on every machine.
let identity = AgentIdentity::derive("research-bot", "phd-lab", None)?;

println!("public key : {}", identity.public_key_hex());
println!("fingerprint: {}", identity.fingerprint()); // ag:sha256:022a6b57...

// Mint a compact binary token — 173 bytes, not 800.
let token = TokenBuilder::new(&identity)
    .scopes(["read:arxiv", "write:notes"])
    .ttl_seconds(900)
    .max_calls(100)
    .build()?;

// Verify offline. No network. No key server. <0.1 ms.
let claims = verify_token(&token, Some(&identity.public_key()))?;

assert_eq!(claims.name, "research-bot");
assert!(claims.permits("read:arxiv")); // wildcard scope matching

CLI

# Initialise the local vault
agentid init

# Store an identity (encrypted with AES-256-GCM, password-derived via PBKDF2)
agentid keys add --name research-bot --project phd-lab

# Mint a token
agentid mint --name research-bot --project phd-lab \
  --scopes "read:arxiv,write:notes" --ttl 900 --max-calls 100

# Verify
agentid verify <token>
# Token verified.
#   name         research-bot
#   project      phd-lab
#   fingerprint  ag:sha256:022a6b577d76ae03
#   scopes       read:arxiv, write:notes
#   expires      2026-05-02T10:14:51.000Z
#   max_calls    100

# Start the optional gRPC server for centralised key management
agentid serve --port 6100

TypeScript / Bun

import { AgentIdentity, verifyToken, vault } from "agentid";

// Derive an identity
const id = AgentIdentity.derive("research-bot", "phd-lab");

// Mint
const token = id.mintToken({ scopes: ["read:arxiv"], ttlSeconds: 900 });

// Verify
const claims = verifyToken(token, id.publicKey);
console.log(claims.fingerprint); // ag:sha256:022a6b577d76ae03

Architecture

Token Wire Format

off  size  field
---  ----  -----
  0     2  magic          0xA9 0x1D
  2     1  version        0x01
  3     1  flags          0x00 (reserved)
  4     8  issued_at      i64 BE (unix seconds)
 12     8  expires_at     i64 BE
 20     4  max_calls      u32 BE  (0 = unlimited)
 24     8  token_id       u64 BE  (random nonce, replay protection)
 32    32  issuer_pubkey  Ed25519 (32 bytes)
 64   var  name, project, scopes  (u8 length-prefixed utf-8)
END    64  Ed25519 signature over bytes [0..END)

Every field is inside the signed region. A single byte flip anywhere causes verification to fail.

Deterministic Key Derivation

IKM   = name ‖ 0x00 ‖ project ‖ 0x00 ‖ seed?
salt  = b"agentid-v1"
info  = b"ed25519-signing-key"
okm   = HKDF-SHA256(salt, IKM, info, len=32)
sk    = Ed25519 SigningKey::from_bytes(okm)

The same (name, project) pair always produces the same keypair — reproducible across machines, no secret material to copy around.

Local Vault

Secret keys at ~/.agentid/keys/<fingerprint>.key:

  • KDF: PBKDF2-HMAC-SHA256, 200 000 iterations
  • Cipher: AES-256-GCM (nonce + tag per file)
  • Permissions: 0o600 (user-only)
  • Index: Unencrypted ~/.agentid/index.json (public metadata only — safe to back up)

Scope Matching

"read:arxiv"  →  matches exactly "read:arxiv"
"read:*"      →  matches "read:arxiv", "read:notes", ...
"*"           →  matches any scope
"*:papers"    →  matches "read:papers", "write:papers"

Feature Flags

Flag What it adds
server (default) Tonic gRPC server — agentid serve --port 6100
napi-bindings N-API cdylib for Node / Bun TypeScript SDK
# Core library only (no async runtime)
agentid-core = { version = "0.1", default-features = false }

# Default: core + gRPC server
agentid-core = "0.1"

Roadmap

  • v0.1 — Ed25519 identity, binary tokens, AES-256-GCM vault, gRPC server, TypeScript SDK, Bun CLI ✅
  • v0.2 — LangGraph + CrewAI framework middleware, token revocation list, key rotation
  • v0.3 — AgentID Cloud (hosted key management, audit log, team dashboard)

License

Apache License 2.0 — free for open-source and commercial use with attribution.

When using AgentID in a public project or product, you must give clear credit to the original author, Samvardhan Singh, in your documentation, README, or NOTICE file.

For enterprise use requiring white-labelling or a no-attribution obligation, contact the author for a commercial licence.

See LICENSE for the full text.


Three tools. Four launches. One platform. Ship the knife before you sell the kitchen.

About

A high-performance cryptographic identity layer for AI workflows (LangGraph, CrewAI). AgentID issues compact, offline-verifiable tokens (173 bytes) using deterministic Ed25519 signatures, eliminating the need for databases or infinite-TTL API keys.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors