# BZZZ SDK Documentation **Version 2.0 - Phase 2B Edition** Software Development Kit for integrating with and extending BZZZ's semantic context publishing platform. ## Table of Contents 1. [SDK Overview](#sdk-overview) 2. [Installation](#installation) 3. [Core SDK](#core-sdk) 4. [Crypto SDK](#crypto-sdk) 5. [DHT SDK](#dht-sdk) 6. [Decision SDK](#decision-sdk) 7. [Election SDK](#election-sdk) 8. [Configuration SDK](#configuration-sdk) 9. [Examples](#examples) 10. [Language Bindings](#language-bindings) ## SDK Overview The BZZZ SDK provides programmatic access to all BZZZ functionality, enabling developers to: - Integrate BZZZ into existing applications - Build custom agents and decision publishers - Implement custom crypto providers - Create specialized storage backends - Develop monitoring and analytics tools ### Architecture ``` ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ Client App │ │ BZZZ SDK │ │ BZZZ Node │ │ │────│ │────│ │ │ - Custom Logic │ │ - Go Packages │ │ - Core Services │ │ - UI/CLI │ │ - HTTP Client │ │ - P2P Network │ │ - Integrations │ │ - Type Safety │ │ - DHT Storage │ └─────────────────┘ └─────────────────┘ └─────────────────┘ ``` ### Key Features - **Type-Safe**: Full Go type safety with comprehensive error handling - **Async Operations**: Non-blocking operations with context cancellation - **Encryption Support**: Built-in Age encryption with role-based access - **DHT Integration**: Direct access to distributed storage - **Real-time Events**: WebSocket-based event streaming - **Configuration Management**: Programmatic configuration updates **Cross-References**: - Core implementation: `pkg/` packages - HTTP API: [API_REFERENCE.md](API_REFERENCE.md) - Examples: `examples/sdk/` directory ## Installation ### Go Module Add BZZZ SDK to your Go project: ```bash go mod init your-project go get github.com/anthonyrawlins/bzzz/sdk ``` ### Import SDK ```go import ( "github.com/anthonyrawlins/bzzz/sdk/bzzz" "github.com/anthonyrawlins/bzzz/sdk/crypto" "github.com/anthonyrawlins/bzzz/sdk/dht" "github.com/anthonyrawlins/bzzz/sdk/decisions" "github.com/anthonyrawlins/bzzz/sdk/elections" ) ``` ### SDK Client Create the main SDK client: ```go package main import ( "context" "log" "github.com/anthonyrawlins/bzzz/sdk/bzzz" ) func main() { // Create SDK client client, err := bzzz.NewClient(bzzz.Config{ Endpoint: "http://localhost:8080", Role: "backend_developer", Timeout: 30 * time.Second, }) if err != nil { log.Fatal(err) } defer client.Close() // Use the client status, err := client.GetStatus(context.Background()) if err != nil { log.Fatal(err) } log.Printf("Connected to BZZZ node: %s", status.NodeID) } ``` ## Core SDK The core SDK provides basic connectivity and agent management. ### Client Configuration ```go // SDK configuration type Config struct { Endpoint string `yaml:"endpoint"` // BZZZ node endpoint Role string `yaml:"role"` // Client role Timeout time.Duration `yaml:"timeout"` // Request timeout RetryCount int `yaml:"retry_count"` // Retry attempts RateLimit int `yaml:"rate_limit"` // Requests per second // Authentication (optional) AuthToken string `yaml:"auth_token,omitempty"` // TLS Configuration (optional) TLSConfig *tls.Config `yaml:"-"` // Crypto configuration AgeKeys *AgeKeyPair `yaml:"age_keys,omitempty"` } // Create client with configuration client, err := bzzz.NewClient(Config{ Endpoint: "http://localhost:8080", Role: "backend_developer", Timeout: 30 * time.Second, RetryCount: 3, RateLimit: 10, }) ``` ### Agent Operations ```go // Get agent status status, err := client.GetStatus(ctx) if err != nil { return fmt.Errorf("failed to get status: %w", err) } fmt.Printf("Agent: %s\n", status.AgentID) fmt.Printf("Role: %s\n", status.Role) fmt.Printf("Authority: %s\n", status.AuthorityLevel) fmt.Printf("Can decrypt: %v\n", status.CanDecrypt) // Get connected peers peers, err := client.GetPeers(ctx) if err != nil { return fmt.Errorf("failed to get peers: %w", err) } for _, peer := range peers.ConnectedPeers { fmt.Printf("Peer: %s (%s)\n", peer.AgentID, peer.Role) } // Update agent configuration err = client.UpdateRole(ctx, bzzz.RoleUpdate{ Role: "senior_software_architect", Specialization: "architecture", Models: []string{"gpt-4", "claude-3"}, }) if err != nil { return fmt.Errorf("failed to update role: %w", err) } ``` ### Event Streaming ```go // Subscribe to real-time events events, err := client.SubscribeEvents(ctx) if err != nil { return fmt.Errorf("failed to subscribe to events: %w", err) } defer events.Close() for { select { case event := <-events.Events(): switch event.Type { case "decision_published": fmt.Printf("New decision: %s\n", event.Data["address"]) case "admin_changed": fmt.Printf("Admin changed: %s -> %s\n", event.Data["old_admin"], event.Data["new_admin"]) case "peer_connected": fmt.Printf("Peer connected: %s\n", event.Data["agent_id"]) } case err := <-events.Errors(): log.Printf("Event stream error: %v", err) case <-ctx.Done(): return ctx.Err() } } ``` **Cross-Reference**: Core client implementation in `sdk/bzzz/client.go` ## Crypto SDK The crypto SDK provides Age encryption functionality with role-based access control. ### Basic Encryption ```go import "github.com/anthonyrawlins/bzzz/sdk/crypto" // Create crypto client cryptoClient := crypto.NewClient(client) // Generate new Age key pair keyPair, err := cryptoClient.GenerateKeyPair(ctx) if err != nil { return fmt.Errorf("failed to generate keys: %w", err) } fmt.Printf("Public Key: %s\n", keyPair.PublicKey) // Store keyPair.PrivateKey securely // Encrypt content for specific role content := []byte("Sensitive decision content") encrypted, err := cryptoClient.EncryptForRole(ctx, content, "backend_developer") if err != nil { return fmt.Errorf("encryption failed: %w", err) } // Decrypt content (if you have permission) decrypted, err := cryptoClient.DecryptWithRole(ctx, encrypted) if err != nil { return fmt.Errorf("decryption failed: %w", err) } fmt.Printf("Decrypted: %s\n", string(decrypted)) ``` ### Multi-Role Encryption ```go // Encrypt for multiple roles roles := []string{"backend_developer", "senior_software_architect", "admin"} encrypted, err := cryptoClient.EncryptForMultipleRoles(ctx, content, roles) if err != nil { return fmt.Errorf("multi-role encryption failed: %w", err) } // Check if current role can decrypt content from another role canDecrypt, err := cryptoClient.CanDecryptFrom(ctx, "admin") if err != nil { return fmt.Errorf("permission check failed: %w", err) } if !canDecrypt { return fmt.Errorf("insufficient permissions to decrypt admin content") } ``` ### Key Management ```go // Validate existing keys valid, err := cryptoClient.ValidateKeys(ctx, crypto.KeyValidation{ PublicKey: "age1...", PrivateKey: "AGE-SECRET-KEY-1...", TestEncryption: true, }) if err != nil { return fmt.Errorf("key validation failed: %w", err) } if !valid.Valid { return fmt.Errorf("invalid keys: %s", valid.Error) } // Get current role permissions permissions, err := cryptoClient.GetPermissions(ctx) if err != nil { return fmt.Errorf("failed to get permissions: %w", err) } fmt.Printf("Current role: %s\n", permissions.CurrentRole) fmt.Printf("Can decrypt: %v\n", permissions.CanDecrypt) fmt.Printf("Authority level: %s\n", permissions.AuthorityLevel) ``` ### Custom Crypto Providers ```go // Implement custom crypto provider type CustomCrypto struct { // Custom implementation fields } func (cc *CustomCrypto) Encrypt(content []byte, recipients []string) ([]byte, error) { // Custom encryption logic return nil, nil } func (cc *CustomCrypto) Decrypt(encrypted []byte, key string) ([]byte, error) { // Custom decryption logic return nil, nil } // Register custom provider cryptoClient.RegisterProvider("custom", &CustomCrypto{}) // Use custom provider encrypted, err := cryptoClient.EncryptWithProvider(ctx, "custom", content, recipients) ``` **Cross-Reference**: Crypto implementation in `pkg/crypto/` and `sdk/crypto/` ## DHT SDK The DHT SDK provides direct access to distributed hash table storage operations. ### Basic DHT Operations ```go import "github.com/anthonyrawlins/bzzz/sdk/dht" // Create DHT client dhtClient := dht.NewClient(client) // Store content with automatic encryption err = dhtClient.StoreContent(ctx, dht.StoreRequest{ Address: "my_agent/backend_developer/project/task/12345", Content: []byte("Task completion data"), ContentType: "decision", Metadata: map[string]interface{}{ "language": "go", "files_changed": 3, }, }) if err != nil { return fmt.Errorf("failed to store content: %w", err) } // Retrieve and decrypt content content, metadata, err := dhtClient.RetrieveContent(ctx, "my_agent/backend_developer/project/task/12345") if err != nil { return fmt.Errorf("failed to retrieve content: %w", err) } fmt.Printf("Content: %s\n", string(content)) fmt.Printf("Creator: %s\n", metadata.CreatorRole) fmt.Printf("Size: %d bytes\n", metadata.Size) ``` ### Search and Discovery ```go // Search for content by criteria results, err := dhtClient.Search(ctx, dht.SearchRequest{ Role: "backend_developer", Project: "user_auth", ContentType: "decision", Since: time.Now().Add(-24 * time.Hour), Limit: 10, }) if err != nil { return fmt.Errorf("search failed: %w", err) } for _, result := range results.Items { fmt.Printf("Found: %s (%s)\n", result.Address, result.ContentType) } // Discover peers with specific content peers, err := dhtClient.DiscoverPeers(ctx, "agent/role/project/task/node") if err != nil { return fmt.Errorf("peer discovery failed: %w", err) } fmt.Printf("Content available on %d peers\n", len(peers.Peers)) ``` ### DHT Metrics ```go // Get DHT performance metrics metrics, err := dhtClient.GetMetrics(ctx) if err != nil { return fmt.Errorf("failed to get metrics: %w", err) } fmt.Printf("Stored items: %d\n", metrics.StoredItems) fmt.Printf("Cache hit rate: %.2f%%\n", metrics.CacheHitRate*100) fmt.Printf("Average store time: %v\n", metrics.AverageStoreTime) fmt.Printf("Connected peers: %d\n", metrics.ConnectedPeers) ``` ### Raw DHT Access (Admin Only) ```go // Admin-only: Direct DHT operations if client.IsAdmin() { // Store raw encrypted content err = dhtClient.StoreRaw(ctx, dht.RawStoreRequest{ Address: "admin/admin/system/backup/12345", Content: encryptedBackupData, Metadata: backupMetadata, }) // Retrieve raw encrypted content rawContent, err := dhtClient.RetrieveRaw(ctx, "admin/admin/system/backup/12345") if err != nil { return fmt.Errorf("failed to retrieve raw content: %w", err) } } ``` **Cross-Reference**: DHT implementation in `pkg/dht/` and `sdk/dht/` ## Decision SDK The decision SDK simplifies publishing and querying decision content. ### Publishing Decisions ```go import "github.com/anthonyrawlins/bzzz/sdk/decisions" // Create decision client decisionClient := decisions.NewClient(client) // Publish architectural decision err = decisionClient.PublishArchitectural(ctx, decisions.ArchitecturalDecision{ Task: "migrate_to_microservices", Decision: "Split monolith into 5 domain-based microservices", Rationale: "Improve scalability and team autonomy", Alternatives: []string{ "Keep monolith with better modularization", "Partial split into 2 services", }, Implications: []string{ "Increased operational complexity", "Better fault isolation", "Need for service mesh", }, NextSteps: []string{ "Define service boundaries", "Plan data migration strategy", }, }) if err != nil { return fmt.Errorf("failed to publish decision: %w", err) } // Publish code decision with test results err = decisionClient.PublishCode(ctx, decisions.CodeDecision{ Task: "implement_user_auth", Decision: "Implemented JWT authentication with refresh tokens", FilesModified: []string{ "internal/auth/jwt.go", "internal/middleware/auth.go", }, LinesChanged: 245, TestResults: &decisions.TestResults{ Passed: 18, Failed: 1, Skipped: 2, Coverage: 87.5, FailedTests: []string{"TestJWT_ExpiredToken"}, }, Dependencies: []string{ "github.com/golang-jwt/jwt/v5", "golang.org/x/crypto/bcrypt", }, }) if err != nil { return fmt.Errorf("failed to publish code decision: %w", err) } // Publish system status err = decisionClient.PublishSystemStatus(ctx, decisions.SystemStatus{ Status: "All systems operational", Metrics: map[string]interface{}{ "uptime_hours": 24, "active_peers": 4, "decisions_count": 25, }, HealthChecks: map[string]bool{ "database": true, "dht": true, "crypto": true, }, }) ``` ### Querying Decisions ```go // Query recent decisions recent, err := decisionClient.QueryRecent(ctx, decisions.QueryRequest{ Role: "backend_developer", Project: "user_auth", Since: time.Now().Add(-7 * 24 * time.Hour), // Last week Limit: 20, }) if err != nil { return fmt.Errorf("failed to query decisions: %w", err) } for _, decision := range recent.Decisions { fmt.Printf("Decision: %s\n", decision.Address) fmt.Printf(" Task: %s\n", decision.Task) fmt.Printf(" Success: %t\n", decision.Success) fmt.Printf(" Created: %s\n", decision.Timestamp.Format(time.RFC3339)) } // Get specific decision content content, err := decisionClient.GetContent(ctx, "agent/role/project/task/node") if err != nil { return fmt.Errorf("failed to get decision content: %w", err) } fmt.Printf("Decision: %s\n", content.Decision) if content.TestResults != nil { fmt.Printf("Tests: %d passed, %d failed\n", content.TestResults.Passed, content.TestResults.Failed) } ``` ### Custom Decision Types ```go // Define custom decision type type DataScienceDecision struct { decisions.TaskDecision ModelName string `json:"model_name"` TrainingAccuracy float64 `json:"training_accuracy"` DatasetSize int `json:"dataset_size"` HyperParams map[string]float64 `json:"hyperparameters"` } // Publish custom decision customDecision := &DataScienceDecision{ TaskDecision: decisions.TaskDecision{ Task: "train_sentiment_model", Decision: "Trained BERT model for sentiment analysis", Success: true, }, ModelName: "bert-base-sentiment", TrainingAccuracy: 0.94, DatasetSize: 50000, HyperParams: map[string]float64{ "learning_rate": 0.001, "batch_size": 32, "epochs": 10, }, } err = decisionClient.PublishCustom(ctx, "data_science", customDecision) if err != nil { return fmt.Errorf("failed to publish custom decision: %w", err) } ``` ### Decision Streaming ```go // Stream decisions in real-time stream, err := decisionClient.StreamDecisions(ctx, decisions.StreamRequest{ Role: "backend_developer", ContentType: "decision", }) if err != nil { return fmt.Errorf("failed to start stream: %w", err) } defer stream.Close() for { select { case decision := <-stream.Decisions(): fmt.Printf("New decision: %s\n", decision.Address) processDecision(decision) case err := <-stream.Errors(): log.Printf("Stream error: %v", err) case <-ctx.Done(): return ctx.Err() } } ``` **Cross-Reference**: Decision implementation in `pkg/ucxl/` and `sdk/decisions/` ## Election SDK The election SDK provides access to admin election and consensus operations. ### Election Management ```go import "github.com/anthonyrawlins/bzzz/sdk/elections" // Create election client electionClient := elections.NewClient(client) // Get current election status status, err := electionClient.GetStatus(ctx) if err != nil { return fmt.Errorf("failed to get election status: %w", err) } fmt.Printf("Current admin: %s\n", status.CurrentAdmin) fmt.Printf("Election active: %t\n", status.IsElectionActive) fmt.Printf("Last heartbeat: %s\n", status.LastHeartbeat.Format(time.RFC3339)) // Monitor election events events, err := electionClient.MonitorElections(ctx) if err != nil { return fmt.Errorf("failed to monitor elections: %w", err) } defer events.Close() for { select { case event := <-events.Events(): switch event.Type { case elections.ElectionStarted: fmt.Printf("Election started: %s\n", event.ElectionID) case elections.CandidateProposed: fmt.Printf("New candidate: %s (score: %.1f)\n", event.Candidate.NodeID, event.Candidate.Score) case elections.ElectionCompleted: fmt.Printf("Election completed. Winner: %s\n", event.Winner) case elections.AdminHeartbeat: fmt.Printf("Admin heartbeat from: %s\n", event.AdminID) } case <-ctx.Done(): return ctx.Err() } } ``` ### Admin Operations ```go // Admin-only operations if client.IsAdmin() { // Trigger manual election election, err := electionClient.TriggerElection(ctx, elections.TriggerRequest{ Reason: "manual_trigger", Force: false, }) if err != nil { return fmt.Errorf("failed to trigger election: %w", err) } fmt.Printf("Election %s started with %d candidates\n", election.ElectionID, len(election.Candidates)) // Get admin key shares information shares, err := electionClient.GetKeyShares(ctx) if err != nil { return fmt.Errorf("failed to get key shares: %w", err) } fmt.Printf("Key shares: %d/%d distributed\n", len(shares.DistributedShares), shares.TotalShares) fmt.Printf("Reconstruction possible: %t\n", shares.ReconstructionPossible) } ``` ### Consensus Operations ```go // Participate in consensus (for eligible nodes) if status.CanParticipate { // Propose candidacy err = electionClient.ProposeCandidate(ctx, elections.CandidateProposal{ Capabilities: []string{"high_uptime", "master_authority"}, Resources: elections.NodeResources{ CPU: 0.2, // 20% CPU usage Memory: 0.15, // 15% memory usage Disk: 0.45, // 45% disk usage }, }) if err != nil { return fmt.Errorf("failed to propose candidacy: %w", err) } // Vote in election (automatic based on scoring) vote, err := electionClient.CastVote(ctx, elections.VoteRequest{ ElectionID: status.CurrentElection, CandidateID: "QmBestCandidate", VoteValue: true, }) if err != nil { return fmt.Errorf("failed to cast vote: %w", err) } fmt.Printf("Vote cast: %t\n", vote.Recorded) } ``` **Cross-Reference**: Election implementation in `pkg/election/` and `sdk/elections/` ## Configuration SDK The configuration SDK provides programmatic access to BZZZ configuration management. ### Configuration Management ```go import "github.com/anthonyrawlins/bzzz/sdk/config" // Create config client configClient := config.NewClient(client) // Get current configuration cfg, err := configClient.GetConfig(ctx) if err != nil { return fmt.Errorf("failed to get config: %w", err) } fmt.Printf("Node ID: %s\n", cfg.NodeID) fmt.Printf("Role: %s\n", cfg.Agent.Role) fmt.Printf("Authority: %s\n", cfg.Agent.AuthorityLevel) // Update agent configuration err = configClient.UpdateAgent(ctx, config.AgentUpdate{ Role: "senior_software_architect", Specialization: "microservices_architecture", Models: []string{"gpt-4", "claude-3-opus"}, MaxTasks: 10, }) if err != nil { return fmt.Errorf("failed to update agent config: %w", err) } // Update security configuration (admin only) if client.IsAdmin() { err = configClient.UpdateSecurity(ctx, config.SecurityUpdate{ AdminKeyShares: config.ShamirConfig{ Threshold: 3, TotalShares: 5, }, ElectionTimeout: 30 * time.Second, HeartbeatInterval: 5 * time.Second, }) if err != nil { return fmt.Errorf("failed to update security config: %w", err) } } ``` ### Role Management ```go // Get available roles roles, err := configClient.GetRoles(ctx) if err != nil { return fmt.Errorf("failed to get roles: %w", err) } for name, role := range roles.Roles { fmt.Printf("Role: %s\n", name) fmt.Printf(" Authority: %s\n", role.AuthorityLevel) fmt.Printf(" Can decrypt: %v\n", role.CanDecrypt) fmt.Printf(" Model: %s\n", role.Model) } // Create custom role err = configClient.CreateRole(ctx, config.RoleDefinition{ Name: "data_scientist", AuthorityLevel: "decision", CanDecrypt: []string{"data_scientist", "backend_developer", "observer"}, Model: "ollama/llama3.1", DecisionScope: []string{"data", "analytics", "ml_models"}, SpecialFunctions: []string{"model_training", "data_analysis"}, }) if err != nil { return fmt.Errorf("failed to create role: %w", err) } // Generate keys for role keys, err := configClient.GenerateRoleKeys(ctx, "data_scientist") if err != nil { return fmt.Errorf("failed to generate role keys: %w", err) } fmt.Printf("Generated keys for data_scientist role\n") fmt.Printf("Public key: %s\n", keys.PublicKey) // Store keys.PrivateKey securely ``` ### Configuration Validation ```go // Validate configuration validation, err := configClient.ValidateConfig(ctx, cfg) if err != nil { return fmt.Errorf("failed to validate config: %w", err) } if !validation.Valid { fmt.Printf("Configuration validation failed:\n") for _, error := range validation.Errors { fmt.Printf(" - %s: %s\n", error.Field, error.Message) } return fmt.Errorf("invalid configuration") } // Get configuration schema schema, err := configClient.GetSchema(ctx) if err != nil { return fmt.Errorf("failed to get schema: %w", err) } // Use schema for validation in external tools fmt.Printf("Schema version: %s\n", schema.Version) fmt.Printf("Required fields: %v\n", schema.RequiredFields) ``` **Cross-Reference**: Configuration implementation in `pkg/config/` and `sdk/config/` ## Examples ### Complete Agent Implementation ```go package main import ( "context" "fmt" "log" "os" "os/signal" "syscall" "time" "github.com/anthonyrawlins/bzzz/sdk/bzzz" "github.com/anthonyrawlins/bzzz/sdk/decisions" "github.com/anthonyrawlins/bzzz/sdk/crypto" ) type CustomAgent struct { client *bzzz.Client decisions *decisions.Client crypto *crypto.Client shutdown chan os.Signal } func NewCustomAgent(endpoint, role string) (*CustomAgent, error) { // Create BZZZ client client, err := bzzz.NewClient(bzzz.Config{ Endpoint: endpoint, Role: role, Timeout: 30 * time.Second, }) if err != nil { return nil, fmt.Errorf("failed to create client: %w", err) } // Create specialized clients decisionsClient := decisions.NewClient(client) cryptoClient := crypto.NewClient(client) agent := &CustomAgent{ client: client, decisions: decisionsClient, crypto: cryptoClient, shutdown: make(chan os.Signal, 1), } signal.Notify(agent.shutdown, os.Interrupt, syscall.SIGTERM) return agent, nil } func (a *CustomAgent) Run(ctx context.Context) error { log.Printf("Starting custom BZZZ agent...") // Get initial status status, err := a.client.GetStatus(ctx) if err != nil { return fmt.Errorf("failed to get status: %w", err) } log.Printf("Connected as %s (%s)", status.AgentID, status.Role) // Start event monitoring events, err := a.client.SubscribeEvents(ctx) if err != nil { return fmt.Errorf("failed to subscribe to events: %w", err) } defer events.Close() // Start decision monitoring decisions, err := a.decisions.StreamDecisions(ctx, decisions.StreamRequest{ Role: status.Role, }) if err != nil { return fmt.Errorf("failed to stream decisions: %w", err) } defer decisions.Close() // Start task processing go a.processTask(ctx) // Main event loop for { select { case event := <-events.Events(): a.handleEvent(event) case decision := <-decisions.Decisions(): a.handleDecision(decision) case <-a.shutdown: log.Printf("Shutting down agent...") return nil case <-ctx.Done(): return ctx.Err() } } } func (a *CustomAgent) handleEvent(event bzzz.Event) { switch event.Type { case "admin_changed": log.Printf("Admin changed: %s -> %s", event.Data["old_admin"], event.Data["new_admin"]) case "peer_connected": log.Printf("Peer connected: %s (%s)", event.Data["agent_id"], event.Data["role"]) default: log.Printf("Received event: %s", event.Type) } } func (a *CustomAgent) handleDecision(decision decisions.TaskDecision) { log.Printf("New decision: %s - %s", decision.Task, decision.Decision) // Process decision based on your logic if decision.Success && len(decision.FilesModified) > 0 { log.Printf("Successful task with %d files modified", len(decision.FilesModified)) // Trigger related tasks or analysis } } func (a *CustomAgent) processTask(ctx context.Context) { // Simulate task processing ticker := time.NewTicker(60 * time.Second) defer ticker.Stop() taskCounter := 0 for { select { case <-ticker.C: taskCounter++ // Simulate completing a task err := a.decisions.PublishCode(ctx, decisions.CodeDecision{ Task: fmt.Sprintf("automated_task_%d", taskCounter), Decision: "Completed automated code analysis task", FilesModified: []string{ fmt.Sprintf("analysis/task_%d.go", taskCounter), }, LinesChanged: 50 + taskCounter*10, TestResults: &decisions.TestResults{ Passed: 5, Failed: 0, Coverage: 85.0 + float64(taskCounter), }, }) if err != nil { log.Printf("Failed to publish task completion: %v", err) } else { log.Printf("Published completion for task %d", taskCounter) } case <-ctx.Done(): return } } } func main() { agent, err := NewCustomAgent("http://localhost:8080", "backend_developer") if err != nil { log.Fatal(err) } defer agent.client.Close() ctx := context.Background() if err := agent.Run(ctx); err != nil { log.Fatal(err) } } ``` ### Data Analysis Tool ```go package main import ( "context" "fmt" "time" "github.com/anthonyrawlins/bzzz/sdk/bzzz" "github.com/anthonyrawlins/bzzz/sdk/decisions" ) func analyzeDecisions() error { // Connect to BZZZ client, err := bzzz.NewClient(bzzz.Config{ Endpoint: "http://localhost:8080", Role: "observer", // Read-only access }) if err != nil { return err } defer client.Close() decisionsClient := decisions.NewClient(client) // Query last 30 days of decisions since := time.Now().Add(-30 * 24 * time.Hour) recent, err := decisionsClient.QueryRecent(context.Background(), decisions.QueryRequest{ Since: since, Limit: 1000, }) if err != nil { return err } // Analyze decision patterns roleStats := make(map[string]int) projectStats := make(map[string]int) successRate := 0 totalDecisions := len(recent.Decisions) for _, decision := range recent.Decisions { // Get full decision content content, err := decisionsClient.GetContent(context.Background(), decision.Address) if err != nil { continue // Skip if we can't decrypt } roleStats[content.Role]++ projectStats[content.Project]++ if content.Success { successRate++ } } // Print analysis fmt.Printf("Decision Analysis (Last 30 Days)\n") fmt.Printf("================================\n") fmt.Printf("Total decisions: %d\n", totalDecisions) fmt.Printf("Success rate: %.1f%%\n", float64(successRate)/float64(totalDecisions)*100) fmt.Printf("\nDecisions by Role:\n") for role, count := range roleStats { fmt.Printf(" %s: %d\n", role, count) } fmt.Printf("\nDecisions by Project:\n") for project, count := range projectStats { fmt.Printf(" %s: %d\n", project, count) } return nil } ``` ### Monitoring Dashboard ```go package main import ( "context" "encoding/json" "fmt" "html/template" "net/http" "time" "github.com/anthonyrawlins/bzzz/sdk/bzzz" "github.com/anthonyrawlins/bzzz/sdk/dht" "github.com/anthonyrawlins/bzzz/sdk/elections" ) type Dashboard struct { client *bzzz.Client dht *dht.Client elections *elections.Client } func NewDashboard(bzzzEndpoint string) (*Dashboard, error) { client, err := bzzz.NewClient(bzzz.Config{ Endpoint: bzzzEndpoint, Role: "observer", }) if err != nil { return nil, err } return &Dashboard{ client: client, dht: dht.NewClient(client), elections: elections.NewClient(client), }, nil } func (d *Dashboard) GetMetrics(ctx context.Context) (map[string]interface{}, error) { // Get node status status, err := d.client.GetStatus(ctx) if err != nil { return nil, err } // Get DHT metrics dhtMetrics, err := d.dht.GetMetrics(ctx) if err != nil { return nil, err } // Get election status electionStatus, err := d.elections.GetStatus(ctx) if err != nil { return nil, err } // Get peers peers, err := d.client.GetPeers(ctx) if err != nil { return nil, err } return map[string]interface{}{ "node": status, "dht": dhtMetrics, "elections": electionStatus, "peers": peers, "timestamp": time.Now(), }, nil } func (d *Dashboard) ServeHTTP(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case "/": d.serveDashboard(w, r) case "/api/metrics": d.serveMetrics(w, r) case "/api/events": d.serveEventStream(w, r) default: http.NotFound(w, r) } } func (d *Dashboard) serveDashboard(w http.ResponseWriter, r *http.Request) { tmpl := template.Must(template.New("dashboard").Parse(dashboardHTML)) tmpl.Execute(w, nil) } func (d *Dashboard) serveMetrics(w http.ResponseWriter, r *http.Request) { metrics, err := d.GetMetrics(r.Context()) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(metrics) } func (d *Dashboard) serveEventStream(w http.ResponseWriter, r *http.Request) { // Set up SSE headers w.Header().Set("Content-Type", "text/event-stream") w.Header().Set("Cache-Control", "no-cache") w.Header().Set("Connection", "keep-alive") // Subscribe to events events, err := d.client.SubscribeEvents(r.Context()) if err != nil { fmt.Fprintf(w, "data: {\"error\": \"%s\"}\n\n", err.Error()) return } defer events.Close() // Stream events for { select { case event := <-events.Events(): data, _ := json.Marshal(event) fmt.Fprintf(w, "data: %s\n\n", data) if f, ok := w.(http.Flusher); ok { f.Flush() } case <-r.Context().Done(): return } } } const dashboardHTML = ` BZZZ Dashboard

BZZZ Cluster Dashboard

` func main() { dashboard, err := NewDashboard("http://localhost:8080") if err != nil { panic(err) } http.Handle("/", dashboard) fmt.Println("Dashboard available at http://localhost:3000") http.ListenAndServe(":3000", nil) } ``` ## Language Bindings ### Python SDK ```python # Install: pip install bzzz-sdk import asyncio from bzzz_sdk import BzzzClient, DecisionType async def main(): # Create client client = BzzzClient( endpoint="http://localhost:8080", role="backend_developer" ) # Get status status = await client.get_status() print(f"Connected as {status.agent_id} ({status.role})") # Publish decision await client.decisions.publish_code( task="implement_feature", decision="Implemented new API endpoint", files_modified=["api/handlers.py", "tests/test_api.py"], lines_changed=120 ) # Query decisions decisions = await client.decisions.query_recent( role="backend_developer", limit=10 ) for decision in decisions: print(f"Decision: {decision.task} - {decision.success}") await client.close() if __name__ == "__main__": asyncio.run(main()) ``` ### JavaScript/Node.js SDK ```javascript // Install: npm install bzzz-sdk const { BzzzClient } = require('bzzz-sdk'); async function main() { // Create client const client = new BzzzClient({ endpoint: 'http://localhost:8080', role: 'frontend_developer' }); // Get status const status = await client.getStatus(); console.log(`Connected as ${status.agentId} (${status.role})`); // Subscribe to events const events = client.subscribeEvents(); events.on('decision_published', (decision) => { console.log(`New decision: ${decision.address}`); }); // Publish architectural decision await client.decisions.publishArchitectural({ task: 'redesign_ui', decision: 'Migrating to React with TypeScript', rationale: 'Better type safety and developer experience', alternatives: ['Vue.js', 'Angular', 'Svelte'], nextSteps: ['Set up build pipeline', 'Migrate components'] }); // Query decisions const recentDecisions = await client.decisions.queryRecent({ role: 'frontend_developer', project: 'user_interface', limit: 5 }); recentDecisions.forEach(decision => { console.log(`Decision: ${decision.task} - ${decision.success}`); }); } main().catch(console.error); ``` ### Rust SDK ```rust // Cargo.toml: bzzz-sdk = "2.0" use bzzz_sdk::{BzzzClient, decisions::CodeDecision, crypto::AgeKeyPair}; use tokio; #[tokio::main] async fn main() -> Result<(), Box> { // Create client let client = BzzzClient::new(bzzz_sdk::Config { endpoint: "http://localhost:8080".to_string(), role: "backend_developer".to_string(), timeout: std::time::Duration::from_secs(30), ..Default::default() }).await?; // Get status let status = client.get_status().await?; println!("Connected as {} ({})", status.agent_id, status.role); // Generate Age keys let keys = client.crypto().generate_keys().await?; println!("Generated Age key pair"); // Publish code decision client.decisions().publish_code(CodeDecision { task: "optimize_performance".to_string(), decision: "Implemented async processing with Tokio".to_string(), files_modified: vec![ "src/async_handler.rs".to_string(), "src/main.rs".to_string(), ], lines_changed: 180, test_results: Some(bzzz_sdk::decisions::TestResults { passed: 25, failed: 0, coverage: 92.5, ..Default::default() }), dependencies: vec![ "tokio".to_string(), "futures".to_string(), ], ..Default::default() }).await?; println!("Published code decision"); Ok(()) } ``` --- ## Cross-References - **Core Implementation**: `pkg/` packages in main codebase - **HTTP API**: [API_REFERENCE.md](API_REFERENCE.md) - REST API documentation - **User Guide**: [USER_MANUAL.md](USER_MANUAL.md) - End-user documentation - **Developer Guide**: [DEVELOPER.md](DEVELOPER.md) - Development documentation - **Examples**: `examples/sdk/` directory in repository **BZZZ SDK v2.0** - Complete Software Development Kit for Phase 2B unified architecture with Age encryption and DHT storage.