Your commitments don't live in one place. A deadline is set in a meeting, moved in an email a week later, and a family plan is agreed in a group chat while all that happens. Things slip because nothing tracks the promises across all of those sources.
A chatbot doesn't solve this. You paste one document, get a summary, and it forgets. Meeting tools like Otter, Fireflies and Granola only see calls. Neither will tell you that Tuesday's email quietly moved the deadline you agreed on Friday.
Feed it the text you already have: emails, meeting notes, auto-generated transcripts, Slack threads, family group chats, voice-memo brain dumps, or PDF and Word files. It keeps one ledger of commitments across all of them:
| Feature | Why it matters | |
|---|---|---|
| 📌 | I owe / Owed to me / Others | Tell it who you are once, and every item is sorted by who owes what to whom. |
| 🔁 | Cross-document change detection | When a newer document moves a deadline, reassigns work or cancels something, you get a proposal with the reason, to accept or ignore, and you can undo either. Nothing is edited silently. |
| ✅ | Verified sources | Every commitment keeps the exact sentence it came from. The app checks that quote against the original, word for word, and flags any that don't match. |
| ✏️ | You stay in charge | If the AI gets an owner or date wrong, fix it with ✏️ Edit. Every correction is kept in the item's history. |
| 📅 | Real dates | "By Friday", "next Tuesday" and "tomorrow" become real dates based on when each document was written. Anything vague stays marked as undated, never guessed. |
| ☀️ | Morning brief | What's overdue, due today and due this week, and who you're waiting on, in one screen. |
| ✉️ | Act on it | Draft follow-up messages per person, export dated items to your calendar (.ics), or download a checklist. |
| 💬 | Ask across everything | "What did I promise Rachel?" Answers come only from your documents, and newer documents win when they disagree. |
No API key needed: click ▶ Load the 3-document demo to explore results saved from a real Nemotron run. With a key, the same button runs the demo live (about a minute with reasoning on). It plays one week in the life of Grace, a product lead:
- Tue Sep 15: kickoff email. Hamid owes the onboarding flow by Oct 9, and offline sync is "definitely in".
- Mon Sep 21: family group chat planning Grandma's 80th. Grace calls the caterer, and Dad orders the cake.
- Tue Sep 22: an email that changes the plan.
Open 🔁 Changes and the app flags the plan changes: Hamid's deadline moved Oct 9 → Oct 6, offline sync was cut, Apple Watch moved to v3.1. Each one is shown with its source quote, for you to accept or ignore. ☀️ Today then shows Grace's work and family commitments together.
Any text ┌──────────────────────────── Nebius Token Factory ─────────────────────────────┐
(email, chat, ──▶ │ 1. Extract JSON-schema output: task, owner, requester, real due date, │
transcript, │ status, change note, exact source quote │
PDF, DOCX) │ 2. Match compare only against commitments with the same owner or similar │
│ wording → same / update / cancelled / none │
│ 3. Write streamed briefing, morning brief, follow-ups, grounded Q&A │
└──────────────────────────── NVIDIA Nemotron (default) ─────────────────────────┘
│
┌───────────────────────────────────────────▼──────────────────────────────────────┐
│ Plain Python (deterministic, unit-tested) │
│ quote verification · who-owes-whom · overdue maths · proposals · calendar export │
└────────────────────────────────────────────────────────────────────────────────────┘
- The model extracts and compares; plain Python decides. Quote checks, date maths, the Mine / Owed / Others split and the morning brief are ordinary code, so they're predictable and tested.
- Structured output: Nebius JSON-schema mode where the model supports it, with automatic fallback to JSON mode.
- Speed: extraction runs in the background while the briefing streams in. Every answer shows its latency and token count.
- Long documents are split into chunks and nothing is dropped. Briefings of long documents summarise each part first, then combine the notes.
- Models: the sidebar lists the chat models Nebius serves right now, with NVIDIA Nemotron 3 Super first. Reasoning traces are removed before display.
- Works on phones: the layout adapts to narrow screens (a 3×2 grid of stat cards, compact cards).
evals/run_evals.py runs the real pipeline on the sample documents and scores it against hand-written expectations in evals/cases.json, for example "Hamid's onboarding is due Oct 6, not the old Oct 9", "'by Friday' from a Tuesday is Sep 25", "offline sync must not stay open", and "don't claim Hannah approved a logo". It also reports source grounding: the share of extracted items whose quote appears word for word in the document.
python -m evals.run_evals --runs 3 # reasoning on
python -m evals.run_evals --runs 3 --fast # Fast mode (reasoning off)NVIDIA Nemotron 3 Super on Nebius, 3 runs per mode (Sep 24, 2026):
| Mode | Checks passed (avg) | Range | Quotes found word for word | Time per run |
|---|---|---|---|---|
| Reasoning on (default) | 32.7 / 34 (96%) | 32–33 | 122/125 (98%) | ~4 min |
| Fast mode | 29.3 / 34 (86%) | 27–31 | 103/110 (94%) | ~0.7 min |
Reasoning is worth the wait where documents have to be compared: in Fast mode the model missed a reassigned task, a deadline moved earlier and a task marked done in the voice memo → email chain, and misread "Friday the 23rd" in the family chat. The one check reasoning mode still misses is ambiguous in the text itself ("maybe Wei can scope it" is later dropped). That voice memo → email chain is a second set of documents the prompts were never tuned on. Full reports: evals/RESULTS.md and evals/RESULTS_fast.md. Model outputs vary between runs, which is why we report averages.
python -m scripts.live_check checks the writing features against the live model: the morning brief, a follow-up draft (it must use the latest plan, not a cancelled task or an old date) and Ask across documents. Latest run: 5/5.
The core logic has 36 offline tests (pytest), including UI tests that click through the real Streamlit app with a stand-in for the model.
- Runs on open-weight models through Nebius Token Factory. Your documents aren't stored in a consumer chatbot's history.
- On a shared deployment, each visitor's workspace lives only in their own browser session. Use Export workspace to keep it.
- Running locally, you can set
WORKSPACE_FILEto save your workspace to a local JSON file. - Because the endpoint is OpenAI-compatible, you can point it at a model you host yourself.
Prerequisites: Python 3.10+ and a Nebius Token Factory API key (tokenfactory.nebius.com).
git clone https://github.com/<your-username>/open-loops.git
cd open-loops
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env # Windows: copy .env.example .env — then add your key
streamlit run app.pyRun the tests with pip install -r requirements-dev.txt and then pytest.
- Push this repo to GitHub.
- At share.streamlit.io, click Create app and pick the repo, with
app.pyas the entry point. - (Optional) Under Advanced settings → Secrets, add
NEBIUS_API_KEY = "..."(the quotes are required) so visitors can use it without their own key. The key stays on the server and is never sent to the browser. - Don't set
WORKSPACE_FILEon a public deployment.
Protecting your credits. When visitors use the app's own key, each one gets a limited number of AI actions per session (analyzing a document, a morning brief, a follow-up draft, a question), there is a daily cap across all visitors, and very long documents are refused. Visitors who paste their own key have no limits. Tune the limits with these optional secrets:
| Secret | Default | Meaning |
|---|---|---|
MAX_AI_ACTIONS_PER_SESSION |
15 |
AI actions per visitor session on the app's key |
MAX_AI_ACTIONS_PER_DAY |
300 |
AI actions per day across all visitors on the app's key |
MAX_DOC_CHARS |
40000 |
Longest document accepted on the app's key |
app.py Streamlit UI (Add · Today · Commitments · Changes · Ask · Documents)
core/
llm.py Nebius client, model discovery, streaming, JSON-schema output
extract.py commitment extraction, quote verification, who-owes-whom
changes.py cross-document matching → proposals
workspace.py ledger data model, proposals, persistence
brief.py morning brief (deterministic)
writer.py model inputs for briefings, Q&A, follow-ups
ingest.py .txt/.md/.pdf/.docx reading, date guessing, chunking
calendar.py .ics export
prompts.py prompts
samples/ 10 messy real-world documents, demo story (catalog.json),
saved demo results (demo_workspace.json)
scripts/ build_demo.py (regenerate saved demo) · live_check.py (live feature check)
make_demo_gif.py (records assets/demo.gif; needs `pip install playwright`)
assets/ demo.gif
evals/ scored evaluation against hand-written expectations
tests/ offline unit + UI tests (fake model)
- Connect directly to Gmail, Slack and calendars, instead of pasting text in
- Voice-memo upload with speech-to-text
- Reminders pushed to your phone when something you're waiting on goes overdue
MIT. See LICENSE.
