npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@reykzett/agentid

v0.1.0

Published

Cryptographic identity for AI agents — verifiable reputation, delegation chains, and agent-to-agent trust

Readme

AgentID

Cryptographic identity for AI agents — verifiable reputation, delegation chains, and agent-to-agent trust.

AI agents have no verifiable identity. When an agent claims "I am Claude, assistant of Company X" — nobody can verify that. There is no trust, no reputation, no accountability. AgentID solves this with cryptographic identities: like SSL certificates, but for agents.

Features

  • Self-certifying identitydid:key addressing, no registry needed
  • Ed25519 signatures — sign and verify any agent action
  • Delegation chains — Human -> Agent A -> Agent B, each link cryptographically signed
  • Scoped authority — action-based permissions with mandatory expiry
  • Revocation — revoke delegations before expiry, checked across all verify paths
  • Attestations — verifiable claims about agent behavior and capabilities
  • Private key encapsulation — keys never exposed via public API
  • Tiny footprint — 3 runtime dependencies, ~25KB total

Install

npm install agentid

Requires Node.js >= 18.

Quick Start

Create an Identity

import { createIdentity } from "agentid";

const { identity, signer } = createIdentity({
  type: "agent",
  name: "DeployBot",
  provider: "acme-corp",
});

console.log(identity.id);
// did:key:z6Mkr1...

Sign and Verify an Action

import { createIdentity, signAction, verify } from "agentid";

const { signer } = createIdentity({ name: "DeployBot" });

const action = await signAction(signer, {
  action: "deploy",
  target: "production",
  version: "1.2.3",
});

const result = verify(action);
console.log(result.valid); // true

// Tamper with the payload
action.payload.version = "9.9.9";
const tampered = verify(action);
console.log(tampered.valid); // false
console.log(tampered.error?.code); // "INVALID_SIGNATURE"

Delegate Authority

import { createIdentity, createDelegation, verifyDelegation } from "agentid";

const human = createIdentity({ type: "human", name: "Alice" });
const agent = createIdentity({ name: "DeployBot", controller: human.identity.id });

const delegation = await createDelegation({
  issuer: human.signer,
  subject: agent.identity.id,
  scope: {
    actions: ["deploy-code", "sign-contract"],
    delegatable: false,
  },
  expiresIn: 3600, // 1 hour
});

const result = verifyDelegation(delegation);
console.log(result.valid); // true

Verify a Delegation Chain

import {
  createIdentity,
  createDelegation,
  signAction,
  verifyDelegationChain,
} from "agentid";

// Human -> Agent A -> Agent B
const human = createIdentity({ type: "human", name: "Alice" });
const agentA = createIdentity({ name: "Orchestrator" });
const agentB = createIdentity({ name: "DeployBot" });

// Human delegates to Agent A (re-delegatable)
const certA = await createDelegation({
  issuer: human.signer,
  subject: agentA.identity.id,
  scope: { actions: ["deploy-code"], delegatable: true },
  expiresIn: 3600,
});

// Agent A delegates to Agent B
const certB = await createDelegation({
  issuer: agentA.signer,
  subject: agentB.identity.id,
  scope: { actions: ["deploy-code"], delegatable: false },
  expiresIn: 1800,
  proofs: [certA.payload.id],
});

// Agent B signs an action
const action = await signAction(agentB.signer, {
  action: "deploy-code",
  target: "production",
}, { delegation: certB });

// Verify the full chain
const proofStore = new Map([[certA.payload.id, certA]]);

const result = await verifyDelegationChain({
  action,
  delegation: certB,
  expectedRoot: human.identity.id,
  resolveProof: (id) => Promise.resolve(proofStore.get(id) ?? null),
});

console.log(result.valid); // true
console.log(result.delegationValid); // true

Attestations

import { createIdentity, createAttestation, verifyAttestation } from "agentid";

const reviewer = createIdentity({ type: "human", name: "Alice" });
const agent = createIdentity({ name: "DeployBot" });

const attestation = await createAttestation(
  reviewer.signer,
  agent.identity.id,
  { type: "behavior_rating", rating: 5, context: "Flawless deployment" },
  { expiresIn: 86400 },
);

const result = verifyAttestation(attestation);
console.log(result.valid); // true

Revoke a Delegation

import {
  createIdentity,
  createDelegation,
  signAction,
  verify,
  createRevocation,
  MemoryRevocationRegistry,
} from "agentid";

const human = createIdentity({ type: "human", name: "Alice" });
const agent = createIdentity({ type: "agent", name: "DeployBot" });

const delegation = await createDelegation({
  issuer: human.signer,
  subject: agent.identity.id,
  scope: { actions: ["deploy-code"], delegatable: false },
  expiresIn: 3600,
});

// Agent acts under delegation — valid
const action = await signAction(agent.signer, { action: "deploy-code" }, { delegation });
const registry = new MemoryRevocationRegistry();
console.log((await verify(action, { revocation: registry })).valid); // true

// Human revokes the delegation
const revocation = await createRevocation(human.signer, delegation.payload.id, {
  reason: "Agent compromised",
});
await registry.revoke(revocation);

// Same action now fails
console.log((await verify(action, { revocation: registry })).valid); // false
console.log((await verify(action, { revocation: registry })).error?.code); // "REVOKED_DELEGATION"

Export and Restore an Identity

import { createIdentity, decryptSigner } from "agentid";

const { identity, signer } = createIdentity({ name: "DeployBot" });

// Export (encrypts private key with passphrase)
const bundle = await signer.export("my-secret-passphrase");

// Later: restore from encrypted bundle
const restored = await decryptSigner(bundle, identity, "my-secret-passphrase");
console.log(restored.identity.id === identity.id); // true

How It Works

A step-by-step walkthrough of the core flow: identity → delegation → action → verification → revocation.

The Scenario

You're building a system where a human (Alice) authorizes an AI agent (DeployBot) to deploy code. Later, the agent gets compromised and Alice needs to revoke its access immediately — before the delegation expires.

Step 1: Create Identities

import { createIdentity } from "agentid";

const alice = createIdentity({ type: "human", name: "Alice" });
const deployBot = createIdentity({
  type: "agent",
  name: "DeployBot",
  controller: alice.identity.id,
});

console.log(deployBot.identity.id);
// did:key:z6Mk...

Each identity gets an Ed25519 key pair and a self-certifying did:key address. The private key is captured in a closure inside the signer object — it can never be read directly, only used to sign.

Step 2: Delegate Authority

import { createDelegation } from "agentid";

const delegation = await createDelegation({
  issuer: alice.signer,
  subject: deployBot.identity.id,
  scope: {
    actions: ["deploy-code"],
    delegatable: false,
  },
  expiresIn: 3600, // 1 hour
});

Alice creates a signed delegation certificate: "I authorize DeployBot to perform deploy-code for 1 hour." The Ed25519 signature proves it came from Alice. The scope limits what the agent can do. delegatable: false prevents the agent from passing authority to another agent.

Step 3: Agent Acts Under Delegation

import { signAction } from "agentid";

const action = await signAction(
  deployBot.signer,
  { action: "deploy-code", target: "production", version: "2.1.0" },
  { delegation },
);

DeployBot signs the action with its own key. The delegation certificate is attached, so any verifier can see both who acted and who authorized it.

Step 4: Verify

import { verify } from "agentid";

const result = await verify(action);
console.log(result.valid);           // true
console.log(result.delegationValid); // true

verify() checks everything in order:

  1. Is DeployBot's signature over the action valid?
  2. Is the attached delegation signed by Alice?
  3. Does the delegation signer match the claimed issuer? (spoofing protection)
  4. Is DeployBot the delegation's subject?
  5. Is the delegation still within its expiry window?
  6. Is the delegation revoked? (if a RevocationChecker is provided)
  7. Does the scope cover the required capability? (if requiredCapability is set)

If any check fails, you get { valid: false, error: { code: "...", message: "..." } }. Verify never throws — invalid input is a normal result, not an exception.

Step 5: Revoke

import { createRevocation, MemoryRevocationRegistry } from "agentid";

const registry = new MemoryRevocationRegistry();

const revocation = await createRevocation(
  alice.signer,
  delegation.payload.id,
  { reason: "Agent exhibited unexpected behavior" },
);
await registry.revoke(revocation);

const result = await verify(action, { revocation: registry });
console.log(result.valid);       // false
console.log(result.error?.code); // "REVOKED_DELEGATION"

Alice creates a signed revocation — cryptographically proving she revoked it. From this point, every verify() call against this registry rejects actions based on that delegation. To restore access, create a new delegation.

Step 6: Delegation Chains (optional)

For multi-agent setups: Alice → Orchestrator → DeployBot.

const orchestrator = createIdentity({ type: "agent", name: "Orchestrator" });

// Alice delegates to Orchestrator (re-delegatable)
const certA = await createDelegation({
  issuer: alice.signer,
  subject: orchestrator.identity.id,
  scope: { actions: ["deploy-code"], delegatable: true },
  expiresIn: 3600,
});

// Orchestrator delegates to DeployBot (terminal)
const certB = await createDelegation({
  issuer: orchestrator.signer,
  subject: deployBot.identity.id,
  scope: { actions: ["deploy-code"], delegatable: false },
  expiresIn: 1800,
  proofs: [certA.payload.id],
});

// Verify the full chain back to Alice
const proofStore = new Map([[certA.payload.id, certA]]);

const result = await verifyDelegationChain({
  action: await signAction(deployBot.signer, { action: "deploy-code" }, { delegation: certB }),
  delegation: certB,
  expectedRoot: alice.identity.id,
  resolveProof: (id) => Promise.resolve(proofStore.get(id) ?? null),
  revocation: registry, // checks revocation at EVERY level
});

Chain verification walks upward: DeployBot → Orchestrator → Alice. If any link is expired, revoked, or has an invalid signature, the entire chain fails.

The Flow

Alice (Human)
  │
  ├── createIdentity() → did:key:z6MkAlice...
  │
  ├── createDelegation() → signed certificate
  │       │                  "DeployBot may deploy-code, 1h"
  │       ▼
  │   DeployBot (Agent)
  │       │
  │       ├── signAction() → signed action + delegation attached
  │       │
  │       ▼
  │   Verifier
  │       │
  │       ├── verify(action, { revocation }) → { valid: true/false }
  │       │
  │       └── Checks: Signature → Delegation → Expiry → Revocation → Scope
  │
  └── createRevocation() → immediately invalidates delegation

API Reference

Identity

| Function | Description | |----------|-------------| | createIdentity(opts?) | Create a new identity with fresh Ed25519 key pair | | resolveDidKey(did) | Resolve a did:key to an IdentityDocument | | decryptSigner(bundle, identity, passphrase) | Restore a Signer from an encrypted key bundle | | serializeIdentity(identity) | Canonical JSON string of an identity |

Signing & Verification

| Function | Description | |----------|-------------| | signAction(signer, payload, opts?) | Sign a payload with timestamp and optional delegation | | verify(action, opts?) | Verify a SignedAction (signature, delegation, revocation) — async | | verifySignedPayload(signed) | Verify the raw signature on a SignedPayload |

Delegation

| Function | Description | |----------|-------------| | createDelegation(opts) | Create a signed, scoped, time-limited delegation | | verifyDelegation(delegation, opts?) | Verify a single delegation certificate — async | | verifyDelegationChain(opts) | Verify a full delegation chain back to root |

Revocation

| Function | Description | |----------|-------------| | createRevocation(signer, delegationId, opts?) | Create a signed revocation for a delegation | | verifyRevocation(revocation) | Verify a revocation entry's signature |

| Class | Description | |-------|-------------| | MemoryRevocationRegistry | In-memory revocation registry (testing / ephemeral) | | FilesystemRevocationRegistry | Persistent registry in ~/.agentid/revocations/ |

All verification functions accept an optional { revocation: RevocationChecker } to check revocation status.

Attestation

| Function | Description | |----------|-------------| | createAttestation(signer, subject, claim, opts?) | Create a signed attestation about an agent | | verifyAttestation(attestation) | Verify an attestation's signature and expiry |

DID Utilities

| Function | Description | |----------|-------------| | didFromPublicKey(pubkey) | Create did:key:z... from 32-byte Ed25519 public key | | publicKeyFromDid(did) | Extract raw public key from did:key | | parseDid(input) | Parse and validate a DID string | | isValidDid(input) | Non-throwing DID validation |

Storage

| Class | Description | |-------|-------------| | MemoryStore | In-memory identity store (testing / ephemeral) | | FilesystemStore | Persistent store in ~/.agentid/ |

Both implement the IdentityStore interface: save(), load(), list(), delete().

Core Concepts

Addressing: did:key

Self-certifying, no registry needed. An Ed25519 public key is encoded as:

did:key:z + base58btc(0xed01 + 32-byte-pubkey)

The DID itself contains everything needed to verify signatures.

Signer Abstraction

Private keys are captured in closures — never exposed via the public API. The only way to extract a key is through passphrase-encrypted export (PBKDF2 + AES-256-GCM).

Delegation Certificates

UCAN-inspired, action-scoped delegation with mandatory expiry. Chainable: Human -> Agent A -> Agent B (if delegatable: true). Each link is signed by the issuer.

scope: {
  actions: ["deploy-code", "sign-contract"],
  resources: ["repo:org/myapp"],  // optional
  delegatable: false               // default
}

Verification as Result

verify() returns a VerificationResult with a typed error union — it never throws for invalid signatures. That's a normal outcome, not an exception.

type VerificationError =
  | { code: "INVALID_SIGNATURE"; message: string }
  | { code: "EXPIRED_DELEGATION"; message: string; expiredAt: string }
  | { code: "SCOPE_VIOLATION"; message: string; action: string; allowed: string[] }
  | { code: "CHAIN_BROKEN"; message: string; brokenAt: AgentDID }
  | { code: "REVOKED_DELEGATION"; message: string; delegationId: string; revokedAt: string }
  | { code: "INVALID_DID"; message: string };

Security

  • Strict Ed25519zip215: false enforces RFC 8032 / FIPS 186-5 compliance, preventing small-order public key forgery
  • Signer/issuer consistency — all verification paths check that the envelope signer matches the claimed issuer
  • Chain depth limit — delegation chains capped at 32 levels to prevent circular reference attacks
  • Canonical signing — RFC 8785 deterministic JSON ensures cross-platform signature reproducibility
  • Revocation support — delegations can be revoked before expiry via signed RevocationEntry; all verify paths support optional revocation checking
  • Key encapsulation — private keys never leave the Signer closure; export requires passphrase encryption

Project Structure

src/
  index.ts              Public API
  types.ts              All type definitions
  errors.ts             Typed error classes
  version.ts            Protocol version
  codec/                Base58, hex, base64url, canonical JSON
  did/                  did:key encoding/decoding/parsing
  crypto/               Key generation, signing, verification
  identity/             Identity creation, resolution, serialization
  delegation/           Delegation creation, verification, chain walking
  revocation/           Revocation creation, verification, registries
  attestation/          Attestation creation, verification
  storage/              MemoryStore, FilesystemStore
test/                   178 tests across 22 files
examples/               5 runnable example scripts

Development

npm install
npm test              # run 178 tests
npm run build         # ESM + CJS + DTS output
npm run typecheck     # strict TypeScript check

Run Examples

npx tsx examples/01-create-identity.ts
npx tsx examples/02-sign-and-verify.ts
npx tsx examples/03-delegate-authority.ts
npx tsx examples/04-verify-delegation-chain.ts
npx tsx examples/05-revoke-delegation.ts

Tech Stack

| Component | Choice | Why | |-----------|--------|-----| | Language | TypeScript (ESM + CJS dual) | Agent ecosystem is JS/TS-heavy | | Crypto | @noble/ed25519 + @noble/hashes | Audited, zero deps, ~20KB | | Canonicalization | canonicalize (RFC 8785) | Deterministic JSON for signing, ~2KB | | Build | tsup | ESM + CJS + DTS in one config | | Test | vitest | Fast, native TS/ESM |

Total runtime deps: 3 packages, ~25KB.

License

MIT