Projects

Monday — An AI-Assisted Life Operating System

Featured — In development

Monday — An AI-Assisted Life Operating System

Monday is a personal AI operating system you can text. It combines conversation, long-term memory, planning, safe action, and accountability so that everyday intent turns into concrete next steps. Its defining property is continuity: every new message can reference your goals, commitments, and prior context, then produce a plan or take an action.

What it does

  • Conversation — SMS / chat-style input.
  • Long-term memory — what you have shared and what you care about, retrievable across sessions.
  • Planning — turning vague intent into structured next steps.
  • Action — calling tools (Calendar, Notion, GitHub) safely, with confirmation when needed.
  • Accountability — reminders, follow-ups, and inactivity detection.

Technical stack

  • Python — orchestrator, tools, and the agent pipeline.
  • AWS — API Gateway (webhooks), Lambda (receiver + orchestrator), SQS (async work queue), EventBridge Scheduler (routines), RDS Postgres (system of record), pgvector (semantic memory), KMS + Secrets Manager (encryption).
  • Terraform — infrastructure as code.
  • Integrations — Twilio (SMS), Google Calendar, Notion, GitHub.

Architecture — orchestrator

The orchestrator runs a fixed, gated pipeline over shared RunState: a Coordinator classifies intent and routes; a Planner drafts a structured plan; a Coach shapes it into an executable day; an Executor runs tools (confirm-first for sensitive actions); and a Memory Curator decides what to persist.

flowchart TD U[User via SMS] --> W[Webhook Receiver] W --> Q1[SQS enqueue] Q1 --> O0[Orchestrator entry] O0 --> LOAD[(Load user state)] O0 --> EMB[Embed inbound message] EMB --> VQ[(memory vector search)] VQ --> COORD[Coordinator: intent and route] LOAD --> COORD COORD -->|answer only| RESP0[Responder] COORD -->|plan or act| PLAN[Planner] COORD -->|confirmation reply| CONFH[Confirmation handler] PLAN --> COACH[Coach: prioritize and pace] COACH --> NEEDCONF{Tool action needed?} NEEDCONF -->|no| MEMCUR[Memory Curator] NEEDCONF -->|yes| CONFREQ{Requires confirmation?} CONFREQ -->|yes| PAWRITE[(pending_actions insert)] CONFREQ -->|no| EXEC[Executor: call tools] EXEC --> AUD[(audit_log)] EXEC --> MEMCUR MEMCUR --> OUT[(messages outbound)] RESP0 --> OUT OUT --> SEND[Send response]

Safety: confirm-first execution

Actions that touch the outside world (create a calendar event, write to Notion) are never executed inline. Monday proposes the action, stores it in a pending_actions table, and asks the user to confirm. Only an explicit "YES" causes the Executor to run the tool — an approved action executes exactly as approved, never reinterpreted.

Modeling relationships — a household knowledge graph

Monday keeps a lightweight knowledge graph in Postgres rather than a dedicated graph database. People are modeled as entities (auto-created per member, and non-members are supported — a grandparent needs no account). Relationships are typed edges stored in both directions, guarded by an inverse-relation allowlist, and a document's subject (who it is about) is kept separate from its owner (who it belongs to).

Reference resolution walks this graph deterministically: "my mom's medication list" follows a parent-of edge to that person's entity, then to documents about them. Resolution proceeds in order — self-words, declared graph, role heuristics, aliases, name match — and any ambiguity asks a clarifying question instead of guessing. Identity is never fuzzy: who "my husband" is resolves relationally through the graph, never by embedding similarity. Edge tables in SQL comfortably cover the one- to two-hop traversals a family needs with plain joins.

The graph also learns from conversation: the Curator proposes entity and relationship writes, and deterministic code validates them against the relation allowlist before persisting — the model extracts, code decides what is admissible. Saying "we call Lisa grandma" once makes "grandma's medication list" resolvable afterward.

Memory ingestion

Memory writes are deduplicated on ingest rather than blindly appended. A new memory is compared by cosine similarity to existing same-type memories: very high similarity reinforces the existing row (bumping confidence and recency), moderate similarity supersedes it (keeping the old row with a superseded-by pointer for lineage), and otherwise it inserts. A single pure decision function is shared by the database implementation and the test fakes so the semantics cannot drift.

Document ingestion treats extraction as a proposal, not truth: uploaded PDFs and photos are transcribed (a parser or a vision model), and the extracted text is what gets chunked and embedded while the original file stays canonical. If extraction fails, the document is stored unindexed and can be re-extracted later when models improve.

Embedding & retrieving documents for a household

Documents are chunked and embedded into pgvector columns, and retrieval runs cosine similarity over a relationally pre-filtered set of ids — a "relational fence." The permission and subject filters are built first in SQL, then vector ranking happens only within that allowed set, so semantic search can never widen access. A few practical choices follow from family scale: an exact scan beats ANN indexes at these row counts (index only when measurement says so); the embedding dimension is a contract with the model, so changing models means re-embedding; and canonical resolution runs before search, so "the medication list" narrows to the right document instead of blending with the whole corpus.

Multi-tenancy is principal-based: one principal per (user, household), so household isolation falls out of the model. Invisible resources return 404 rather than 403 to avoid leaking their existence, and sensitive vault items are never embedded or chunked at all.

Data model

erDiagram users ||--o{ conversations : has conversations ||--o{ messages : contains users ||--o{ tasks : owns users ||--o{ commitments : has users ||--o{ events : has users ||--o{ connections : has users ||--o{ pending_actions : has users ||--o{ memory_items : has users ||--o{ audit_log : has

Key tables: messages (append-only dialogue), tasks and commitments (the execution and accountability backbone), pending_actions (the safety gate), memory_items (pgvector semantic memory), connections (encrypted OAuth tokens), and audit_log (traceability for every tool call).

Design principles

  • Model proposes, code grounds. The LLM never carries identifiers or authority; real ids are injected from resolved context.
  • Deterministic executor. No model call in the execution path.
  • Graceful degradation. Every model-backed agent has a keyword fallback.
  • Auditability over autonomy. A fixed, gated pipeline beats a free-running loop for a product with a bounded intent space.