Skip to main content

Architecture Overview

Evatar uses a three-tier architecture with frontend-backend separation, consisting of Android Client, Python Backend, and React Web Frontend, communicating via REST API.


System Architecture


Core Components

Backend Service Layer

The backend is based on the FastAPI framework, using SQLAlchemy ORM with SQLite database. Core modules:

ModuleFileResponsibility
App Entrymain.pyFastAPI app initialization, CORS, auth middleware, rate limiting
Configconfig.pyPydantic Settings, env var prefix EVATAR_
Data Modelsmodels.pySQLAlchemy declarative models, all table definitions
Screenshot Pipelineservices/pipeline.pyReceives photo_id, calls LLM Vision API to analyze screenshots
Agent Chat Engineservices/agent.pyMulti-turn dialogue, tool call loop (max 3 rounds), user memory injection
Intent Reasonerservices/reasoner.pyBackground scheduled analysis of recent activity, generates structured notes
Memory Systemservices/memory.pyShort-term (48h expiry) and long-term (permanent) memory, LLM extraction + dedup + decay
RAG Retrievalservices/rag.pyFTS5 full-text search + keyword fuzzy matching
LLM Clientservices/llm.pyShared httpx.AsyncClient, supports Vision multimodal and Tool Calling
Schedulerservices/scheduler.pyHourly reasoning, daily memory decay, daily data cleanup
Push Notificationsservices/push.pyBroadcast push to all registered devices (FCM / Webhook)
Data Encryptionservices/encryption.pyFernet symmetric encryption, auto key management, key rotation
Data Retentionservices/retention.pyCleanup expired data by day count
Web Searchservices/search.pyTavily API preferred, Brave Search as fallback
File Storageservices/storage.pySave original images and thumbnails

API Routes

Route PrefixFileMain Endpoints
/api/photosapi/photos.pyPOST /upload, POST /upload-batch, GET / (list), GET /{id}, GET /{id}/image, GET /sync-state
/api/chatapi/chat.pyPOST /send, POST /send-with-file, GET /conversations, GET /conversations/{id}
/api/dynamicsapi/dynamics.pyGET / (cursor pagination), GET /{id}, PUT /{id}/read, POST /trigger
/api/memoriesapi/memories.pyGET /, GET /stats
/api/configapi/config.pyGET /llm, PUT /llm, GET /llm/presets
/api/skillsapi/skills.pyGET /, GET /{id}
/api/pushapi/push.pyPOST /register, POST /test
/api/healthmain.pyGET / -- returns {"status": "ok"}

Middleware

Authentication Middleware

When EVATAR_API_KEY is set, all requests except / and /api/health require a Bearer <key> in the Authorization header. Uses hmac.compare_digest for secure comparison.

Rate Limiting Middleware

IP-level rate limiting (10 requests per minute) on the following high-frequency endpoints:

  • /api/chat/send
  • /api/chat/send-with-file
  • /api/dynamics/trigger

Android Client Architecture

The Android client uses the MVVM pattern, built with Jetpack Compose:

ComponentFileResponsibility
MainActivityMainActivity.ktApp entry, permission requests, theme/language switching, onboarding flow
AppNavigationui/AppNavigation.ktBottom navigation: Dynamics / Chat / Settings tabs
OnboardingScreenui/screens/OnboardingScreen.ktFirst-use guide: server config -> sync range -> sync execution
ChatTabui/screens/ChatTab.ktChat interface, supports Markdown rendering and file attachments
DynamicTabui/screens/DynamicTab.ktDynamic notes list, cursor pagination + infinite scroll
SettingsTabui/screens/SettingsTab.ktSettings page: theme, language, server config
SyncManagersync/SyncManager.ktScreenshot scanning (MediaStore) and concurrent upload (Semaphore(3))
SyncWorkersync/SyncWorker.ktWorkManager CoroutineWorker, background scheduled sync
SyncServicesync/SyncService.ktForeground Service, keeps sync task running continuously
ApiClientnetwork/ApiClient.ktOkHttp singleton, retry logic (max 3 times, exponential backoff)
ChatViewModelviewmodel/ChatViewModel.ktChat state management
DynamicViewModelviewmodel/DynamicViewModel.ktDynamic notes state management

Background Tasks

The backend includes a scheduler (services/scheduler.py) running via asyncio.create_task:

TaskIntervalDescription
Intent Reasoning1 hourCollects recent screenshots, chats, memories, calls LLM to generate note articles
Memory Decay24 hoursDeletes expired short-term memories, reduces long-term memory importance
Data Cleanup24 hoursCleans expired data per EVATAR_RETENTION_DAYS (default 30 days)

Additionally, every 3 screenshot analyses completed (_REASONING_TRIGGER_EVERY = 3), a reasoning cycle is automatically triggered.