Inspiration

Somnora came from wanting to point AI at a novel problem, not just make an existing problem easier to solve. The belief underneath it: the ability to understand yourself, and to feel understood, should not be a gatekept luxury.

The concept was forged while I was a press videographer in an active conflict zone. In that kind of volatile, high-stress environment, I needed a psychological sounding board, something to keep me grounded and help me unpack the hyper-vivid dreams I kept having. I did not want a boilerplate therapist-bot handing me canned behavioral checklists. I wanted a companion with an unapologetic, witty, deeply human personality; one that means well and genuinely entertains, but refuses to preach.

When I started with Codex last July, it felt like a caveman pasting blocks of code into a terminal. After the early prototype earned a spot in Google for Startups, that experiment matured into a full multi-agent build pipeline. The sprint has cost me plenty of my own sleep, but the infrastructure we built is meant to give our users theirs back.


What it does

Somnora is an agentic wellness companion that turns subconscious raw material and spontaneous cognitive overflow into structured insight, behavioral patterns, and emotional clarity.

  • Daily Journal — an interactive diary where users process daily events and emotional states in live conversation with Nora.
  • Multi-modal ingestion — captures sleep profiles plus audio or text entries during the fragile waking window.
  • Eureka Mode (the Apple Watch stream) — for the raw thoughts caught away from a screen. Record an idea to your watch in the shower; by the time you dry off, an asynchronous queue has delivered it to Nora, who interrogates it, extracts the hidden links, and compiles an actionable report ready to export into a development environment.
  • Dreamcatcher — an isolated visualization microservice that turns dream narratives into vivid, surrealist imagery.
  • Reflection Ledger — a range-bounded curiosity engine that cross-references emotional states against real HealthKit sleep cycles to surface long-term recurring themes.

How we built it

The client is native Swift for iOS and watchOS, built on a thread-isolated, actor-based architecture so the UI never stutters; local persistence is decoupled from the main thread via a dedicated FileStorageRepository actor handling all sandbox file I/O.

The heart of the product is Nora's memory, and that is where OpenAI did the heavy lifting. We built Somnora's RAG memory system inside Codex, driving the build with GPT-5.6 Sol, Terra, and Luna — routing the hardest architectural reasoning to the top tier and delegating mechanical refactors and test scaffolding to the faster ones. Codex did not just autocomplete; it designed and implemented the pipeline that decides what Nora remembers, how she consolidates it, and how she keeps it clean. Memory runs in three stages: formation, synthesis, and linting.

Formation. Every conversational turn yields candidate memories, each scored for salience before it is allowed to persist:

$$ s(c) = \sigma!\left( \beta_0 + \beta_1\,\text{emo}(c) + \beta_2\,\text{spec}(c) + \beta_3\,\text{recur}(c) \right) $$

where \( \text{emo} \), \( \text{spec} \), and \( \text{recur} \) capture emotional charge, specificity, and recurrence. Only candidates above threshold survive.

Synthesis. A memory's salience decays over time but is reinforced whenever its theme resurfaces, so durable patterns rise and one-off noise fades:

$$ s_t = s_0\,e^{-\lambda (t - t_0)} + \sum_{r \in R} \rho\, e^{-\lambda (t - t_r)} $$

At prompt-construction time, Nora ranks memories by blending semantic similarity, salience, and recency:

$$ \text{score}(m,q) = \alpha\cos(\mathbf{e}_m,\mathbf{e}_q) + \gamma\, s(m) + \delta\, e^{-\lambda \Delta t_m} $$

then packs the highest-value set that fits a fixed token budget — a 0/1 knapsack over the memory pool, where \( \tau(m) \) is a memory's token cost and \( B \) the packet budget:

$$ \max \sum_i x_i\,\text{score}(m_i) \quad \text{s.t.} \quad \sum_i x_i\,\tau(m_i) \le B, \quad x_i \in {0,1} $$

Inference streams through a serverless gateway (somnora-proxy) fronted by a dynamic router that selects a target model node \( M_i \) from prompt complexity \( C \) and a latency budget:

$$ M_i = \arg\min_{m} \left( \omega_1\,\text{Cost}(m) + \omega_2\,\text{Latency}(m) \right) \quad \text{s.t.} \quad C \le \text{ContextLimit}(m) $$

To pressure-test Nora's persona, we ran an automated swarm of Codex-powered OpenClaw agents through hundreds of parallel, adversarial conversations designed to break her tone, then tuned her from the metrics. Fittingly, half of our feature ideas were brainstormed inside Somnora's own Eureka mode — we used the platform to expand the platform.


Challenges we ran into

Teaching Nora to remember. The hardest problem was not storing text; it was deciding what deserves to become a memory, how to fuse it with what she already knows, and how to stop the pool from rotting — the three stages Codex built. Formation had to reject conversational filler without discarding the quiet, load-bearing detail (the 4am wake, the clenched jaw). Synthesis had to reconcile schema drift across deployments, so we built memoryReaderPrecedence.js to merge and deduplicate legacy profiles with our durable RAG collections live during prompt construction. And linting had to bound growth: unbounded, every nightly consolidation appended forever. Near-duplicates are merged above a similarity threshold,

$$ \text{merge}(m_i, m_j) \iff \cos(\mathbf{e}{m_i}, \mathbf{e}{m_j}) \ge \theta_{\text{dup}} $$

and each memory class is capped to the freshest \( N \) by reinforcement-recency:

$$ \mathcal{M}' = \underset{m \in \mathcal{M}}{\text{top-}N}\ \max!\big(t^{\text{reinf}}_m,\ t^{\text{created}}_m\big) $$

Identity consistency in Dream Cards. When a generated card depicts the user, it must reflect their actual demographics rather than the model's default guess. We blend the user's demographic anchor \( \mathbf{U} \) with Nora's contextual interpretation vectors \( \mathbf{E}_{\text{nora}} \):

$$ \mathbf{I}{\text{card}} = \sigma!\left( \mathbf{U}{\text{demographics}} + \sum_{k=1}^{n} w_k\,\mathbf{E}_{\text{nora}}(k) \right) $$

Context isolation for Dreamcatcher. We had to constrain the image model to the dream itself, filtering out unrelated conversational filler so tangential chat topics never leaked into the generation prompt.

The privacy realignment. Early designs claimed the app was entirely on-device, but running deep linguistic models requires cloud egress. We overhauled our privacy compliance and in-app copy to be radically transparent: health biometrics stay strictly isolated on-device, while conversational text is encrypted and processed through our private API proxy.

Defeating feature overloading. Because we brainstormed expansion inside Eureka, the platform over-featurized fast and the layout cluttered. We resolved the anxiety by restructuring the UI into a modular, widgetized framework.


Accomplishments that we're proud of

We made self-reflection stop feeling like work. By treating a user's thoughts with genuine curiosity instead of cold, clinical judgment, we built something people actually look forward to opening to discover their own cognitive patterns — and we gave it a distinct, uncompromised personality that does not try too hard to be safe or devoid of human characteristics.


What we learned

Building a product that is not quite possible until tomorrow means solving problems that do not exist yet. At the edge of agentic AI, model capabilities and API architectures shift under your feet mid-sprint; you cannot build for current-generation constraints, you have to predictively engineer for the next leap. That pushed us from reactive debugging toward flexible, highly decoupled scaffolding that can absorb sudden jumps in LLM intelligence without breaking the user experience.

Working through Codex and GPT-5.6 also showed us that agentic systems have no guidebook — what you get out depends entirely on the intention, structure, and trust you put in. The models were capable enough that our real job became specification and judgment, not syntax.


What's next for Somnora

  • Ecosystem expansion (Android & Wear OS). Porting the app to Android and Eureka Mode natively to the Samsung Galaxy Watch — rebuilding background listener routines in Kotlin and Jetpack Compose and mapping our asynchronous telemetry queues to Health Connect for parity across watchOS and Wear OS.
  • Portable memory via MCP (next-stage proof of concept). We are using Codex to build an MCP bridge to Obsidian, so users who choose to take their data outside our ecosystem can let their own desktop LLMs keep their personal progress organized and current — memory that belongs to the user, not the app.
  • Modular interface customization. With the widgetized architecture, users will be able to paint their own layouts, pulling specialized tracker modules from a feature store so the app stays uncluttered while feeling completely their own.

Built With

Share this project:

Updates