TripleNoodle — Technical Architecture Overview
A high-level engineering overview of a production AI product I designed and built. Written for technical conversations (interviews, portfolio review) — architecture and engineering practice, not product marketing or business detail.
What It Is
TripleNoodle is a consumer web application that configures a dedicated, persistent AI assistant ("Super Who") for each user's specific goal — not a generic chatbot, but a purpose-built AI participant scoped to one person's real, hard, ongoing objective (a career transition, a health goal, a project). Each assistant is produced by a structured configuration pipeline rather than a single prompt, is verified before it ever talks to a user, and is continuously monitored and correctable in production.
The interesting engineering problem isn't "call an LLM API" — it's building the surrounding system that makes a dynamically-configured AI behavior safe, correctable, and trustworthy to run at scale for real people, on real personal problems, over months of sustained use.
System Architecture
| Layer | Technology | Why |
|---|---|---|
| Backend | ASP.NET Core (C#) | Full control over multi-step orchestration; strong typing for a system with many interacting pipelines and state machines |
| Database | PostgreSQL | Relational integrity for provenance/audit trails; native Row-Level Security for tenant
isolation; pgvector extension for retrieval |
| Background processing | Hangfire (Postgres-backed) | Scheduled and event-driven jobs — document generation/extraction, retrieval indexing, audit sampling, usage-cap resets |
| Real-time | SignalR (WebSockets) | Multi-participant live conversation, sub-2-second cross-client message visibility |
| LLM providers | Anthropic Claude (primary reasoning/generation), OpenAI (embeddings) | Deliberately multi-vendor at the seams that matter (embeddings vs. generation), never locked to one provider's SDK |
| Frontend | Svelte / TypeScript | Lightweight, no heavy framework overhead for a focused UI surface |
| Hosting | Railway (managed Postgres, object storage, deploys from git) | Affordable at current scale; portable — no vendor-specific architecture lock-in |
| Auth | Passwordless magic-link + short-lived JWT | No password store to breach; stateless access tokens, revocable refresh tokens |
Core Architecture Patterns
1. A configuration pipeline, not a prompt
Each AI assistant is produced through a staged pipeline: a structured interview extracts the user's actual goal and constraints → a synthesis stage drafts one or more candidate configurations → each candidate is independently reviewed against both general-quality and domain-specific correctness criteria → only a configuration that passes review is ever deployed. Nothing goes live off a single generation. This exists because natural-language configuration is inherently variable-quality, and a plausible-sounding-but-wrong configuration is worse than an honest failure — it fails silently at the output layer, not at creation.
2. A layered behavioral-safety model
Every deployed assistant runs against a two-tier behavioral contract: a non-negotiable base layer (honesty, no fabrication, scope discipline in high-risk domains, safety-critical halts) that no per-assistant configuration can override, plus a per-assistant layer that governs tone, delivery register, and domain specialization. The base layer is verified as part of the same pre-deploy gate every configuration goes through, so a safety property is never something an individual configuration has to "remember" to include.
3. A separate, architecturally-independent supervising process
Alongside the user-facing assistant, a second process (never the same conversational context) watches for signals that the assistant might no longer be the right fit for the user's actual situation — drift in the user's stated goal, an unusually high-stakes action about to be taken for the first time, extended inactivity — and intervenes procedurally when warranted. This process cannot be asked by a user to explain itself away, because it isn't the same LLM context being asked to judge its own output — a structural answer to the "can a model reliably supervise itself" problem, rather than a prompted one.
4. Retrieval-augmented knowledge, with correction built in
User-uploaded and user-authored content is indexed and retrieved via a standard RAG pipeline (chunking → embedding → similarity search), but retrieval quality is treated as a first-class concern rather than assumed: a relevance-grading pass filters out low-quality matches before they ever reach a response, and a second pass checks the drafted response itself against the retrieved material and can trigger one bounded regeneration if the answer isn't actually supported by what was retrieved. Both grading stages sit behind a swappable interface so the underlying judge model can be changed independently of the generation model.
5. Long-conversation continuity without relying on the model's own context handling
Rather than letting a long-running conversation simply grow until it hits a context-window limit (or relying on generic, model-level context compaction), the system maintains its own three-tier memory structure: frequent lightweight checkpoints of what's happened, rare full "handoff" events that reset the live working context while preserving continuity of relationship and state, and a suppression mechanism that avoids resetting context at an emotionally sensitive moment in the conversation. This is a deliberately engineered alternative to "hope the platform's default context management is good enough" for a product whose whole premise is sustained, multi-month engagement. The suppression mechanism specifically reflects a design judgment that context-management decisions have emotional timing, not just technical timing — resetting at the wrong moment doesn't just disrupt state, it can disrupt trust.
6. Multi-format document generation as regenerate-and-replace, never in-place editing
The assistant can produce and revise real documents (PDF, Word) on a user's behalf. Rather than attempting byte-level document editing (fragile, hard to verify, hard to make safe), every "edit" is: regenerate the full document from its underlying structured content, then atomically replace the prior version. This trades a small amount of efficiency for a much stronger correctness and auditability property — the system always knows exactly what produced a given document version.
7. Multi-tenant isolation enforced at the database layer, not just the application layer
Every tenant-scoped table enforces isolation via PostgreSQL Row-Level Security, with the tenant-context variable scoped to the transaction (not the pooled connection) — so a connection reused from a pool can never carry a stale tenant identity into the next request. Isolation is a database-enforced invariant, not something every query has to remember to filter for correctly.
8. Usage and cost governance as a first-class system, not an afterthought
Because every user interaction has a real, variable AI-inference cost, the system tracks per-account usage and cost in real time and enforces configurable caps atomically (row-locked check-and-increment, not a race-prone read-then-write) before an expensive operation is allowed to proceed — with the enforcement message itself designed to preserve the relationship ("I'm still holding your goal") rather than reading as a hard cutoff.
Engineering Practices Worth Naming
- Adversarial, multi-model review as a standing process, not a one-off. Non-trivial design and code changes go through a dual-vendor review pipeline: primary review at maximum reasoning capacity, followed by mandatory secondary verification from a model of a different vendor — both must independently converge on pass before anything ships. High-stakes or architectural changes trigger full independent secondary review, not just verification of what the primary flagged. This routes around a specific, named failure mode: a model cannot reliably grade its own work against its own criteria — self-certification is treated as a risk to engineer around, not a default to accept.
- Verify by execution, not by reading. A recurring lesson across this project: prose/code review repeatedly missed defects that a real execution against a real database or a real document-processing library caught in seconds — so certain classes of change (anything touching database-extension features, engine-specific semantics, or cross-format document rendering) have a standing rule requiring the actual operation be executed before being considered verified.
- Schema and cross-file consistency enforced mechanically, not by memory. A custom checker tool independently derives ground truth from the schema/migrations and asserts that every document that mirrors a piece of that state (contracts, architecture docs, build-agent instructions) actually agrees with it — catching the specific, repeatable class of drift that prose review reliably misses.
- Tiered automated testing, from fast no-database unit tests to a full integration suite running against a real, migrated Postgres instance for anything touching schema or cross-cutting state — calibrated so day-to-day iteration stays fast without losing real correctness coverage before anything ships.
- Multi-agent coordination via an async convergence protocol, designed from scratch when existing frameworks didn't fit. Coordinating agents that run in separate sessions and contexts, without a shared live process or always-on connection between them, doesn't fit the live-runtime assumption every existing multi-agent framework makes — so this uses a lightweight, git-backed protocol instead: a shared file in a dedicated architecture repo, an explicit claim-write-release lock checked every time with no exceptions, and bounded polling inside active sessions. Disagreement-handling is a built-in norm, not a bolt-on: every claim gets verified against real evidence before the channel can close, including a participant's own. That discipline caught a genuine concurrency bug live, during the protocol's own first formal use — a lock-claim was skipped on a stale assumption, producing a real duplicate-message collision with another agent writing concurrently — found and fixed before anyone else ever hit it, by re-verifying state before trusting the obvious read.
- The system itself was designed and built through a structured, AI-agent-assisted engineering workflow — not a single developer prompting a single model, but a disciplined process with distinct architect/build/adversarial-review roles, explicit gates between them, and durable written records of every design decision and its reasoning. Directly relevant to any conversation about how AI actually changes engineering practice, from someone who has run that process end-to-end on a real production system, not observed it from the outside.
This document intentionally omits business metrics, pricing, prompt content, and specific safety-mechanism internals — it describes the shape of the engineering, not the product's competitive specifics.