Skip to content

lacasoft/evva-ai

Repository files navigation

Evva

Evva

AI-powered personal assistant with real memory and proactive actions.
Lives in Telegram and WhatsApp. Remembers everything. Acts before you ask.

Release License Node Skills Tools Channels

Leer en Espanol · Setup Guide · Releases

Try Evva now — no setup required: t.me/evva_dev_bot

Evva Demo


Features

Brain Persistent semantic memory Bell Scheduled reminders & proactive messages
Note Notes, lists & todos Person Contact management
Calendar Google Calendar integration Mail Gmail read, search & send
Dollar Personal finance & savings goals Mic Voice note transcription (Groq Whisper)
Camera Photo & document analysis (Claude Vision) Sun Daily proactive briefing
Globe Web search (Brave) & news summaries Cloud Weather for any city
Pill Medication & habit tracking Phone Emergency contacts
Language Translation & smart dictation Music Spotify integration
Exchange Live currency conversion Birthday Proactive birthday reminders
Recipe Recipe suggestions from grocery lists WhatsApp Multi-channel (Telegram + WhatsApp)
Plane Flight search (SerpAPI) + bus search (Firecrawl) Broom Auto-unsubscribe from newsletters
Speaker Voice responses (OpenAI TTS) Puzzle Self-extending runtime skills
Pencil Update and delete user data

Tech Stack

Layer Technology
Framework NestJS + TypeScript
Bot grammY
LLM Claude Sonnet (Vercel AI SDK)
Embeddings Voyage AI (voyage-3-lite, 512 dims)
Database PostgreSQL + pgvector
Queue BullMQ + Redis
Transcription Groq (Whisper)
Vision Claude Vision
Search Brave Search API
Monorepo pnpm workspaces

Architecture

Evva follows a gateway/worker split. The gateway handles all user-facing interactions -- receiving messages, orchestrating the LLM agent loop, and returning responses. Heavy or scheduled work (reminders, fact extraction, daily briefings) is offloaded to an async worker via BullMQ, keeping the bot responsive at all times.

Telegram / WhatsApp
        |
        v
+-----------------------------------+
|  Gateway (NestJS)                 |
|                                   |
|  TelegramModule    -- receives messages, sends replies
|  ConversationModule -- orchestrates the agent loop
|  MemoryModule      -- RAG over user facts
|  PersonaModule     -- dynamic system prompt
|  ToolsModule       -- web_search, reminders, etc.
|  SchedulerModule   -- enqueues jobs via BullMQ
|  UsersModule       -- user and assistant CRUD
+-----------------------------------+
        | BullMQ (Redis)
        v
+-----------------------------------+
|  Worker (NestJS)                  |
|                                   |
|  ScheduledJobProcessor   -- executes reminders
|  FactExtractionProcessor -- extracts facts from conversations
|  DailyBriefingProcessor  -- sends daily morning summaries
+-----------------------------------+
        |
        v
+-----------------------------------+
|  PostgreSQL + pgvector            |
|                                   |
|  users, assistant_config,         |
|  messages, memory_facts,          |
|  onboarding_state                 |
+-----------------------------------+

Quick Start

For detailed step-by-step instructions, see docs/SETUP.md.

Prerequisites: Node.js >= 22, pnpm >= 9, PostgreSQL with pgvector, Redis.

Option A -- Docker Compose (recommended)

git clone https://github.com/lacasoft/evva-ai.git
cd evva-ai
cp .env.example .env
# Edit .env with your credentials (see .env.example for all variables)

docker compose up

PostgreSQL, Redis, migrations, gateway, and worker all start automatically.

Option B -- Manual setup
git clone https://github.com/lacasoft/evva-ai.git
cd evva-ai
pnpm install
cp .env.example .env
# Edit .env with your credentials

pnpm db:migrate

# Terminal 1 -- Gateway (Telegram bot)
pnpm dev:gateway

# Terminal 2 -- Worker (BullMQ processors)
pnpm dev:worker

The bot starts in long polling mode -- no webhook setup required for local development.


Project Structure

evva/
├── apps/
│   ├── gateway/                 # Main app -- Telegram bot + API
│   │   └── src/
│   │       ├── telegram/             # Telegram message handler
│   │       ├── conversation/         # Agent loop + onboarding
│   │       ├── memory/              # Fact search and storage
│   │       ├── persona/             # System prompt construction
│   │       ├── tools/               # Tools available to the LLM
│   │       ├── scheduler/           # BullMQ job scheduling
│   │       ├── users/               # User and assistant CRUD
│   │       ├── health/              # Health check endpoints
│   │       └── config/              # Env var validation
│   │
│   └── worker/                  # BullMQ worker -- async jobs
│       └── src/
│           ├── processors/           # ScheduledJob + FactExtraction
│           └── handlers/             # TelegramSender
│
├── packages/
│   ├── core/                    # Shared types, constants, and utils
│   ├── database/                # PostgreSQL client (pg) and repositories
│   ├── ai/                      # LLM (Claude), embeddings (Voyage), prompts
│   └── skills/                  # Modular skill plugins (28 skills)
│       └── src/
│           ├── registry.ts           # Central skill registry
│           ├── base-skill.ts         # SkillDefinition interface
│           ├── rag-helper.ts         # Cross-skill RAG fact saving
│           ├── runtime-loader.ts     # Runtime skill engine
│           ├── memory/               # Persistent semantic memory
│           ├── notes/                # Notes and lists
│           ├── contacts/             # Contact management
│           ├── data-management/      # Update and delete user data
│           ├── reminders/            # Scheduled reminders
│           ├── finance/              # Cards, transactions, savings
│           ├── finance-security/     # Secret word protection
│           ├── health/               # Medication and habit tracking
│           ├── emergency/            # Emergency contacts
│           ├── calendar/             # Google Calendar
│           ├── gmail/                # Gmail (read, search, send)
│           ├── spotify/              # Spotify integration
│           ├── weather/              # Weather lookup
│           ├── search/               # Web search (Brave)
│           ├── news/                 # News summary
│           ├── translator/           # Language translation
│           ├── exchange/             # Currency exchange rates
│           ├── dictation/            # Smart message drafting
│           ├── briefing/             # Daily proactive briefing
│           ├── birthdays/            # Birthday reminders
│           ├── recipes/              # Recipe suggestions
│           ├── voice/                # Voice note transcription
│           ├── vision/               # Photo and document analysis
│           ├── travel/               # Flight and bus search
│           ├── email-cleaner/        # Auto-unsubscribe from newsletters
│           ├── tts/                  # Text-to-speech voice responses
│           └── skill-creator/        # Self-extending runtime skills
│
└── docs/                        # Setup guides and documentation
Adding a New Skill

Each skill is a self-contained module. To add a new one:

// packages/skills/src/my-skill/index.ts
import { tool } from 'ai';
import { z } from 'zod';
import type { SkillDefinition } from '../base-skill.js';

export const mySkill: SkillDefinition = {
  name: 'my-skill',
  description: 'What this skill does',
  category: 'utility',
  forProfiles: ['young', 'adult', 'senior'],
  requiredEnv: ['MY_API_KEY'],  // optional

  buildTools: (ctx) => ({
    my_tool: tool({
      description: 'Tool description for the LLM',
      parameters: z.object({ input: z.string() }),
      execute: async ({ input }) => {
        return { success: true, result: input };
      },
    }),
  }),

  promptInstructions: [
    '- my_tool: Description of what this tool does',
  ],
};

Then register it in packages/skills/src/index.ts:

export { mySkill } from './my-skill/index.js';
import { mySkill } from './my-skill/index.js';
skillRegistry.register(mySkill);

The skill is automatically available to the LLM. No other files need to change.


How it Works

Message Flow

  1. User sends a message in Telegram or WhatsApp.
  2. TelegramService receives the message and upserts the user in PostgreSQL.
  3. If the user is new, the onboarding flow starts (choose assistant name).
  4. For existing users: semantic search retrieves relevant facts (Voyage + pgvector), a dynamic system prompt is constructed, recent history is loaded, and Claude is called with all available tools.
  5. If the LLM invokes a tool, it is executed and the result is fed back.
  6. The final response is sent to the user. The message is persisted, and fact extraction is enqueued in BullMQ (async).

Proactive Flow (Reminders)

  1. User says "remind me to X on Friday at 8am".
  2. Claude calls the create_reminder tool.
  3. SchedulerService creates a BullMQ job with the calculated delay.
  4. At the scheduled time, ScheduledJobProcessor generates a personalized message with Claude and delivers it to the user.

Available Tools

Productivity

Tool Description Requires
save_fact Persist a permanent fact about the user --
create_note Create notes or lists --
get_notes View active notes and lists --
update_note Modify, check items, archive or delete notes --
save_contact Store a contact (name, phone, email, relationship) --
search_contacts Search contacts by name or relationship --
create_reminder Schedule a future reminder Redis
configure_daily_briefing Enable/disable daily morning summary --

Finance

Tool Description Requires
add_credit_card Register a credit card with cut-off and payment dates --
get_credit_cards View registered cards with balances --
record_transaction Log income or expense --
get_finance_summary Monthly financial summary by category --
get_recent_transactions View recent transactions --
create_savings_goal Create a savings goal with target amount --
get_savings_goals View savings progress --

Communication

Tool Description Requires
connect_google Generate Google OAuth link (Calendar + Gmail) Google OAuth
list_calendar_events List upcoming calendar events Google OAuth
create_calendar_event Create a new calendar event Google OAuth
list_emails List recent emails Google OAuth
read_email Read full email content Google OAuth
send_email Send an email from user's Gmail Google OAuth

Health

Tool Description Requires
add_medication Register a medication with schedule --
get_medications View active medications --
create_habit Create a habit to track daily --
log_habit Log progress on a habit --
get_habit_progress View today's habit completion --
add_emergency_contact Register an emergency contact --
get_emergency_contacts View emergency contacts --

Utility

Tool Description Requires
web_search Up-to-date web search BRAVE_SEARCH_API_KEY
summarize_news Search and summarize current news BRAVE_SEARCH_API_KEY
get_weather Current weather for a city --
translate Translate text between languages --
calculate_exchange_rate Live currency conversion --
draft_message Generate formal/informal messages --
save_birthday Save a birthday date --
check_upcoming_birthdays Find upcoming birthdays --
suggest_recipes Suggest recipes from grocery list --

Media

Tool Description Requires
connect_spotify Generate Spotify OAuth link Spotify OAuth
now_playing Show currently playing track Spotify OAuth
recent_tracks Show recently played tracks Spotify OAuth
top_tracks Show user's top tracks Spotify OAuth
search_music Search Spotify catalog Spotify OAuth

Travel

Tool Description Requires
search_flights Search flights between cities SERPAPI_API_KEY
search_airport Find airport codes by city name SERPAPI_API_KEY
get_booking_link Get a booking link for a flight SERPAPI_API_KEY
search_buses Search bus routes between cities FIRECRAWL_API_KEY
get_travel_page_info Extract details from a travel page FIRECRAWL_API_KEY

Data Management

Tool Description Requires
update_user_data Update contacts, emergency, cards, medications, habits --
delete_user_data Delete contacts, facts, medications, habits --
set_finance_secret Set a secret word for finance protection --
verify_finance_secret Verify secret word before financial operations --
create_runtime_skill Create a custom skill via conversation --
list_runtime_skills List user-created custom skills --

Token Optimization

Evva is designed to minimize LLM token consumption per message:

Optimization Before After Savings
Conversation history window 12 messages 6 messages ~480 tokens
maxSteps (tool call rounds) 3 2 ~5,400 tokens
System prompt (behavioral block) 225 tokens 80 tokens ~145 tokens
OAuth skill filtering All 60 tools always loaded Only connected tools loaded ~2,000 tokens
Provider query 2 DB calls per message 1 cached call (Redis 5min TTL) Latency
Skill registry env check on every call Cached after first call CPU

Estimated total reduction: ~55% (from ~23K to ~10K tokens per message)

Before:  [system ~1,400] + [60 tools ~4,200] + [history ~960] x 3 steps = ~27,000 tokens
After:   [system ~1,200] + [~25 tools ~1,800] + [history ~480] x 2 steps = ~11,000 tokens

Configuration

Required Environment Variables

Variable Where to get it
TELEGRAM_BOT_TOKEN @BotFather on Telegram
ANTHROPIC_API_KEY console.anthropic.com
VOYAGE_API_KEY dash.voyageai.com
DATABASE_URL postgresql://localhost:5432/evva for local dev
REDIS_URL redis://localhost:6379 for local dev

Optional Environment Variables

Variable Purpose
BRAVE_SEARCH_API_KEY Web search tool (brave.com/search/api)
GROQ_API_KEY Voice note transcription via Whisper
GOOGLE_CLIENT_ID Google Calendar and Gmail integration
GOOGLE_CLIENT_SECRET Google Calendar and Gmail integration
APP_BRAND_NAME Custom assistant brand name (default: "Evva")
LLM_MODEL Override the default Claude model
TELEGRAM_WEBHOOK_URL Production only
TELEGRAM_SECRET_TOKEN Production only -- generate with openssl rand -hex 32

Development

pnpm build              # Build all packages and apps
pnpm build:gateway      # Build gateway only
pnpm build:worker       # Build worker only

pnpm test               # Run all tests
pnpm test:watch         # Run tests in watch mode
pnpm test:cov           # Run tests with coverage

pnpm lint               # Lint all packages
pnpm lint:fix           # Lint and auto-fix

pnpm db:migrate         # Run pending migrations
pnpm db:migrate:new     # Create a new migration file

Telegram Commands

Command Action
/start Welcome message and onboarding
/reset Start a new conversation session
/memory Show what the assistant remembers
/help List available commands

Contributing

Contributions are welcome! Fork the repo, create a feature branch, and open a pull request. Please ensure all tests pass (pnpm test) and linting is clean (pnpm lint) before submitting. For bugs and feature requests, open an issue.


License

MIT


Made by LACA-SOFT · GitHub