Verifiable delegated authority for AI agents. The human signs a scoped receipt; middleware verifies it before the agent calls a tool.
SD-JWT receipts + KB-JWT proof-of-possession + IETF status-list revocation. Per-call audience, action, permission, amount-cap, and expiry checks. Apache-2.0, one dep, 95 conformance tests. ZKP cohort v0.3.0 shipped — mutual handshake, scope-narrowing delegation, Stripe ACP gating.
npm install @bolyra/sdk @bolyra/mcp @bolyra/payment-protocols
v0.3.0 live
Prefer SD-JWT today? npm install @bolyra/delegation
v0.2.2
Available today · v0.2.2 on npm
~30 lines from npm install to a verified call. The human issues a scoped SD-JWT receipt; the agent presents it with a fresh KB-JWT (proof of holder-key possession); middleware verifies before any side effect. Rejects wrong audience, expired receipt, amount-over-cap, currency mismatch, revoked status, or replayed nonce — each with a crisp, switchable failure reason.
import { allow, present, verify, staticIssuerResolver } from '@bolyra/delegation';
import { generateKeyPair } from 'jose';
// 1. Human issues a scoped SD-JWT receipt to an agent.
const issuer = await generateKeyPair('EdDSA');
const holder = await generateKeyPair('EdDSA');
const receipt = await allow({
iss: 'did:web:bolyra.ai',
sub: 'did:bolyra:agent-alice',
aud: 'https://merchant.example',
act: 'checkout.charge',
perm: 'FINANCIAL_SMALL',
max: { amount: 50, currency: 'USD' },
ttlSeconds: 3600,
agentPubKey: holder.publicKey,
}, { privateKey: issuer.privateKey, kid: 'k1' });
// 2. Agent presents the receipt with a fresh server nonce (KB-JWT binding).
// `serverNonce` is the 32-byte random the merchant returned on its prior
// HTTP 402 response (`Bolyra-Challenge` header) — see /402 for the flow.
const serverNonce = crypto.randomUUID(); // in production: read from 402 response
const presented = await present(receipt, holder.privateKey, {
audience: 'https://merchant.example',
nonce: serverNonce,
});
// 3. Middleware verifies before the tool runs.
const result = await verify(presented, {
audience: 'https://merchant.example',
action: 'checkout.charge',
perm: 'FINANCIAL_SMALL',
amount: 25, currency: 'USD',
kbNonce: serverNonce,
trustedIssuers: staticIssuerResolver({ 'did:web:bolyra.ai': { k1: issuer.publicKey } }),
});
if (!result.ok) throw new Error(`delegation rejected: ${result.reason}`);
Today (v0.2.2): SD-JWT receipts with selective disclosure + KB-JWT proof-of-possession + IETF status-list revocation (draft-20) + EdDSA over Ed25519. Legacy v0.1 compact-JWS receipts still verify via acceptLegacyV01. ZKP upgrade (v0.3.0 — shipped): zero-knowledge mutual handshake and one-way scope-narrowing delegation chains, same circuit-compatible permission encoding. npm install @bolyra/sdk.
Zero-knowledge upgrade · v0.3.0 on npm
Same trust model, zero information leakage. The human proves uniqueness without revealing identity; the agent proves an operator-signed credential without revealing the credential. Both Groth16 proofs are bound to a session nonce, verified atomically. Flip one byte of a proof — the pairing check fails by construction.
import {
createHumanIdentity, createAgentCredential,
proveHandshake, verifyHandshake, Permission,
} from '@bolyra/sdk';
// 0. Fixtures — replace with your production values.
// secret: BN254-safe scalar; modelHash: Poseidon hash of the AI model id;
// operatorPrivKey: EdDSA-on-Baby-Jubjub private key held by the AI operator.
const humanSecret = 12345678901234567890n;
const modelHash = 0xabc1234567890n;
const operatorPrivKey = '0x' + '11'.repeat(32);
// 1. Human + agent enroll once. Commitments go on-chain; secrets never leave.
const human = await createHumanIdentity(humanSecret);
const agent = await createAgentCredential(
modelHash, operatorPrivKey,
[Permission.READ_DATA, Permission.FINANCIAL_SMALL],
BigInt(Math.floor(Date.now() / 1000) + 86400),
);
// 2. Mutual handshake: both Groth16 proofs in parallel, bound to one nonce.
const { humanProof, agentProof, nonce } = await proveHandshake(human, agent);
// 3. Verify off-chain or submit to IdentityRegistry.verifyHandshake() on Base.
const result = await verifyHandshake(humanProof, agentProof, nonce);
if (!result.verified) throw new Error('handshake rejected');
Under the hood: HumanUniqueness reuses the public Semaphore v4 ceremony (depth 20, no project setup); AgentPolicy uses a project-specific Groth16 key over pot16.ptau. Production proving runs on rapidsnark (~200ms for both proofs in parallel). The verifier in the demo above is the same snarkjs.groth16.verify that the on-chain Solidity verifier was generated from.
Protocol
Receipts are the on-ramp. The full Bolyra protocol is a complete authentication primitive for the human-AI boundary: three capabilities, zero information leakage. Same wire format and permission encoding as @bolyra/delegation — the v0.3 upgrade is drop-in.
Humans prove uniqueness via EdDSA + Poseidon commitments. AI agents prove operator-signed credentials. Both proofs are generated in parallel and verified in a single on-chain transaction.
Agents delegate scoped permissions to other agents through privacy-preserving delegation circuits. Each link in the chain is a ZK proof — the verifier sees only that the permission is valid, not the delegation path.
Neither party learns anything about the other beyond policy satisfaction. No identity attributes, no model weights, no operator details are revealed. Proof of compliance without disclosure.
ZKP SDK · v0.3.0 shipped
When you graduate from signed receipts to zero-knowledge proofs: @bolyra/sdk@0.3.0. Identity creation, credential issuance, parallel proof generation, on-chain verification, and one-way scope-narrowing delegation chains — without revealing operator, model, or scope to the relying party. Python bindings on PyPI as bolyra==0.3.0.
import { createHumanIdentity, createAgentCredential,
Permission, proveHandshake, verifyHandshake } from '@bolyra/sdk';
// Fixtures — replace with your production values.
const secretScalar = 12345678901234567890n;
const modelHash = 0xabc1234567890n;
const operatorKey = '0x' + '11'.repeat(32);
const expiryTimestamp = BigInt(Math.floor(Date.now() / 1000) + 86400);
// Human creates identity (EdDSA keypair + Poseidon commitment)
const human = await createHumanIdentity(secretScalar);
// AI agent gets operator-signed credential
const agent = await createAgentCredential(
modelHash, operatorKey,
[Permission.READ_DATA, Permission.WRITE_DATA],
expiryTimestamp
);
// Mutual handshake — both Groth16 proofs generated in parallel (<200ms with rapidsnark)
const { humanProof, agentProof, nonce } = await proveHandshake(human, agent);
// Verify off-chain (or submit to IdentityRegistry.verifyHandshake on Base L2 for ~590k gas)
const result = await verifyHandshake(humanProof, agentProof, nonce);
Market
The infrastructure for agentic commerce is being built right now. Bolyra is the missing privacy layer.
Non-human identities outnumber human users 3:1 in most enterprises. 63% of organizations cannot enforce purpose limitations on their AI agents (ISACA 2025).
NIST, IETF (OpenAI co-authoring), OWASP Agentic Top 10, and FIDO Payments Working Group are all working on agent identity. Bolyra is the ZKP-native approach.
Visa Trusted Agent Protocol (Stripe, Shopify, Cloudflare), Mastercard Agent Pay, and Google AP2 are converging on agent payment standards. Each needs a privacy-preserving identity layer.
Ecosystem
Plug Bolyra into your agent framework, wallet, or payment flow.
Drop-in auth for Model Context Protocol servers. One line wraps any McpServer with mutual ZKP handshake plus v=2 delegation-chain bundles: withBolyraAuthStdio(server, { resolveCredential, toolPolicy }). ~217ms proofs via rapidsnark. npm install @bolyra/mcp@0.3.0.
Stripe Agent Commerce Protocol wedge. verifyStripeACPSpend(ctx, amount, currency, 'authorize' | 'confirm') gates PaymentIntents against the leaf delegatee's cumulative-bit scope. confirm fails closed without SIGN_ON_BEHALF; AP2 / Visa TAP adapters in the same package. npm install @bolyra/payment-protocols@0.3.1.
ZKP-native trust verification for OpenClaw's onAgentVerify hook. 5-dimension scoring: proof validity, expiry, permissions, freshness, scope. npm install @bolyra/openclaw@0.3.0
Verify handshakes locally with zero gas. Batch sessions and post a single Merkle root on-chain. ~375x gas reduction at batch size 100.
LangChain BolyraAuthTool and CrewAI delegation adapters. pip install bolyra==0.3.0 — Python types + delegate() / verify_delegation() via subprocess bridge to @bolyra/sdk. Authenticate agents before sensitive operations in any framework.
Where this goes
The receipts you ship today are wire-compatible with the ZKP circuits underneath. Groth16 across all three, rapidsnark-accelerated for sub-200ms client-side proving. Verified through a unified Solidity contract stack on Base L2.
Circuit 1
Circuit 2
Circuit 3
Benchmarks
Measured on commodity hardware. Verifier deployed on Base Sepolia testnet — mainnet with v0.3.
Standards
Not just code — a protocol with formal specifications, a DID method, and conformance tests.
draft-bolyra-mutual-zkp-auth-01
Formal protocol specification for mutual zero-knowledge proof authentication. Defines message flows, proof formats, and verification procedures. v0.3.0 release locks the canonical 6-element Delegation public-signals layout for IETF submission.
did:bolyra
W3C Decentralized Identifier method for Bolyra identities. Supports both human and agent DID documents with ZKP-aware verification methods.
48 vectors, all passing
Conformance suite covers handshake, 2-hop delegation chain, forged-token EdDSA, nullifier-per-nonce, Poseidon3/4 binding sensitivity, LeanIMT root edges, canonical 6-element public-signals layout, financial scope narrowing, and cumulative-invariant rejection.
Become a design partner
Small cohort through 2026 to harden the protocol against real deployments. We are looking for agent platforms, identity providers, and regulated enterprises with a real integration scenario. No public partner list yet — we will name partners only with their permission.