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
- User types message in ChatPage
- Frontend calls
invoke('chat', { agentId, message }) - Tauri routes to chat() command
- AgentLoop.run() starts in background task
- Events emitted via window.emit()
- Frontend receives events via listen()
- UI updates in real-time
Approval Workflow
- Agent determines tool needs approval
- Emit ApprovalRequired event
- Frontend shows approval dialog
- User clicks Approve/Reject
- Frontend calls approve_action or reject_action
- Oneshot channel resolves
- 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 levelDatabase 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-slimoralpinecontainers - 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