README.md
September 18, 2026 · View on GitHub
EN · RU
Iva is a self-hosted Telegram AI assistant with layered memory that turns your messages into an Obsidian-compatible vault. You talk, it files: voice notes, photos, forwarded posts and decisions become plain-markdown cards it actually remembers. Everything runs on your own server, with your keys and your data.
One command installs it:
curl -fsSL https://raw.githubusercontent.com/smixs/iva-agent/main/install.sh | bash
Why people run Iva
- "What did we agree with client X about the last shipment?" — found in seconds, months later.
- A five-minute voice note from the car → a task list, a draft email, a meeting card.
- "Make a quote from this price list, cut the discount by 2.5%, send it to the client" — a finished Google Doc, link in the chat.
The rest — for business owners, specialists, executives and everyday life: Use cases.
How it works
The bridge long-polls Telegram, so no public HTTPS, domain or webhook is needed. Iva runs as two systemd user services, two systemd watchdog timers and seven in-process eve schedules — operations live in docs/deploy.md.
Wondering what you'd actually use an agent for? → 25+ real scenarios — business, work, everyday life.
Features
Voice, vision, memory, personal CRM, Google Workspace, skills — expand the full list
- Voice — voice, audio and video notes transcribed with Deepgram nova-3; auto-detects ru/uz/en.
- Vision — photos described by your provider's own vision model; no extra key, no extra bill.
- Rich replies — tables, checklists, collapsible blocks and formulas render natively in Telegram via Bot API 10.1 rich messages; plain formatting keeps its proven path, with a graceful fallback.
- Quiet update checks — once a day Iva checks for a newer stable release without spending model tokens. If one exists, Telegram offers Update or Later once; otherwise it says nothing.
- Layered memory — remembers across months, long after the chat window has scrolled away.
- Personal CRM — who your people are, what you agreed, when to follow up.
- Search by meaning — BM25 plus link-graph rerank, any language; optional vector mode with one key.
- Decision cards — what you chose, when and why; old versions stay in a dated History.
- Tasks & reminders — priorities, due dates and a morning digest.
- Web search — four pluggable providers: Tavily, Exa, Parallel or Brave.
- Google Workspace — Gmail, Calendar, Drive, Sheets, Docs and Tasks from chat via the
gwsCLI; installed for you, with a guided key setup right in the conversation. - Skills & MCP — drop one file to add a procedure or connect an MCP server; keys stay in
.env. - Personal Telegram — userbot (beta) — read and send from your own account, not just the bot; connect by chat (QR, no terminal). Rough and buggy — opt-in, at your own risk. A server-side anti-ban guardrail (FloodWait compliance + randomized pacing + circuit-breaker) is enforced, not just advised. Details.
- Safe to forward — forwarded text, captions and voice transcripts pass an injection screen before the model reads them. A flagged message or transcript reaches the model tagged as data rather than as an instruction; for media captions the screen runs but the tag does not travel with it yet.
- Token accounting — every model step is logged;
/usagereports it for free.
The Memory Tree
| Layer | What lives there | Path |
|---|---|---|
| 🍃 Leaves | the word-for-word transcript of each day, Iva's replies included | daily/YYYY-MM-DD.md |
| 🌿 Branches | summaries folded upward: day → week → month → year | summaries/daily/, weekly/, monthly/, yearly/ |
| 🪵 Trunk | CORE.md (≤1200 chars, in every prompt) + typed cards: contacts, projects, decisions, ideas, notes | CORE.md, cards/ |
- Every message lands verbatim in a daily markdown log — nothing is paraphrased on arrival.
- A nightly rollup at 04:00 distills day → week → month → year into schema-validated cards; facts that change get rewritten, not piled up.
- One core file,
CORE.md(≤1,200 chars), rides in every prompt — Iva knows you before it searches anything.
Full architecture and search internals: docs/memory.md.
A secretary inside Telegram
The bot is half of Telegram. The other half is your personal account: connect the userbot (beta, opt-in) and Iva works from it like a secretary — reads the group chats you never keep up with, folds them into summaries, catches the messages that actually need you, and replies as you.
- All of Telegram — groups, channels, unreads, search and the full history of your personal account.
- Onboarding in chat — tell the bot to connect your Telegram, scan a QR. No terminal.
- Anti-ban guardrail on the server — FloodWait compliance, a randomized delay after every send, and a circuit-breaker that pauses sending after three FloodWaits in 24 hours. It is enforced in the proxy rather than asked for in a prompt, and it wraps the three outbound calls that actually get accounts flagged: messages, files, forwards. Joins, invites, contact imports and reactions are not wrapped — those limits live in the skill file, which is a prompt.
- Read-only mode — one
.envswitch and Iva can read and search but physically cannot send.
Warning
Automating a personal account is against Telegram's ToS and can get the account limited or banned. The userbot is opt-in, beta, and used at your own risk — reading is far safer than sending. Details: docs/userbot.md.
Security & privacy
Web pages, search results, voice transcripts, captions and the vision model's description of a picture reach the model only through a prompt-injection sanitizer. On a forwarded text message the same gate annotates the turn with a warning instead of filtering the text, and document bodies, userbot-read chats and agent-browser output are not screened at all. Everything that leaves through the Outbox passes a secret-redaction gate, and the user allowlist fails closed — an empty list answers nobody. Your memory is a private git repo you own; the honest boundary is that the model and transcription are cloud APIs you choose and pay for. Gate internals and the full boundary: docs/security.md.
Install
One command on any Ubuntu/Debian box — a fresh VPS or your own machine:
curl -fsSL https://raw.githubusercontent.com/smixs/iva-agent/main/install.sh | bash
- Get a bot token from @BotFather.
- Run the installer and answer its questions.
- Message your bot. The wizard picks your Telegram ID out of that message, finishes setup, and Iva confirms right in the chat that it's live.
Brand-new VPS, still logged in as root? Run bash <(curl -fsSL https://raw.githubusercontent.com/smixs/iva-agent/main/bootstrap.sh) first: it creates your sudo user (with lingering enabled), updates the box, and turns on a firewall, fail2ban and SSH hardening. It asks three things — a login, its password, and the timezone — and no SSH key. Then log in as that user with that password and run the installer above. Details: docs/install.md.
Install as a normal user, not as root — Iva's shell tool runs as whoever installed it. Headless installs take --skip-setup or --non-interactive. Prefer to read before you run? Fetch it with curl -fsSL https://raw.githubusercontent.com/smixs/iva-agent/main/install.sh -o install.sh, read it, then bash install.sh. Wizard walkthrough and an SSH primer for first-time VPS owners: docs/install.md.
The first minute
Three messages, and you can watch the memory work:
- Send a voice note about your day — anything, out loud. Then look in
daily/inside your vault on the server: your words are sitting there in plain markdown, dated, yours. No other assistant hands you the file. - Tell it something a colleague would remember:
Marina at Acme wants the revised quote by Friday — she never picks up the phone. - Ask for it back the way a person would:
how should I follow up with Marina?— the answer comes from the card Iva just wrote, not from the last few messages.
Then send a photo of a business card, or forward a long post and ask for the gist. /menu has the rest; the full list is in 25+ scenarios.
Install from a clone — build it yourself
git clone https://github.com/smixs/iva-agent.git ~/iva
cd ~/iva && bash install.sh
The installer reuses the existing checkout instead of re-cloning, keeps .env and the vault untouched, and installs the same dependencies. A fork or a branch works through variables read at startup: REPO_URL=…, BRANCH=…, INSTALL_DIR=… (defaults: this repo, main, ~/iva). Details: docs/install.md.
Providers & cost
Five model providers. Pick one and fill its block in .env:
| Provider | How you pay |
|---|---|
| OpenCode Go | API key, ~$10/mo ($5 first month) |
| Ollama Cloud | API key, ~$20/mo |
| OpenRouter | API key, pay-as-you-go, 300+ models |
| OpenAI (ChatGPT) | your Plus/Pro subscription, no API key |
| Custom | your own OpenAI-compatible endpoint |
Default model is deepseek-v4-pro, 131k context. On Go it runs about $14–15/mo all-in ($10 model + $4–5 VPS; the model's first month is $5), no markup; voice rides Deepgram's free starter credit. Model lists, limits and the search matrix: docs/providers.md.
Documentation
Use cases · Install · Configuration · Memory · Providers · Security · Deploy · Commands & CLI · Menu · Reminders · Extending · Plugins · FAQ · Troubleshooting
Документация на русском → docs/ru/
What's New
v0.4.4 · 17.09.2026 — expand the latest releases
17.09.2026
v0.4.4
- ⏰ A reminder is an instruction Iva gives her future self: at the due minute the text of the reminder is the prompt of one fresh turn with tools, not a line to read back — "in 3 minutes find the news and send it" arrives as the news, not as its own wording. A turn that could not run, failed or came back empty still delivers: the code sends your text verbatim and names the cause in the row.
- ⏰ A reminder comes back to the chat it was asked in: the row remembers the chat and the topic of the turn, so a reminder set in a group topic lands in that topic instead of a private chat; old rows and requests that did not come from Telegram still go to the owner's chat.
iva doctorstopped claiming "the dispatcher has not ticked yet" — it was reading the pulse from the wrong folder. - 🔁
/update --forceworks from the chat too: the word after/updateis read now, so the running build can be rebuilt from Telegram exactly asiva update --forcedoes on the server — the way out of a broken edit in Iva's own code. The flag travels in the request file, so a restarted update rebuilds as well. - 🩺 The doctor names the cure for stuck workflows: "running count 7 exceeds 5" now says in the same line that such runs are stale rather than live, and that
iva resetquarantines them and restarts the services; memory is left alone.
14.09.2026
v0.4.3
- 🔁 One updater, the way pi does it: the old in-place update path (stash and rebase inside the working folder with a byte-level check of stray files, ~15k lines) is gone together with the guesswork "developer or installation" by branches and shims that kept people with a second branch on the fragile path forever. Every Iva folder now updates through versions: build beside, probe, switch, roll back. A developer checkout is marked with an empty
.iva-devfile. Edits to Iva's own code are no longer promised or kept — your own skills, tools and plugins live indata/custom.repair.shand a re-run ofinstall.shhand an existing installation to the same updater. An update cut off mid-way (a server reboot) is restarted once by the bridge itself with a line in the chat. Older flat installs need two/updates: the first fetches the new code, the second moves onto versions. - 🔘 Menu buttons two per row again: the classic menu lays buttons out in pairs as before 0.4.2; the new rich menu shows the same pairs as compact pills with a "button — what it does" caption under the row, no more one long full-width button.
- 🔌 A tool schema the provider rejects no longer kills the turn: OpenAI (codex) rejects the whole request when any tool carries a regex with lookaround; Iva now retries once without those patterns, and if it still fails, the error names the field and where the tool lives.
- 🧷 Codex tools without strict mode: tools go to codex with
strict: false, so optional fields stay optional and reminders are set on the first call instead of looping. - 🧰
diagnose.shcollects more: the plugin list, the reminder dispatcher pulse and the schedule lines of the last day.
13.09.2026
v0.4.2
- 🎤 The voice key is no longer required at install: the Deepgram step of the wizard is skipped with Enter (console.deepgram.com does not open from some countries, and people got stuck on install for an optional feature); without the key voice notes are saved and Iva suggests
/menu→ 🎤 Voice, andiva doctorshows a warning instead of a failure. - 🔘 A new menu, on request: buttons inside the message: by default the menu, the
/modeland/thinkwizards, the update offer and the "Working" status look as before (a message with buttons under it);/menu→ Maintenance → ✨ New menu switches them to Telegram rich messages — every button a full-width row with what it does right under it, headings, status and timers as tables, and ◀︎ Classic menu at the bottom brings the old look back. Iva also offers buttons in her own replies when there are two to four options, and a tap comes back to her as your message; therich-repliesskill covers the whole palette. The new menu needs a Telegram client from August 2026; in groups the reply buttons don't work. ADR-0015 - 💬 Rich replies and voice are set from the menu: two new
/menuscreens — a switch for rich replies (Auto: tables, task lists, folds and formulas go as rich messages;Plain text: ordinary messages) and🎤 Voicewith the Deepgram key and the recognition language (Auto/Русский/English/Oʻzbek); the key is taken from your next message in a private chat and deleted from the chat, and both screens offer a restart after saving. - 📦 Dependencies cleaned up: the unused
@vercel/connectis gone,fast-uri,honoandqsunder@modelcontextprotocol/sdkare bumped past their vulnerabilities (npm audit: 0 high, 0 moderate), and theaipin is lifted to^7.0.82, the peer eve 0.51.1 requires.
v0.4.1
- ⏰ A reminder is an instruction Iva gives her future self: a
data/row moves "pending → fired" in one atomic transition, and at the due minute the text of the reminder is the prompt of one fresh turn — Iva does what it says with her tools and the code sends the final text of that turn back to the chat and topic you asked in, so "in 3 minutes find the news and send it" arrives as the news, not as its own wording. A turn that could not run, failed or came back empty still delivers: the code sends your text verbatim and names the cause in the row. The firing fact (fired_at,delivered,error) sits in the row,iva doctorshows it, and rows from the old schema survive the update. - 🔔 One
remindtool withadd,list,remove: one-off reminders ("in 30 minutes", "at 14:30") and repeating ones (a cron expression in your time zone) are set, listed and removed by a single tool with anactionfield instead of three. The moment is computed in code and handed to the agent as a ready time, schedules firing more often than every 10 minutes are refused, and the destination is always your chat. ADR-0013 - 🛡
bashcannot set timers of its own or talk to Telegram anymore:systemd-run, writingcrontab,at/batch, units under~/.config/systemd/user,~/.iva-scripts,sleepchains and direct calls to api.telegram.org are refused before they run, and the refusal names the replacement; reading (crontab -l,systemctl status,journalctl) still passes. - 📋 Every schedule run leaves a fact, and the agent wakes up with it: each run writes a row to
data/jobs.json(reason, exit code, secret-free tail, kept seven days). On success Iva stays silent; on failure she fixes the cause and tells the owner, open failures are visible to every turn and iniva doctorand close on the next success or withiva jobs ack <name>, and if the agent cannot wake at all, one message a day reaches you. A wake turn that ended by waiting for the next message is a normal end now, not a failure. The schedules section ofiva doctorworks without systemd. - 🔎 A complaint turns into an evidence bundle with no secrets in it:
iva diagnoseputs versions, OS and node, theiva doctoroutput, the last 200 service log lines, reminder and turn-failure facts and the schedule table intodata/diagnose/<date>.md, cutting the values of every.envkey except settings, plus the bot token, owner chat id and e-mail; thereport-problemskill reads the bundle, explains the failure in two lines and offers a ready issue link or a message for the support group. - 🧹 An interrupted update cleans up after itself and names the reason: the retiring checkout wears a marker with its own identity, deletes
.gitlast and finishes on a repeat; stale shim-refresh claims in~/.local/binare swept by age even under a live pid; a failed optional step now logs its exit code and the last output line (for exampleexit 127: uv: command not found) instead of a silent "… did not run". - 🧩 Your rules live beside the bundled persona and load every turn: markdown files in
data/custom/agent/instructions/reach the prompt live without a rebuild, so a behavior rule written intorules.md(withwrite_file, after your confirmation) works at once; the oldinstructions.mdreplacement is obsolete, andiva doctorshows the rule count and warns when it overruns the limit. - 🧭 The vault directory is computed by one formula everywhere: file tools, media, the diary, nightly memory, the CLI, the menu, the build and the installer call a single resolver. An empty value or stray spaces is now a clear error naming the variable instead of a silent directory swap, a relative path resolves against the caller's base, and a bad setting reaches the user as one line, not a stack trace.
- 🧩 Iva runs on eve 0.51.1 (0.4.0 shipped 0.47.3): the local patch is ported and rebuilt for the new runtime.
Full history — CHANGELOG.md.
Built on
eve 0.51.1, Vercel's agent framework, runs the agent; Node 24's built-in SQLite runs the search index — no separate database. Iva grew out of agent-second-brain and autograph — that story is in docs/memory.md.
Thanks
Iva gets better because people run it for real — contributors are welcome. Open an issue with what breaks, or send a PR. Everyone who already helped: docs/thanks.md.
License
MIT — take it, change it, run it on a hundred servers; just don't blame anyone if something breaks.