Deep Dive
Architecture
How Omni is built — the crate structure, data flow, and key design decisions.
Crate Map
Omni is a Rust workspace split into focused crates. Each crate has a single responsibility and clearly defined boundaries.
Configuration parsing, database (SQLite + SQLCipher encryption), event bus, logging, and shared types. Every other crate depends on this.
Capability-based permission system with 20 capability types. PolicyEngine for decision caching, AuditLogger for trail recording, and scope validation.
4-layer anti-injection pipeline — signature scanning, heuristic analysis, ML classification, and output policy validation. Scans at 5 points in the agent loop.
Extension host, WASM sandbox (Wasmtime), manifest parsing, extension discovery and installation, host functions (FFI bridge), and storage.
Published crate for extension developers. Typed clients for HTTP, filesystem, process, storage, LLM, channels, and config. The omni_main! macro and prelude.
Provider abstraction layer with 6 adapters. SSE streaming, token counting, provider rotation with exponential backoff. Also contains the agent loop, native tools, and hook system.
21 messaging platform adapters, channel manager, multi-instance support, binding registry, message router, and webhook server.
Tauri v2 shell that wires everything together. 26+ IPC commands, event bridging, and application state management. Excluded from the Cargo workspace.
Agent Loop
The agent loop is the core orchestration engine. It manages multi-turn conversations between the user, the LLM, and tools. Each iteration can invoke one or more tools, then feed the results back to the LLM.
Loop Steps (per turn)
Receive user message → Guardian SP-1 scan → MessageReceived hook
Assemble full prompt (system + history + message) → Guardian SP-2 scan → LlmInput hook
Stream response from LLM provider → Guardian SP-3 scan → LlmOutput hook
Parse tool calls from response → Guardian SP-4 scan → BeforeToolCall hook
Execute tools (native or extension) → Permission check → AfterToolCall hook → Guardian SP-5 scan
If tools were called, append results and go to step 2 (up to max_iterations)
Return final text response to user
Tool Resolution
When the LLM requests a tool call, Omni resolves the tool name in this order:
1. Native Tools
29 built-in tools (exec, read_file, web_fetch, git, debugger, etc.). Checked first.
2. Flowchart Tools
Tools from enabled flowcharts. Visual no-code workflows with 19 node types.
3. Extension Tools
Tools from activated extensions. Resolved by reverse-domain ID (e.g., com.example.weather.get_forecast).
Event Bus
The event bus is a broadcast channel that distributes system events to all subscribers. It uses tokio::sync::broadcast for lock-free, multi-consumer event delivery.
Event Types
In the Tauri desktop app, events are bridged to the frontend via Tauri's event system, allowing React components to react to backend state changes in real time.
Database
Omni uses SQLite with SQLCipher encryption for all persistent storage. The database is accessed through Arc<Mutex<Database>> with Tokio's spawn_blocking to avoid blocking the async runtime.
Encryption Key Resolution
OS keychain (macOS Keychain, Windows Credential Manager, Linux Secret Service)
OMNI_DB_KEY environment variable
Key file at ~/.data/Omni/db.key
Auto-generate and store a new key
Tables
Data Flow
A simplified view of how data flows through the system when a user sends a message.
User Input
↓
Tauri IPC (send_message command)
↓
Guardian Scan (SP-1: user input)
↓
Hook: MessageReceived
↓
Agent Loop
↓
LLM Bridge → Provider Adapter → SSE Stream
↓
Guardian Scan (SP-3: LLM output)
↓
Tool Call? → Permission Check → Native/Extension Tool
↓
Guardian Scan (SP-5: tool output)
↓
Response → Tauri Event (omni:llm-chunk) → React UI
Extension Lifecycle
An extension goes through several states from installation to active use.