Inference privacy
for AI agents
Peek-a-boo is a privacy protocol built for AI agent inference on Bittensor. Shielded payments, anonymous miner participation, and private agent routing — powered by ZK-SNARKs on Subtensor EVM.
01 Overview
When AI agents transact on public blockchains, every inference request, payment, and routing decision is visible. This creates surveillance vectors—anyone can track which agents use which miners, how much they pay, and when.
Peek-a-boo solves this by wrapping agent‑to‑miner interactions in a privacy layer. Agents deposit TAO into a shielded pool, generate ZK proofs to withdraw without linkability, and use stealth addresses so miners can receive payment without revealing their identity.
No observer can link a deposit to a withdrawal, or determine which agent paid which miner. The ZK proof proves you had funds in the pool—without revealing which deposit was yours.
02 Quickstart
Peek-a-boo is a monorepo built with npm workspaces and Turborepo. All packages build to ESM + CJS + DTS via tsup.
| Tool | Version | Purpose |
|---|---|---|
| Node.js | v24.11.1 | Runtime |
| npm | 11.6.2 | Package manager |
| Turborepo | latest | Monorepo build orchestration |
| tsup | latest | Library bundler (ESM + CJS + DTS) |
| Vitest | latest | Test runner |
| Hardhat | latest | Smart contract toolchain |
| Circom | 2.1.9 | ZK circuit compiler |
| snarkjs | latest | Groth16 proving system |
03 Architecture
The protocol is organized as a layered stack. Types at the base, core privacy primitives in the middle, chain adapters on top, and an SDK that composes everything into a unified API.
Storage Abstraction
Every core module uses constructor-injected storage adapters. In-memory implementations ship as defaults. SQLite adapters are opt-in via the @pas/storage-sqlite package—core has zero SQLite dependency.
Cryptography
All cryptographic operations use @noble/curves and @noble/hashes—pure JavaScript with no native bindings. The library stays fully platform-agnostic: no node:crypto, no WASM, no system dependencies.
04 Policy Engine
The policy engine enforces spend constraints on agent transactions. Rules are evaluated in priority order—the first matching rule determines the outcome.
| Rule Type | Description |
|---|---|
| Spend Limit | Per-transaction and cumulative limits with configurable time windows |
| Time Bounds | Restrict transactions to specific time ranges with timezone support |
| Whitelist | Allow only specific destination addresses |
| Denylist | Block specific destination addresses |
| Chain Restriction | Limit which chains an agent can transact on |
Rules are composable and priority-ordered. An agent session might have a per-tx limit of 1 TAO, a daily cumulative limit of 10 TAO, and a whitelist restricting payments to verified miners only.
05 Session Manager
Sessions scope an agent's access to the privacy layer. Each session has a lifecycle:
Sessions auto-expire on access check if their TTL has elapsed. A background cleanup sweep removes stale sessions. Policy rules are attached per-session, so different agents (or different tasks within one agent) can have different spending constraints.
06 Shielded Treasury
The treasury manages a UTXO note set representing shielded balances. Each note is a commitment that can only be spent once—double-spend prevention uses nullifiers.
Each deposit creates a note (commitment = Poseidon(nullifier, secret)). Spending a note reveals its nullifierHash but not the original commitment—breaking the link between deposits and withdrawals.
The treasury supports multi-token balances, greedy UTXO selection for optimal transaction construction, and filtered transaction history with timestamps.
07 Stealth Addresses
Stealth addresses let miners receive payments without revealing a persistent public address. The protocol implements ERC-5564 using ECDH on secp256k1.
How it works
The sender generates a one-time address from the miner's meta-address. The miner scans on-chain announcements using their viewing key to detect payments—a viewTag enables fast filtering so miners only need to attempt full derivation on ~1/256 of all announcements.
08 Smart Contracts
Five Solidity contracts handle the on-chain privacy operations. All contracts are ready for deployment on any EVM-compatible chain.
| Contract | Purpose |
|---|---|
| ShieldedPool | Privacy pool with Poseidon Merkle tree, Groth16 ZK verification for withdrawals |
| StealthAnnouncer | ERC-5564 announcement registry for stealth address discovery |
| IncrementalMerkleTree | Gas-efficient Merkle tree library with Poseidon hashing |
| PoseidonHasher | On-chain Poseidon hash wrapper (matches circomlib) |
| Groth16Verifier | Auto-generated ZK proof verifier from snarkjs |
Deposit & Withdraw Flow
Deposits insert a commitment into the Poseidon Merkle tree. Withdrawals require a Groth16 proof demonstrating knowledge of the pre-image without revealing which deposit is being spent. A 30-root history buffer prevents race conditions between concurrent deposits and withdrawals.
Deploy Order
09 ZK Circuits
The withdrawal circuit is written in Circom and compiled to a Groth16 proving system. It follows the Tornado Cash pattern, upgraded from keccak256 to Poseidon hashing for ZK efficiency.
Circuit Design
The recipient and amount are bound to the proof via a square constraint trick. A front-runner cannot change the destination or amount without invalidating the proof.
10 Bittensor EVM
Bittensor's Subtensor EVM is the primary deployment target. The adapter supports both mainnet and testnet.
| Network | Chain ID | RPC | Currency |
|---|---|---|---|
| Mainnet | 964 | lite.chain.opentensor.ai | TAO (18 decimals) |
| Testnet | 945 | test.chain.opentensor.ai | TAO (18 decimals) |
The BittensorAdapter implements the PrivacyBackend interface—the same interface used by the Railgun adapter. Config widening via BittensorAdapterConfig extends BackendConfig allows chain-specific options without breaking the shared interface.
11 Railgun Adapter
The Railgun adapter provides shielded ERC-20 transactions via the Railgun SDK's ZK-SNARK infrastructure. It uses a provider abstraction pattern—all SDK calls are isolated behind a single interface, making the adapter fully testable with mocks.
| Module | Responsibility |
|---|---|
| WalletManager | Engine initialization, wallet create/load |
| TransactionBuilder | Shield / unshield / transfer assembly |
| ProofService | Groth16 proof generation & verification |
| BalanceScanner | Shielded balance queries |
| ChainMap | ChainId ↔ NetworkName mapping |
Supported chains: Ethereum (1), BSC (56), Polygon (137), Arbitrum (42161).
12 Chain Strategy
| Priority | Chain | Status | Rationale |
|---|---|---|---|
| 1st | Bittensor EVM | Adapter built | Primary target — TAO privacy for AI agents |
| 2nd | Railgun | Adapter built | UTXO model matches our treasury, existing privacy infra |
| 3rd | Ethereum L2 | Stub | Cheapest gas, most agent activity |
| 4th | Aztec | Stub | Native private execution, deepest guarantees |
13 Package Map
16 packages total — 13 libraries, 2 config, 1 docs app. 246 tests across 5 packages, all passing.
| Package | Description | Status |
|---|---|---|
@pas/types | Shared type definitions (9 modules) | Live |
@pas/core | Privacy engine, policy, sessions, treasury, stealth | 65 tests |
@pas/storage-sqlite | SQLite persistence adapters | 41 tests |
@pas/contracts | Solidity contracts + ZK circuits | 41 tests |
@pas/adapter-bittensor | Bittensor Subtensor EVM adapter | 25 tests |
@pas/adapter-railgun | Railgun privacy backend | 74 tests |
@pas/sdk | Universal developer-facing API | Stub |
@pas/mcp-server | MCP server for agent tools | Stub |
@pas/settlement | L1/L2 providers, gasless relay | Stub |
@pas/adapter-ethereum | Native Ethereum L2 privacy | Stub |
@pas/adapter-aztec | Aztec private execution | Stub |
@pas/agent-crewai | CrewAI tool wrappers | Stub |
@pas/agent-langchain | LangChain tool wrappers | Stub |
14 SDK & MCP Server
The @pas/sdk provides a universal privacy interface for AI agents. It composes core modules into high-level operations: shield, unshield, transfer, query balance.
The @pas/mcp-server exposes these operations as MCP tools, so any MCP-compatible agent runtime (Claude, custom agents) can use privacy features without direct SDK integration.
Framework-specific wrappers for CrewAI and LangChain are scaffolded in @pas/agent-crewai and @pas/agent-langchain. These translate SDK calls into framework-native tool interfaces.
15 SDK Reference
The PASClient class is the primary developer-facing interface. It wraps a PrivacyBackend and exposes high-level operations for transactions, identity, and policy management.
Constructor & Lifecycle
Transaction API
| Method | Params | Returns |
|---|---|---|
pay(params) | { recipient, amount, token, memo? } | PASResult<PaymentReceipt> |
receive(params) | { token, singleUse? } | PASResult<ReceiveAddress> |
swap(params) | { fromToken, toToken, amount, slippageBps? } | PASResult<SwapReceipt> |
bridge(params) | { token, amount, fromChain, toChain } | PASResult<BridgeReceipt> |
Identity API
| Method | Params | Returns |
|---|---|---|
prove(id, disclosure) | credentialId: string, disclosure: DisclosureRequest | PASResult<Proof> |
credential(cred) | Credential { type, claims, issuer } | PASResult<string> (ID) |
disclose(attrs) | attributes: string[] | PASResult<Proof> |
Policy API
PrivacyBackend Interface
Every chain adapter implements this interface. Swap backends without changing application code.
16 MCP Tools
The @pas/mcp-server exposes 10 tools via the Model Context Protocol. Any MCP-compatible agent runtime can call these directly—no SDK integration required.
Transaction Tools
| Tool | Description | Inputs |
|---|---|---|
pas_pay | Send a shielded payment—no on-chain link between sender and recipient | recipient, amount, token, memo? |
pas_receive | Generate a single-use stealth receive address | token, singleUse? |
pas_swap | Private token swap within the shielded pool | fromToken, toToken, amount, slippageBps? |
pas_bridge | Bridge tokens privately between chains | token, amount, fromChain, toChain |
Treasury Tools
| Tool | Description | Inputs |
|---|---|---|
pas_get_balance | Query shielded balance—computed locally, never exposed on-chain | token |
pas_shield_funds | Move funds from a public address into the shielded pool | token, amount |
pas_unshield_funds | Withdraw from the shielded pool to a public address | token, amount, recipient |
Identity Tools
| Tool | Description | Inputs |
|---|---|---|
pas_prove | Generate a ZK proof for a credential without revealing underlying data | credentialId, attributes[] |
pas_credential_store | Store a ZK-provable credential in the vault | type, claims |
pas_disclose | Selectively reveal specific attributes for compliance | attributes[] |
MCP Resources
Read-only resources for querying protocol state without invoking tools.
| URI | Description |
|---|---|
pas://balance/{token} | Current shielded balance for a specific token |
pas://policies | Currently active policy rules |
pas://credentials | Available ZK-provable credentials |
pas://session | Current privacy session state |
All MCP tools accept amounts as string (not number) to preserve precision with large token values. Use Wei-denominated strings for TAO and ERC-20 tokens.
17 Roadmap
| Phase | Milestone | Status |
|---|---|---|
| 0 | Monorepo scaffolding, type system, config | Complete |
| 1 | Core infrastructure — policy, sessions, treasury, stealth | Complete |
| 2 | Persistence layer — SQLite storage adapters | Complete |
| 3 | Smart contracts — ShieldedPool, StealthAnnouncer | Complete |
| 4 | ZK circuits — Circom withdraw circuit, Groth16 proofs | Complete |
| 5 | Railgun adapter — provider abstraction pattern | Complete |
| 6 | Bittensor EVM adapter — chain config, adapter scaffold | Complete |
| 7 | Deploy contracts to Bittensor testnet | Next |
| 8 | Wire adapter to deployed contracts | Planned |
| 9 | SDK, MCP server, agent adapters | Planned |
| 10 | Relayer network, key management, security audit | Planned |