Inspiration

Reminder apps store "what" you decided. None of them store "why" - so none of them can tell you when the "why" stops being true. The seed case: you tell your assistant "I'm visiting my parents Saturday, since my presentation is Friday. Remind me to book a train Friday evening." Three days later the presentation moves. A calendar app says nothing; it only knows about the appointment, not that your weekend plan depended on it. We wanted an assistant that notices, explains itself with your own words, and lets you decide what happens next - without silently editing anything or pretending to certainty it doesn't have.

What it does

You tell Continuum a decision and why, in your own words. It drafts the decision, its assumptions and any commitments, each tied to the exact quote it came from, and shows you the draft before saving anything. Underneath, that's not a flat reminder - it's a dependency graph: a commitment depends on a decision, which depends on an assumption, each backed by evidence.

When something that decision depended on changes - a presentation moves, an appointment's status shifts - Continuum checks it against a deterministic policy, not a guess: a verified change that actually breaks your plan's order opens a review, citing the original quote next to the new one; a change that doesn't break the order (the presentation moving to an earlier day that's still before your trip) raises nothing; anything the engine can't verify only asks you to confirm, never asserting more certainty than it has. You decide what happens next - dismiss it with a reason, or revise the decision into a new version that keeps the old reasoning and the new one both visible. Ask "why did I change this?" and it rebuilds a cited timeline from stored facts, never from guesswork.

It's built as an Alexa+-style simulated voice assistant (a real web client, not a deployed Alexa+ skill), backed by a real Model Context Protocol server over Streamable HTTP - the same tools an MCP-aware host would call are independently callable by MCP Inspector and our own separate client, both proven live against the public endpoint.

How we built it

Two people, two surfaces, one frozen contract, built in parallel for a week:

  • The engine (Dhyey): FastAPI + PostgreSQL + SQLAlchemy/Alembic. A real MCP server over Streamable HTTP, exposing eight continuum.* tools that call the exact same service functions as the REST routes, so MCP and REST can never drift apart. A deterministic contradiction policy: a verified date change that breaks a plan's order challenges the assumption and opens a review; one that keeps the order raises nothing; anything unverifiable only asks the user to confirm. Amazon Bedrock (Converse API, forced tool use) drafts a structured decision from the user's own words, and every quote and date it returns is re-checked against the user's exact text in code before anything is shown or saved - the model proposes, deterministic code decides what's trustworthy. Owner-scoped everywhere, rate-limited, size-capped, with security headers and a chaos-tested failure path. Deployed to a real AWS EC2 instance behind Caddy and Let's Encrypt, with Bedrock reached through a least-privilege IAM instance role and no static keys on the host.
  • The web client (Ancy): Next.js 16, TypeScript, Tailwind, React Flow for the dependency graph. A typed client generated from the same OpenAPI contract the engine publishes. Server Components read the engine live for every list, detail and graph page, so there's no fabricated data when the engine is unreachable - by construction, not by discipline. An independent TypeScript MCP client calls the real MCP server directly from a visible trace panel, deliberately separate from the REST product flow, to prove the tool invocation is real. A 20-case labeled evaluation dataset - half of the project's 40 - scored against the real running engine, not mocks.
  • Both: a daily pull-review-build rhythm against the shared contract, and each the other's reviewer before a merge touched their area. When the release candidate needed the whole demo journey working end to end, Dhyey built it (Demo Controls and the browser integration suite) inside Ancy's area of the app, and asked for her review before it counted as done - and she independently re-ran his half of the evaluation dataset, including standing up a second engine instance herself to verify the cross-account isolation case, before signing off.

Challenges we ran into

  • A live-model quirk, caught by our own grounding code, not trust in the model. Once Bedrock access actually worked, the live model sometimes stated a dependency ("since my presentation is Friday") without quoting it as a reason the way our grounding expected, so a real conflict raised nothing. The fix lived in grounding: treat an assumption quoted inside a stated reason as a stated dependency, whatever the model's own edge annotation says - not in trusting the model's judgment more.
  • A new AWS account's first region didn't match our docs. US West was unavailable on the free plan; the account was pinned to US East (Ohio). Several model profiles the console listed as "ACTIVE" were still access-denied when actually called. We built a one-token probe call to find a model that was genuinely callable, not just listed.
  • A stale-timestamp bug in our own evaluation harness, not the engine. Reusing one timestamp across a 20-case run made a later case's correction event look older than evidence captured only moments before it, in real wall-clock time - and the engine correctly refused to let it override more recent evidence. Fixed by timing each case independently, and written up honestly in our docs rather than quietly adjusted until it passed.
  • A CSS cascade-layers bug that looked like it should be impossible. A leftover boilerplate rule for dark-mode colors sat outside Tailwind's CSS layers, which made it silently win over explicit Tailwind text and background classes regardless of specificity - invisible text on a dark-mode browser, found only once we actually looked at the rendered app instead of trusting that explicit classes always win.
  • Two people, one shared database, forty vocabulary-sharing test cases. A demo account that had accumulated a week of manual testing meant some evaluation cases spuriously matched other decisions' assumptions over shared words like "presentation" or "car." Scoring each case strictly from its own decision's own alerts, instead of the triggering event's account-wide impact field, fixed it - and is the more correct methodology regardless of test-data hygiene.

Accomplishments that we're proud of

  • A real Model Context Protocol server, independently verified by a tool we didn't write (MCP Inspector) and a second client we built ourselves in a different language - not a REST endpoint with "/mcp" in the name, and now reachable over real public HTTPS, not just localhost.
  • Live Amazon Bedrock extraction that's actually reliable: 15 out of 15 drafts valid on the first attempt, with all 95 quoted spans exact matches of the user's own words.
  • A 40-case labeled evaluation benchmark we designed, built and cross-verified ourselves - including an instruction-injection case, a cross-account isolation case, and the master scenario's own negative case (a change that must not raise a false alert) - scoring 40/40, independently re-run by each of us against the real running engine.
  • A contradiction policy that's deterministic and explainable, not a vector-search guess: it correctly tells "the presentation moved to Saturday, your Saturday trip is affected" from "the presentation moved to Thursday, your Saturday trip isn't" every single time, because it's a graph traversal and a template, not a prompt we hoped would generalize.
  • Two real accounts, on purpose, each tried every read and write on the other's records and failed correctly every time; a database failure injected mid-write leaves nothing behind.
  • Shipping a release candidate we could both run clean from a fresh clone, as a two-person team, in a little under two weeks - with a real work log and friction log kept honestly the whole way, including the bugs we found in our own code, not just the libraries'.

What we learned

  • A deterministic, template-explained contradiction policy beats a vector-search chat answer for this problem. Judging "does this change actually matter" needs a real dependency graph and a real policy - verified versus possible change, order-preserving moves, reverts - not similarity search over embeddings. We built it as code we could unit-test against 40 labeled cases, not a prompt we hoped would generalize.
  • Grounding has to happen in code, not in the model. Every quote Bedrock's Claude Sonnet returns is checked against the user's actual text before it becomes an evidence span; a reason without a real quote is dropped, not kept on faith. That single rule is what caught the live-model quirk above before it ever reached a user.
  • A frozen contract - OpenAPI plus JSON Schema - is what let two people build a full-stack app in a week without blocking each other. The frontend was built against fixtures the day the schema was published, a full day before the real extraction endpoint existed, and needed zero changes when the real endpoint landed.
  • MCP and REST calling the exact same service functions, not two parallel implementations, is what makes "a real tool invocation through MCP" actually true instead of theater. We proved it with two independent clients - MCP Inspector, written by someone else, in another language, and our own TypeScript client - both calling the same running server with no server-side changes for either.

What's next for Continuum AI - The Assistant That Remembers Why- A publicly hosted web client, so anyone can click through the actual UI instead of only watching the demo video or cloning the repo.

  • A larger live Bedrock extraction benchmark than the first live sample, now that account access and model selection are solved problems.
  • A real usability study beyond the two of us building it.
  • Archive and delete in the frontend - the engine already supports both; only the UI is missing.
  • Per-user OAuth instead of one shared demo token, and a real calendar connector instead of synthetic change events, so the "Friday became Saturday" moment can happen on its own.

Built With

Share this project:

Updates

Submission history