Logging Agent Activities and Deployment Considerations

Debugging and understanding the behavior of a multi-agent system like Kanbots can be incredibly challenging without proper visibility. In this final chapter, we’ll equip our Kanbots application with robust logging capabilities to capture agent activities, inputs, outputs, and any errors. This provides the essential observability needed to diagnose issues, track performance, and even audit AI agent decisions.

Beyond observability, this chapter also guides you through the critical steps of preparing your Kanbots application for distribution. We’ll explore Tauri’s deployment features, focusing on how to package your application for various operating systems and important considerations like secure API key management and application signing.

By the end of this chapter, you will have a Kanbots application that not only orchestrates AI agents effectively but also provides clear insights into their operations through structured logs. You’ll also understand the process of building and preparing your desktop application for real-world use, making it ready to share or deploy within your team.

Project Overview: Kanbots - AI-Powered Kanban

Kanbots is an open-source, local-first Kanban desktop application designed to streamline development workflows. It allows users to create Kanban cards, each capable of hosting and orchestrating multiple AI agents (such as Claude Code or Codex). These agents operate within isolated Git worktrees, enabling parallel task execution, code generation, review, and other development activities. The application leverages a multi-persona approach, assigning specific roles to agents to manage complex tasks effectively.

Tech Stack Deep Dive for Observability and Deployment

This chapter focuses on two critical aspects: observability and distribution. Our core technologies, Tauri and Rust, provide powerful tools for both.

  • Tauri (v2): The framework for building our cross-platform desktop application. Its robust build system handles packaging and distribution.
  • Rust (Latest Stable): The backend language powering our application logic, including agent orchestration and Git worktree management.
  • tracing crate (v0.1.40): Rust’s idiomatic, structured logging framework. It allows us to emit rich, machine-readable log events.
  • tracing-subscriber (v0.3.18): Provides the configuration layer for tracing, allowing us to direct logs to files, consoles, and filter by level.
  • tracing-appender (v0.2.2): Enables efficient, non-blocking file logging and log rotation, crucial for production applications.
  • Svelte (v5): Our frontend framework, which interacts with the Rust backend via Tauri’s IPC for UI updates and triggering agent actions.

Build Plan: Logging and Distribution Milestones

This chapter breaks down into two main milestones:

  1. Implement Structured Logging: Integrate the tracing ecosystem into the Rust backend to capture detailed, machine-readable logs of agent activities. This will involve adding dependencies, configuring a file appender with rotation, and instrumenting key agent operations with tracing macros.
  2. Prepare for Deployment: Configure Tauri’s build settings to package the application for various operating systems. This includes setting application metadata, handling icons, and understanding the process for generating distributable installers.

Architecture: Integrating Observability

For Kanbots, logging serves several critical purposes: debugging, auditing agent actions, monitoring performance, and managing AI API costs. We will use tracing to emit structured logs that are both human-readable (in development) and machine-parseable (for analysis). These logs will be written to daily rotating files in the application’s data directory.

Log File Flow

The following diagram illustrates how user actions flow through the system, trigger agent logic, and how the tracing system captures events from both agent operations and Git worktree interactions, outputting them for monitoring.

flowchart TD UserAction[User Action] --> SvelteFrontend[Svelte Frontend] SvelteFrontend --> RustBackend[Rust Backend] RustBackend --> AgentLogic[Agent Logic] subgraph AgentExecution["Agent Execution"] AgentLogic --> AI_API[AI API] AI_API -->|Response| AgentLogic AgentLogic --> GitWorktree[Git Worktree] end AgentLogic --> Tracing_System[Tracing System] GitWorktree --> Tracing_System
  • User Action: Initiates a task in the Svelte UI.
  • Svelte Frontend: Communicates with the Rust backend via IPC.
  • Rust Backend: Orchestrates agent logic.
  • Agent Logic: Contains the core intelligence, interacting with external AI APIs and local Git worktrees.
  • Tracing System: Captures events from Agent Logic and Git Worktree operations.
  • Log File: Stores structured log events, typically rotated daily.
  • Debugging/Monitoring: Engineers use these logs to understand system behavior.

Step-by-Step Implementation: Agent Logging with tracing

We’ll integrate the tracing crate into our Rust backend to provide structured, file-based logging.

1. Add tracing Dependencies

Open your Cargo.toml file located in the src-tauri directory. Add the following dependencies under the [dependencies] section. These versions were current as of 2026-05-24.

# src-tauri/Cargo.toml

[dependencies]
# ... other dependencies ...
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "fmt", "ansi", "json"] }
tracing-appender = "0.2.2"
  • tracing = "0.1.40": This is the core tracing crate. It provides the macros (info!, error!, debug!, etc.) that you’ll use to emit log events throughout your Rust code.
  • tracing-subscriber = "0.3.18": This crate provides the “subscriber” implementation, which is responsible for collecting, filtering, and formatting the events emitted by tracing.
    • env-filter: Enables filtering log events based on environment variables (e.g., RUST_LOG=info). This is very useful for controlling verbosity without recompiling.
    • fmt: Provides a formatter for human-readable log output, typically to the console or a file.
    • ansi: Adds ANSI color codes to console output for better readability during development.
    • json: Enables structured JSON output, which is ideal for machine parsing, analysis, and integration with log management systems.
  • tracing-appender = "0.2.2": This crate provides utilities for efficiently writing logs to files. We’ll use it for non-blocking I/O and log file rotation.

2. Configure tracing in main.rs

Next, we’ll set up the tracing subscriber in our main.rs to direct logs to a file and the console. We’ll also make the log file path configurable and ensure logs are written to a platform-appropriate application data directory.

Open src-tauri/src/main.rs and add the following code.

// src-tauri/src/main.rs

use tracing::{info, error, warn, debug, Level};
use tracing_subscriber::{
    fmt::{self, MakeWriter},
    EnvFilter,
    prelude::*,
};
use tracing_appender::rolling::{RollingFileAppender, Rotation};
use std::path::PathBuf;
use std::fs;

// ... other imports for your Tauri commands ...

/// Helper function to get the application's data directory.
/// This function determines a platform-specific directory for persistent application data.
/// For a running Tauri app, `app_handle.path_resolver().app_data_dir()` is more precise.
/// Here, we use a default config to get a base path suitable for early logging setup.
fn get_app_data_dir() -> PathBuf {
    // This will typically resolve to a platform-specific directory, e.g.:
    // Linux:   ~/.config/kanbots
    // macOS:   ~/Library/Application Support/com.kanbots.dev
    // Windows: C:\Users\Username\AppData\Roaming\Kanbots
    tauri::api::path::app_data_dir(&tauri::Config::default())
        .expect("Failed to get application data directory")
}

/// Sets up the global tracing subscriber for structured logging.
/// Logs are directed to both a daily rotating file (JSON format) and the console (compact format).
/// Log levels are controlled by the RUST_LOG environment variable, defaulting to INFO.
fn setup_logging() {
    let app_data_dir = get_app_data_dir();
    let log_dir = app_data_dir.join("logs");

    // Ensure the log directory exists, creating it if necessary.
    fs::create_dir_all(&log_dir).expect("Failed to create log directory");

    // Configure a rolling file appender: new log file daily, named "kanbots.log".
    let file_appender = RollingFileAppender::new(Rotation::DAILY, &log_dir, "kanbots.log");
    // Wrap the file appender in a non-blocking writer to prevent logging from blocking the main thread.
    let (non_blocking_appender, _guard) = tracing_appender::non_blocking(file_appender);

    // Build the tracing subscriber registry.
    tracing_subscriber::registry()
        // Filter logs based on the RUST_LOG environment variable, defaulting to INFO.
        .with(EnvFilter::from_default_env().add_directive(Level::INFO.into()))
        // Layer for file logging: JSON format, no ANSI colors, compact.
        .with(
            fmt::layer()
                .with_writer(non_blocking_appender) // Direct output to the non-blocking file writer
                .json() // Output logs in structured JSON format
                .with_ansi(false) // Disable ANSI colors for file logs
                .compact(), // Use a compact format for fields
        )
        // Layer for console logging: compact format, with ANSI colors.
        .with(
            fmt::layer()
                .with_writer(std::io::stdout) // Direct output to standard console
                .with_ansi(true) // Enable ANSI colors for console logs
                .compact(), // Use a compact format for fields
        )
        // Initialize the global default subscriber.
        .init();

    info!("Kanbots logging initialized to: {:?}", log_dir);
}


fn main() {
    // Initialize logging as the very first step in main.
    setup_logging();

    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![
            // ... your existing command handlers here ...
            // e.g., agent_start_task, git_create_worktree, etc.
            agent_start_task // Ensure this example command is included
        ])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

// Example of how to use tracing in your Tauri commands:
// This command simulates an AI agent starting a task.
#[tauri::command]
async fn agent_start_task(card_id: String, agent_id: String, task_description: String) -> Result<(), String> {
    // Log the initiation of an agent task using info! macro with structured fields.
    info!(
        card_id = %card_id,
        agent_id = %agent_id,
        task = %task_description,
        "AI agent task initiated."
    );

    // Simulate agent work and a potential error condition.
    if task_description.contains("fail") {
        // Log an error if a simulated failure occurs.
        error!(
            card_id = %card_id,
            agent_id = %agent_id,
            error = "Simulated failure condition",
            "Agent task failed unexpectedly."
        );
        return Err("Agent task simulation failed.".into());
    }

    // Log a debug message for intermediate processing steps.
    debug!(
        card_id = %card_id,
        agent_id = %agent_id,
        "Agent is processing task..."
    );

    // ... actual agent logic, git operations, API calls would go here ...
    // Use info!, debug!, warn!, error! macros as appropriate for different stages.

    // Example: When making an API call to an AI service.
    info!(
        card_id = %card_id,
        agent_id = %agent_id,
        api_endpoint = "Claude Code API",
        prompt_length = 500,
        "Calling AI API for code generation."
    );

    // Example: When receiving a response from the AI API.
    debug!(
        card_id = %card_id,
        agent_id = %agent_id,
        response_length = 1200,
        "Received response from AI API."
    );

    // Example: When a file is created or modified in the agent's worktree.
    info!(
        card_id = %card_id,
        agent_id = %agent_id,
        file_path = "src/new_feature.rs",
        "Agent created file in worktree."
    );

    // Log successful completion of the agent task.
    info!(
        card_id = %card_id,
        agent_id = %agent_id,
        "AI agent task completed successfully."
    );
    Ok(())
}

Explanation of the Logging Setup:

  1. get_app_data_dir(): This helper function leverages Tauri’s API (tauri::api::path::app_data_dir) to determine a platform-appropriate directory for storing application data. This is crucial for cross-platform compatibility and ensures logs are stored persistently and in a user-specific location without cluttering the project directory. We use tauri::Config::default() to get a base path.
  2. setup_logging():
    • Log Directory Creation: It first constructs a path for a logs subdirectory within the application’s data directory and ensures it exists.
    • RollingFileAppender: Creates a file appender that automatically rotates log files daily. This prevents a single log file from growing indefinitely, which is a common issue in long-running applications. Files will be named like kanbots.log.YYYY-MM-DD.
    • tracing_appender::non_blocking: Wraps the file appender with a non-blocking writer. This is a critical performance optimization: logging operations are offloaded to a background thread, preventing them from blocking your application’s main execution flow and ensuring a smooth user experience.
    • tracing_subscriber::registry().with(...): This is where the tracing ecosystem is configured.
      • EnvFilter: Allows you to control the verbosity of logs using the RUST_LOG environment variable (e.g., RUST_LOG=debug to see all debug messages). It defaults to INFO level if RUST_LOG is not set.
      • File Layer: Configures a fmt::layer() to write to the non_blocking_appender. Crucially, .json() ensures logs are emitted in a structured JSON format, making them easy to parse by log analysis tools. .with_ansi(false) prevents color codes from polluting the file.
      • Console Layer: Configures a separate fmt::layer() to write to std::io::stdout (your terminal). .with_ansi(true) enables colorized output, which is very helpful for debugging during development.
    • .init(): Activates the configured subscriber globally, making tracing macros available throughout your application.
  3. main(): The setup_logging() function is called at the very beginning of your main function. This ensures that the logging system is fully initialized and ready to capture events from the moment your application starts.
  4. Tracing in Commands:
    • You use info!, debug!, warn!, and error! macros (similar to println!) to emit log events.
    • Structured Fields: The syntax card_id = %card_id is key. It creates named key-value pairs in your log output. The % ensures the value is formatted using its Display trait. These structured fields are invaluable for filtering and querying logs later. For example, you could easily search for all log entries related to a specific card_id.

3. Update Frontend to Trigger Logging (Optional)

While the logging logic resides in Rust, ensure your Svelte frontend calls the relevant Tauri commands (e.g., agent_start_task) that you’ve instrumented with tracing macros. Your existing frontend code should already do this. The important part is that when these commands are invoked from the UI, the Rust backend will now automatically generate detailed log entries.

Step-by-Step Implementation: Deployment Preparation

Tauri makes building for deployment straightforward. We’ll configure tauri.conf.json and discuss the build process.

1. Configure tauri.conf.json for Production

Open src-tauri/tauri.conf.json. This file is the central configuration for how your Tauri application is built, packaged, and behaves. The structure shown here is compatible with Tauri v2. Review and customize the fields as described.

// src-tauri/tauri.conf.json

{
  "build": {
    "devPath": "../dist",
    "distDir": "../dist",
    "beforeDevCommand": "npm run dev",
    "beforeBuildCommand": "npm run build"
  },
  "package": {
    "productName": "Kanbots",
    "version": "0.1.0",
    "description": "Kanban board with AI agents for development workflows.",
    "authors": ["Your Name or Team Name"],
    "homepage": "https://your-project-website.com"
  },
  "tauri": {
    "bundle": {
      "active": true,
      "targets": "all",
      "identifier": "com.yourcompany.kanbots",
      "icon": [
        "icons/32x32.png",
        "icons/128x128.png",
        "icons/128x128@2x.png",
        "icons/icon.icns",
        "icons/icon.ico"
      ],
      "resources": [],
      "externalBin": [],
      "copyright": "Copyright (c) 2026 Your Name",
      "deb": {
        "depends": []
      },
      "macOS": {
        "entitlements": null,
        "exceptionDomain": "",
        "frameworks": [],
        "providerShortCode": null,
        "signingIdentity": null,
        "hardenedRuntime": true,
        "resources": [],
        "infoPlist": {}
      },
      "windows": {
        "certificateThumbprint": null,
        "digestAlgorithm": "sha256",
        "timestampUrl": ""
      }
    },
    "security": {
      "csp": null
    },
    "windows": [
      {
        "fullscreen": false,
        "resizable": true,
        "title": "Kanbots",
        "width": 1200,
        "height": 800
      }
    ]
  }
}

Key fields to note and customize:

  • build.devPath / build.distDir: These point to your Svelte frontend’s build output directory. ../dist is a common default.
  • build.beforeDevCommand / build.beforeBuildCommand: These commands tell Tauri how to start your frontend in development mode and how to build it for production. Ensure npm run dev and npm run build (or yarn / pnpm equivalents) are correctly configured in your frontend’s package.json.
  • package.productName: The user-facing name of your application, displayed in the OS.
  • package.version: The version number of your application. Follow semantic versioning (e.g., 0.1.0, 1.0.0).
  • package.description, package.authors, package.homepage: Important metadata for your application’s installers and about dialogs.
  • tauri.bundle.identifier: CRITICAL. This is a unique identifier for your application, usually in reverse domain name notation (e.g., com.yourcompany.kanbots). It’s used by the operating system for various purposes, including application sandboxing, storing user data, and identifying your app for updates. Ensure you change com.kanbots.dev to something unique to your project.
  • tauri.bundle.icon: Paths to your application icons. Tauri uses these to generate platform-specific icons. Ensure these files exist in your src-tauri/icons/ directory.
  • tauri.bundle.targets: Defines which installer types Tauri should build. Set to "all" to build for all supported targets for your host OS, or specify specific targets like ["msi", "dmg", "appimage"].
  • tauri.bundle.macOS.signingIdentity / tauri.bundle.windows.certificateThumbprint: These fields are for code signing. Code signing is crucial for production applications to establish trust with users and operating systems. Setting them up requires developer accounts (Apple Developer Program, Microsoft Partner Center) and specific certificates. For now, leaving them null is fine, but be aware of their purpose for future production readiness.
  • tauri.bundle.macOS.hardenedRuntime: A security feature for macOS applications, generally recommended to be true for production builds.

2. Create Application Icons

Ensure you have a set of application icons in the src-tauri/icons/ directory as specified in tauri.conf.json. These icons are used by the operating system for the application executable, taskbar, and various menus. If you don’t have them, you can use online tools (search for “Tauri icon generator” or “app icon generator”) to create a set from a single high-resolution image.

Example structure:

src-tauri/
└── icons/
    ├── 32x32.png
    ├── 128x128.png
    ├── 128x128@2x.png
    ├── icon.icns  (macOS specific)
    └── icon.ico   (Windows specific)

3. Build the Application for Distribution

Once tauri.conf.json is configured, building your application for distribution is a single command. Navigate to your src-tauri directory in the terminal.

# In your project root (where Cargo.toml is in src-tauri/)
cd src-tauri
cargo tauri build

This command will:

  1. Execute npm run build (or pnpm build, yarn build) in your frontend directory (../dist) to compile your Svelte application into static assets.
  2. Compile your Rust backend in release mode (with optimizations).
  3. Bundle the compiled frontend and backend, along with your specified assets and icons, into platform-specific installers or application bundles.

The generated installers and application bundles will be located in src-tauri/target/release/bundle/. You’ll typically find .dmg (macOS), .msi or .exe (Windows), and .deb or .AppImage (Linux) files there, depending on your tauri.bundle.targets setting and host OS.

Testing & Verification: Log Inspection and Build Check

After implementing logging and preparing for deployment, it’s crucial to verify everything works as expected.

1. Verify Agent Logging

  1. Run Kanbots in Development Mode: Open your terminal in the src-tauri directory and execute:
    cargo tauri dev
    You should see console output from your tracing setup, including the info! message confirming logging initialization.
  2. Trigger an Agent Task: Interact with the Kanbots UI to start an AI agent task on a card (e.g., initiate the agent_start_task command).
  3. Locate the Log File:
    • In your terminal, look for the initial info! message: Kanbots logging initialized to: .... This will tell you the exact path to your log directory.
    • Navigate to this directory (e.g., ~/.config/kanbots/logs on Linux, ~/Library/Application Support/com.yourcompany.kanbots/logs on macOS).
    • You should find a file named kanbots.log.YYYY-MM-DD (e.g., kanbots.log.2026-05-24).
  4. Inspect Log Contents: Open the log file using a text editor. You should see JSON-formatted entries reflecting the agent’s activity:
    {"timestamp":"2026-05-24T12:00:00.000000Z","level":"INFO","target":"kanbots_app::main","fields":{"message":"AI agent task initiated.","card_id":"card-123","agent_id":"agent-456","task":"generate hello world"},"span":{"name":"agent_start_task"},"spans":[{"name":"agent_start_task"}]}
    {"timestamp":"2026-05-24T12:00:00.100000Z","level":"DEBUG","target":"kanbots_app::main","fields":{"message":"Agent is processing task...","card_id":"card-123","agent_id":"agent-456"},"span":{"name":"agent_start_task"},"spans":[{"name":"agent_start_task"}]}
    // ... more log entries for API calls, file creations, etc. ...
    Look for INFO messages marking the start and completion of tasks, DEBUG for intermediate steps, and ERROR if you simulated a failure condition. The structured fields (card_id, agent_id, task) should be present, confirming the JSON output.

2. Verify Application Build

  1. Run the Build Command: Open your terminal in the src-tauri directory and execute:
    cargo tauri build
    This process can take several minutes.
  2. Check Output Directory: Once the build completes, navigate to src-tauri/target/release/bundle/.
  3. Inspect Bundles/Installers:
    • macOS: You should find a .dmg disk image and/or an .app bundle.
    • Windows: You should find an .msi installer and/or a standalone .exe executable.
    • Linux: You should find a .deb package (for Debian/Ubuntu-based systems) or an .AppImage file (for broader Linux compatibility).
  4. Test the Built Application: Install or run the generated package on your system. Confirm that the application launches correctly, the UI is fully functional, and that AI agents can still perform tasks. Crucially, verify that this built application also generates log files in the correct location (as confirmed in step 1). This ensures your production build includes all logging components.

Production Considerations: Operations and Security

Deploying a desktop application involves more than just building a package; it requires careful consideration of security, maintenance, and user experience.

Secure API Key Handling

🧠 Important: Never hardcode sensitive API keys directly into your application’s source code or bundle them into the executable. This exposes them to anyone who can inspect your application.

For desktop applications, robust methods for handling secrets include:

  • Environment Variables: This is the simplest and recommended starting point. Users set environment variables (e.g., CLAUDE_API_KEY, CODEX_API_KEY) in their shell before launching the application. Your Rust backend then reads these using std::env::var.
    • Tradeoff: Requires manual user setup and isn’t as secure as OS-level storage if the user’s environment is compromised.
  • OS-level Secret Management: For higher security, leverage platform-specific credential managers like macOS Keychain, Windows Credential Manager, or libsecret on Linux. These store secrets securely at the operating system level.
    • Tradeoff: More complex to implement, often requires additional Rust crates (e.g., keyring) and platform-specific configurations.
  • Encrypted Configuration File: A configuration file stored locally that is encrypted at rest and decrypted at runtime using a user-provided password or an OS-level secret.
    • Tradeoff: Adds complexity for key management and user interaction.

Recommendation for Kanbots: Start with environment variables for ease of development and initial distribution. For a truly production-grade application, especially if dealing with sensitive user data or high-value API keys, investigate OS-level secret management.

Log Rotation and Retention

Our tracing-appender configuration already handles daily log rotation. For a production system, consider further enhancements:

  • Compression: Implement automatic compression of old log files (e.g., using gzip) to save disk space, especially for applications generating high volumes of logs.
  • Retention Policy: Define and enforce a policy for automatically deleting log files older than a certain period (e.g., 30 days). This prevents log files from consuming excessive disk space over time. This can be managed by a small background task within your Rust app or an external script.

Performance Impact of Logging

While tracing with non-blocking appenders is highly efficient, excessive debug! or trace! logging in a production build can still introduce a minor performance overhead and generate very large log files.

  • Sensible Log Levels: Use info! for significant events, debug! for detailed debugging (which is often disabled or filtered out in release builds by default via RUST_LOG), warn! for non-critical issues, and error! for critical failures.
  • Conditional Logging: Avoid expensive computations or data serialization within debug! or trace! macros unless those levels are explicitly enabled. For example, avoid complex string formatting if the log message won’t be seen.

Application Signing

Code signing is a non-negotiable step for distributing production desktop applications:

  • Trust and Authenticity: Code signing assures users that the application comes from a verified developer and has not been tampered with since it was signed.
  • OS Security Features: macOS Gatekeeper, Windows SmartScreen, and other OS security mechanisms will block or heavily warn users about unsigned applications. A signed application appears legitimate and runs without undue friction.
  • Updates: Code signing is often a prerequisite for secure over-the-air update mechanisms.

Setting up code signing requires:

  • Obtaining a developer certificate from a trusted Certificate Authority (e.g., Apple Developer Program, Microsoft Partner Center).
  • Configuring your build environment with these certificates.
  • Updating tauri.conf.json with the appropriate signingIdentity (macOS) or certificateThumbprint (Windows).

This is a complex, platform-specific process that typically falls outside the scope of a single project chapter, but it’s a critical consideration for any public distribution.

Distribution Channels

Once your application is built and signed, you need a strategy for how users will acquire it:

  • Direct Download: Host the installers (DMG, MSI, AppImage) on your project’s website. This offers the most control but requires you to manage updates.
  • App Stores:
    • macOS App Store: Offers broad reach but requires significant changes to adhere to Apple’s strict sandboxing rules and review process.
    • Microsoft Store: Generally easier to get into than Apple’s store.
    • Linux Package Managers: Distribute via .deb for Debian/Ubuntu-based systems, .rpm for Fedora/RHEL, or AppImage for wider compatibility across various Linux distributions.

Common Issues & Solutions

  1. Logs Not Appearing or Empty:

    • Issue: You run the app, trigger agents, but the log file is empty or doesn’t exist.
    • Solution:
      • Check Console Output: Verify the initial Kanbots logging initialized to: ... message in your terminal to confirm the log directory path and that setup_logging() ran.
      • setup_logging() Call: Ensure setup_logging() is called at the very beginning of your main function in src-tauri/src/main.rs.
      • RUST_LOG Environment Variable: Check if the RUST_LOG environment variable is set to a level that filters out all your messages (e.g., RUST_LOG=off or RUST_LOG=error when you’re only emitting info! messages). Try setting RUST_LOG=debug to get more verbose output.
      • File Permissions: Ensure your application has write permissions to the determined log directory.
  2. cargo tauri build Fails:

    • Issue: The build process errors out, often related to frontend compilation or specific platform targets.
    • Solution:
      • Frontend Build: First, try running npm run build (or pnpm build, yarn build) independently in your frontend directory (../) to ensure it compiles successfully. Fix any frontend-specific errors there.
      • Dependencies: Confirm all Rust (cargo update) and Node.js (npm install) dependencies are correctly installed and up-to-date.
      • Tauri Configuration: Double-check src-tauri/tauri.conf.json for any syntax errors or incorrect paths, especially for bundle.identifier and icon paths.
      • Cross-Compilation: If you’re attempting to build for a different OS (e.g., macOS on Linux, or Windows on macOS), you might need specific cross-compilation tools (e.g., mingw for Windows builds on Linux) or virtual machines. It’s generally easiest to build for a target OS on that OS itself.
  3. Sensitive Information in Logs:

    • Issue: API keys, personal user data, or other secrets are accidentally written to log files.
    • Solution:
      • Code Review: Rigorously review all info!, debug!, error!, etc., calls to ensure no sensitive data is passed directly into log messages or structured fields. This includes prompt contents sent to AI APIs or responses received.
      • Redaction/Masking: For production systems, implement a log redaction mechanism. This could be a custom tracing-subscriber layer that automatically masks or removes sensitive patterns (e.g., API key formats, email addresses, credit card numbers) before writing to the log file.
      • Access Control: Ensure log files themselves are protected with appropriate file system permissions, limiting access to authorized users.

Summary & Next Steps

Congratulations! You’ve reached the end of building Kanbots, a sophisticated desktop Kanban application capable of orchestrating multi-agent AI workflows using Git worktrees. In this final chapter, we’ve equipped Kanbots with essential observability through structured logging and explored the critical steps for preparing your application for real-world deployment.

You now have a functional desktop application that:

  • Provides an interactive Kanban board for task management.
  • Integrates AI agents (like Claude Code or Codex) for automated task execution.
  • Manages isolated task environments using Git worktrees, preventing conflicts.
  • Orchestrates complex multi-agent workflows with persona-based assignments for efficient development.
  • Offers clear insights into agent activities and system behavior via robust, structured logging.
  • Is configured and ready for packaging and distribution across Windows, macOS, and Linux.

This project serves as a strong foundation for building more advanced AI-powered desktop tools. From here, consider these next steps to evolve Kanbots:

  • Enhanced UI/UX: Implement more sophisticated real-time feedback for agent progress, richer control over agent tasks (pause, stop, re-run), and user customization options for the board and agents.
  • More Agent Types and Tooling: Integrate with additional specialized AI models or provide agents with access to more tools (e.g., web search, file system manipulation with careful sandboxing, external APIs).
  • Advanced Workflow Orchestration: Develop more complex dependency management between agent tasks, allowing for sophisticated multi-stage pipelines.
  • Cloud Integration (Optional): While local-first is a key principle, you might explore syncing board state or agent progress to a cloud service for collaboration among a team.
  • AI Cost Monitoring: Integrate with billing APIs from AI providers (if available and permissible) to display real-time cost estimates within the application for each agent’s activity.

Keep iterating, keep building, and continue to explore the exciting possibilities of AI-enhanced development!


References

This page is AI-assisted and reviewed. It references official documentation and recognized resources where relevant.