Documentation
System Architecture

Last Updated: 2026-01-20 Version: 0.1.0

Overview

AnyCowork is a native desktop AI assistant platform built with Tauri and Rust. It provides:

  • Native Performance: Rust backend with minimal resource usage (Optimized)
  • Smart AI: Multi-provider support (Gemini 3 Pro, OpenAI, Anthropic Claude) via rig-core & MCP integration (Smart)
  • Safe Execution: Human-in-the-loop permission system (Safe)
  • Telegram Integration: Multi-bot support with teloxide
  • Local-First: SQLite database with Diesel ORM

Architecture Layers

PRESENTATION LAYER

  • React + Vite Frontend
  • Components (shadcn/ui + Tailwind)
  • React Query for state management
  • Tauri IPC for backend communication

APPLICATION LAYER

  • Tauri Commands (lib.rs)
  • Agent CRUD operations
  • Chat message handling
  • Telegram bot management
  • Approval workflow

SERVICE LAYER

  • Agent Loop (agents.rs)
  • Telegram Manager (telegram.rs)
  • Events System (events.rs)

AI PROVIDER LAYER

  • rig-core Framework
  • AI Clients: Gemini 3 Pro, OpenAI, Anthropic

DATA LAYER

  • Diesel ORM + SQLite
  • SQLite Database (anycowork.db)

Core Components

1. Tauri Application (lib.rs)

Purpose: Main application entry point and IPC command definitions

Key Responsibilities:

  • Initialize application state
  • Define Tauri commands for frontend communication
  • Manage shared state (database pool, bot manager, pending approvals)
  • Window event handling

Application State:

pub struct AppState {
    pub db_pool: DbPool,
    pub telegram_manager: TelegramBotManager,
    pub pending_approvals: Arc<DashMap<String, oneshot::Sender<bool>>>,
}

Command Categories:

  • Agent management: create_agent, get_agents
  • Chat: chat
  • Telegram: create_telegram_config, start_telegram_bot, etc.
  • Approval: approve_action, reject_action

2. Agent System (agents.rs)

Purpose: Execute AI-powered conversations with tool support

Components:

  • AgentLoop: Manages conversation state and AI interactions
  • ExecutionJob: Represents a running agent task
  • ExecutionStep: Individual tool execution within a job

Event Types:

  • JobStarted - Agent begins processing

  • Thinking - Agent is processing

  • ApprovalRequired - Tool needs user approval

  • StepApproved / StepRejected - Approval result

  • StepCompleted - Tool execution finished

  • Token - Streaming response chunk

  • JobCompleted - Agent finished

  • JobCompleted - Agent finished

3. Skills System (skills/)

Purpose: Extensible capabilities for agents

Components:

  • SkillTool: Tool wrapper for executing skills
  • DockerSandbox: Verification and isolation environment
  • SkillLoader: Loads skills from filesystem/marketplace

Skill Structure:

  • skill.yaml: Metadata (name, description, triggers)
  • README.md: User documentation
  • Source Files: Python scripts, Node.js scripts, etc.

Execution Modes:

  • Sandbox: Runs in isolated Docker container (Debian/Alpine)
  • Flexible: Uses Docker if available, falls back to direct
  • Direct: Runs on host (if permitted)

4. Telegram Integration (telegram.rs)

Purpose: Manage multiple Telegram bot instances

Components:

  • TelegramBotManager: Lifecycle management for bots
  • BotShutdownSender: Graceful shutdown channel

Features:

  • Start/stop individual bots

  • Auto-start bots on application launch

  • Chat ID filtering for security

  • Integration with agent system

    Send response to Telegram


### 5. Database Layer (database.rs, schema.rs, models.rs)

**Purpose**: Persistent storage with Diesel ORM

**Tables**:
- `agents` - Agent configurations
- `sessions` - Chat sessions
- `telegram_configs` - Telegram bot settings

**Connection Pool**:
```rust
pub type DbPool = r2d2::Pool<ConnectionManager<SqliteConnection>>;

Migrations: Managed via Diesel CLI, auto-run on startup

6. Event System (events.rs)

Purpose: Type-safe event definitions for frontend communication

Event Structures:

pub enum AgentEvent {
    JobStarted { job: ExecutionJob },
    Thinking { message: String },
    ApprovalRequired { job: ExecutionJob, step: ExecutionStep },
    StepApproved { job: ExecutionJob, step: ExecutionStep },
    StepRejected { job: ExecutionJob, step: ExecutionStep },
    StepCompleted { job: ExecutionJob, step: ExecutionStep },
    Token { content: String },
    JobCompleted { job: ExecutionJob, message: String },
}

Frontend Architecture

Technology Stack

  • Framework: React 19
  • Build Tool: Vite
  • Language: TypeScript
  • Styling: Tailwind CSS + shadcn/ui
  • State: React Query (TanStack Query)
  • Routing: React Router

Tauri IPC Communication

Frontend communicates with Rust backend via Tauri's invoke API:

// lib/anycowork-api.ts
import { invoke } from '@tauri-apps/api/core';
 
export async function createAgent(agent: AgentCreate): Promise<Agent> {
  return invoke('create_agent', { agent });
}
 
export async function chat(agentId: string, message: string): Promise<void> {
  return invoke('chat', { agentId, message });
}

Event Listening

import { listen } from '@tauri-apps/api/event';
 
// Listen for agent events
listen(`session:${sessionId}`, (event) => {
  const agentEvent = event.payload as AgentEvent;
  switch (agentEvent.type) {
    case 'Token':
      appendMessage(agentEvent.content);
      break;
    case 'JobCompleted':
      finishMessage(agentEvent.message);
      break;
  }
});

Data Flow

Chat Message Flow

  1. User types message in ChatPage
  2. Frontend calls invoke('chat', { agentId, message })
  3. Tauri routes to chat() command
  4. AgentLoop.run() starts in background task
  5. Events emitted via window.emit()
  6. Frontend receives events via listen()
  7. UI updates in real-time

Approval Workflow

  1. Agent determines tool needs approval
  2. Emit ApprovalRequired event
  3. Frontend shows approval dialog
  4. User clicks Approve/Reject
  5. Frontend calls approve_action or reject_action
  6. Oneshot channel resolves
  7. AgentLoop continues or skips tool

Configuration

Environment Variables

# Required (choose one or more)
GOOGLE_AI_API_KEY=your_gemini_api_key    # Google AI Studio (Gemini) - Default
OPENAI_API_KEY=your_openai_api_key       # OpenAI (optional)
ANTHROPIC_API_KEY=your_anthropic_api_key # Anthropic Claude (optional)
 
# Optional
RUST_LOG=info    # Logging level

Database Location

  • Linux: ~/.local/share/com.anycowork.app/anycowork.db
  • macOS: ~/Library/Application Support/com.anycowork.app/anycowork.db
  • Windows: %APPDATA%\com.anycowork.app\anycowork.db

Security

Sandboxing

  • Tauri provides process isolation
  • File operations restricted to app data directory
  • Network requests go through system proxy

Docker Sandbox (New)

Purpose: Safe execution of untrusted code (Skills, Bash)

Features:

  • Isolation: Runs code in debian:stable-slim or alpine containers
  • Resource Limits: Configurable RAM/CPU limits (e.g., 256MB RAM)
  • Network: Optional network access
  • Mounts: Workspace mounted as R/W, Skill files as R/O

Enforcement:

  • Agents can enforce "Sandbox Mode" globally via execution_settings
  • Skills can require "Sandbox Mode" in skill.yaml
  • If Sandbox is required but Docker is missing, execution is blocked

API Key Management

  • Keys stored in environment variables
  • Never exposed to frontend
  • Not stored in database

Input Validation

  • Diesel ORM prevents SQL injection
  • Serde deserialization validates input types
  • Path traversal prevented in file operations

Design Patterns

Command Pattern

Used in: Tauri IPC commands

#[tauri::command]
async fn create_agent(state: State<'_, AppState>, agent: NewAgent) -> Result<Agent, String>

Observer Pattern

Used in: Event emission for real-time updates

window.emit(&format!("session:{}", session_id), event)?;

Repository Pattern

Used in: Database operations

pub fn create_agent(conn: &mut SqliteConnection, new_agent: &NewAgent) -> QueryResult<Agent>

Technology Stack

Backend (Rust)

  • Framework: Tauri 2.0
  • ORM: Diesel
  • Database: SQLite
  • AI: rig-core (Gemini, OpenAI, Anthropic)
  • Telegram: teloxide
  • Async: Tokio
  • Serialization: Serde

Frontend (TypeScript)

  • Framework: React 19
  • Build: Vite
  • Styling: Tailwind CSS
  • Components: shadcn/ui, Radix UI
  • State: React Query
  • Routing: React Router

References