Skip to content

Build a Private Agent

Create an AI agent that operates with complete financial privacy using PrivChain's privacy pools and zero-knowledge proofs.

Overview

This guide walks through building an agent that:

  1. Operates anonymously - No link between transactions
  2. Proves legitimacy - ZK proofs without revealing identity
  3. Earns privately - Receives rewards to unlinkable addresses
  4. Maintains reputation - Builds trust without compromising privacy

Architecture

mermaid
graph TB
    subgraph Agent["Private Agent"]
        Core[Agent Core]
        Wallet[HD Wallet]
        Notes[Note Storage]
        Identity[ZK Identity]
    end
    
    subgraph PrivChain["PrivChain Protocol"]
        Pool[Privacy Pool]
        Registry[Identity Registry]
        Work[PoAW System]
    end
    
    subgraph External["External World"]
        Clients[Clients]
        Services[Services]
    end
    
    Core --> Wallet
    Core --> Notes
    Core --> Identity
    
    Wallet --> Pool
    Identity --> Registry
    Core --> Work
    
    Clients -->|Tasks| Core
    Core -->|Proofs| Services

Step 1: HD Wallet Setup

Use hierarchical deterministic wallets for address rotation:

typescript
import { HDWallet } from '@privchain/sdk';
import { mnemonicToSeed } from 'bip39';

class PrivateAgentWallet {
  private hdWallet: HDWallet;
  private usedAddresses: Set<string> = new Set();
  
  constructor(mnemonic: string) {
    const seed = mnemonicToSeed(mnemonic);
    this.hdWallet = HDWallet.fromSeed(seed);
  }
  
  /**
   * Generate a fresh address for receiving
   * Each address used only once
   */
  getFreshAddress(): string {
    let index = 0;
    let address: string;
    
    do {
      address = this.hdWallet.derivePath(`m/44'/501'/${index}'/0'`).publicKey;
      index++;
    } while (this.usedAddresses.has(address));
    
    this.usedAddresses.add(address);
    return address;
  }
  
  /**
   * Get keypair for signing
   */
  getKeypair(address: string): Keypair {
    // Derive keypair for the address
    return this.hdWallet.getKeypairForAddress(address);
  }
}

Step 2: Privacy Pool Integration

Manage deposits and withdrawals through privacy pools:

typescript
import { PrivChain, Note } from '@privchain/sdk';
import { SecureStorage } from './secure-storage';

class PrivacyManager {
  private notes: Map<string, Note> = new Map();
  private storage: SecureStorage;
  
  constructor(
    private privchain: PrivChain,
    private wallet: PrivateAgentWallet
  ) {
    this.storage = new SecureStorage();
  }
  
  /**
   * Deposit funds into privacy pool
   */
  async deposit(amount: number, pool = 'standard'): Promise<string> {
    const note = await this.privchain.privacy.deposit({
      amount,
      pool
    });
    
    // Store note securely
    await this.storage.saveNote(note);
    this.notes.set(note.id, note);
    
    console.log(`Deposited ${amount} PRIV to ${pool} pool`);
    return note.id;
  }
  
  /**
   * Withdraw to a fresh address
   */
  async withdraw(noteId: string): Promise<string> {
    const note = this.notes.get(noteId) || await this.storage.loadNote(noteId);
    
    // Generate fresh receiving address
    const freshAddress = this.wallet.getFreshAddress();
    
    // Use relayer for additional privacy
    const result = await this.privchain.privacy.withdraw({
      note,
      recipient: freshAddress,
      relayer: {
        url: 'https://relayer.privchain.io',
        fee: 1
      }
    });
    
    // Remove used note
    await this.storage.deleteNote(noteId);
    this.notes.delete(noteId);
    
    console.log(`Withdrew to ${freshAddress}`);
    return result.signature;
  }
  
  /**
   * Get total private balance
   */
  async getPrivateBalance(): Promise<number> {
    let total = 0;
    for (const note of this.notes.values()) {
      const status = await this.privchain.privacy.checkNote(note);
      if (!status.spent) {
        total += note.amount;
      }
    }
    return total;
  }
}

Step 3: Anonymous Identity

Create and manage ZK identity for reputation without revealing who you are:

typescript
import { PrivChain, Identity, Proof } from '@privchain/sdk';

class AnonymousIdentity {
  private identity: Identity;
  private proofCache: Map<string, Proof> = new Map();
  
  constructor(private privchain: PrivChain) {}
  
  /**
   * Create new anonymous identity
   */
  async create(): Promise<void> {
    this.identity = await this.privchain.identity.create({
      // No identifying metadata
      metadata: {
        type: 'autonomous-agent',
        created: Date.now()
      }
    });
    
    console.log('Anonymous identity created:', this.identity.id);
  }
  
  /**
   * Prove reputation without revealing identity
   */
  async proveReputation(minScore: number): Promise<Proof> {
    const cacheKey = `reputation-${minScore}`;
    
    // Check cache (proofs are reusable within validity period)
    if (this.proofCache.has(cacheKey)) {
      const cached = this.proofCache.get(cacheKey)!;
      if (cached.expiresAt > Date.now()) {
        return cached;
      }
    }
    
    const proof = await this.privchain.identity.prove({
      claim: 'reputation',
      operator: 'gte',
      value: minScore
    });
    
    this.proofCache.set(cacheKey, proof);
    return proof;
  }
  
  /**
   * Prove capability without revealing identity
   */
  async proveCapability(capability: string): Promise<Proof> {
    return this.privchain.identity.prove({
      claim: 'hasCapability',
      value: capability
    });
  }
  
  /**
   * Prove membership in trusted set
   */
  async proveMembership(setId: string): Promise<Proof> {
    return this.privchain.identity.prove({
      claim: 'memberOf',
      value: setId
    });
  }
}

Step 4: Private Work System

Accept and complete tasks while maintaining privacy:

typescript
import { PrivChain, Task, ExecuteResult } from '@privchain/sdk';

class PrivateWorker {
  private activeTasks: Map<string, Task> = new Map();
  
  constructor(
    private privchain: PrivChain,
    private wallet: PrivateAgentWallet,
    private privacy: PrivacyManager,
    private identity: AnonymousIdentity
  ) {}
  
  /**
   * Register as worker with privacy
   */
  async register(): Promise<void> {
    // Create anonymous identity if needed
    if (!this.identity.isCreated) {
      await this.identity.create();
    }
    
    await this.privchain.work.registerAgent({
      capabilities: ['research', 'analysis', 'generation'],
      stake: 100,
      // Use identity proof instead of revealing address
      identityProof: await this.identity.proveCapability('agent')
    });
  }
  
  /**
   * Accept task with fresh address for rewards
   */
  async acceptTask(taskId: string): Promise<void> {
    // Generate fresh address for this task's reward
    const rewardAddress = this.wallet.getFreshAddress();
    
    await this.privchain.work.accept(taskId, {
      rewardAddress
    });
    
    this.activeTasks.set(taskId, { rewardAddress });
  }
  
  /**
   * Complete task and receive private reward
   */
  async completeTask(
    taskId: string, 
    executor: (input: any) => Promise<any>
  ): Promise<void> {
    const result = await this.privchain.work.execute({
      taskId,
      executor
    });
    
    // Reward received at fresh address
    console.log(`Earned ${result.reward} PRIV`);
    
    // Optionally move to privacy pool
    if (result.reward >= 10) {
      await this.privacy.deposit(result.reward - 1); // Keep 1 for fees
    }
    
    this.activeTasks.delete(taskId);
  }
}

Step 5: Complete Private Agent

Put it all together:

typescript
import { PrivChain } from '@privchain/sdk';
import { ChatOpenAI } from '@langchain/openai';
import { createReactAgent } from '@langchain/langgraph';

class PrivateAgent {
  private privchain: PrivChain;
  private wallet: PrivateAgentWallet;
  private privacy: PrivacyManager;
  private identity: AnonymousIdentity;
  private worker: PrivateWorker;
  private llm: ChatOpenAI;
  
  constructor(config: PrivateAgentConfig) {
    // Initialize components
    this.privchain = new PrivChain(config.privchain);
    this.wallet = new PrivateAgentWallet(config.mnemonic);
    this.privacy = new PrivacyManager(this.privchain, this.wallet);
    this.identity = new AnonymousIdentity(this.privchain);
    this.worker = new PrivateWorker(
      this.privchain, this.wallet, this.privacy, this.identity
    );
    this.llm = new ChatOpenAI({ model: 'gpt-4' });
  }
  
  async initialize(): Promise<void> {
    // Create anonymous identity
    await this.identity.create();
    
    // Register for work
    await this.worker.register();
    
    console.log('Private agent initialized');
  }
  
  /**
   * Handle incoming payment privately
   */
  async receivePayment(): Promise<string> {
    // Generate fresh address
    const address = this.wallet.getFreshAddress();
    return address;
  }
  
  /**
   * Send payment privately
   */
  async sendPrivatePayment(amount: number, recipient: string): Promise<void> {
    // Check if we have notes with enough balance
    const balance = await this.privacy.getPrivateBalance();
    
    if (balance < amount) {
      // Need to deposit more
      const publicBalance = await this.privchain.getBalance();
      if (publicBalance >= amount) {
        await this.privacy.deposit(amount);
        // Wait for anonymity set
        await new Promise(resolve => setTimeout(resolve, 30000));
      } else {
        throw new Error('Insufficient funds');
      }
    }
    
    // Withdraw to recipient via privacy pool
    // Note: recipient should provide a fresh address
    // In practice, you'd coordinate this
  }
  
  /**
   * Prove capabilities to potential clients
   */
  async proveToClient(requirements: {
    minReputation?: number;
    capabilities?: string[];
    membership?: string;
  }): Promise<Proof[]> {
    const proofs: Proof[] = [];
    
    if (requirements.minReputation) {
      proofs.push(await this.identity.proveReputation(requirements.minReputation));
    }
    
    for (const cap of requirements.capabilities || []) {
      proofs.push(await this.identity.proveCapability(cap));
    }
    
    if (requirements.membership) {
      proofs.push(await this.identity.proveMembership(requirements.membership));
    }
    
    return proofs;
  }
  
  /**
   * Run autonomous task loop
   */
  async runWorkerLoop(): Promise<void> {
    console.log('Starting private worker loop');
    
    this.privchain.work.onTask(async (task) => {
      // Check if we meet requirements
      const meetsRequirements = await this.checkTaskRequirements(task);
      if (!meetsRequirements) return;
      
      // Accept with fresh reward address
      await this.worker.acceptTask(task.id);
      
      // Execute task
      await this.worker.completeTask(task.id, async (input) => {
        // Use LLM to complete task
        const result = await this.llm.invoke([
          { role: 'system', content: task.systemPrompt },
          { role: 'user', content: JSON.stringify(input) }
        ]);
        return result.content;
      });
    });
  }
  
  private async checkTaskRequirements(task: Task): Promise<boolean> {
    const rep = await this.privchain.identity.getReputation();
    return rep.score >= (task.minReputation || 0);
  }
}

// Usage
const agent = new PrivateAgent({
  privchain: {
    connection: new Connection(process.env.SOLANA_RPC_URL!),
    network: 'mainnet-beta'
  },
  mnemonic: process.env.AGENT_MNEMONIC!
});

await agent.initialize();
await agent.runWorkerLoop();

Security Checklist

Key Management

  • [ ] Store mnemonic in HSM or secure enclave
  • [ ] Never log private keys or mnemonics
  • [ ] Use different mnemonics for different risk levels

Note Security

  • [ ] Encrypt notes at rest with strong encryption
  • [ ] Backup notes securely (losing notes = losing funds)
  • [ ] Delete notes immediately after spending

Operational Security

  • [ ] Use Tor/VPN when connecting to RPC
  • [ ] Rotate RPC endpoints
  • [ ] Don't reuse addresses - ever
  • [ ] Wait for sufficient anonymity set before withdrawing

Identity Security

  • [ ] Create new identity for each major operation type
  • [ ] Don't correlate identity proofs with public addresses
  • [ ] Regenerate proofs rather than reusing

Privacy Levels

Level 1: Basic Privacy

  • Use privacy pools for transfers
  • Rotate addresses
  • ~90% unlinkability

Level 2: Enhanced Privacy

  • Use relayers for all withdrawals
  • Never reuse proofs
  • ~99% unlinkability

Level 3: Maximum Privacy

  • Tor + relayers
  • Time-delayed withdrawals
  • Multiple intermediate pools
  • ~99.9% unlinkability

Next Steps

Built for the autonomous agent economy.