Field note

The Architecture Underneath the Writing Room

Or: How I Went from Chatting with an AI to Running a Production System, and Why the Difference Matters

The Architecture Underneath the Writing Room

I didn’t set out to build a system. I set out to write a novel.

Seven months and 557,000 words later, I had roughed out the outline for an eleven-book series, built a custom MCP server to hold the canon, and wired up 19 scheduled automation tasks to handle everything else. The writing got done. The system is how.

This post is a breakdown of what that infrastructure actually looks like. Not the philosophy of AI collaboration. The working parts: the databases, the behavioral memory, the automation layer that handles the work that doesn’t require my brain.


The Core Problem Every AI Writer Eventually Hits

AI has no memory between sessions. You spend twenty minutes getting the model calibrated to your project: your characters, your scene-level rules, what the voice is supposed to feel like. Next session it’s gone. The model is a brilliant amnesiac.

Most people solve this by pasting context at the top of every session. It works until it doesn’t. By session three, your context window is half occupied by setup and you haven’t written a word.

I solved it differently.


The MCP Server

Everything in this system runs through a custom MCP (Model Context Protocol) server, a local Python process that Claude queries mid-session. Two databases, two entirely different purposes.

The first is a read-only canon database: 94 character profiles with voice calibration blocks, image prompts, and psychological architecture. 37 locations with GPS coordinates. Chapter-by-chapter tracking across nine active novel books. This data originates from a single Excel workbook, and a PowerShell export pipeline pushes it into SQLite and JSONL on demand.

Claude reads from it. Claude never writes to it. The source of truth is the workbook; the database is just how the model gets at it quickly.

The second database is Claude’s working memory. Not mine. Claude’s.


The Behavioral Flywheel

This is the part that changes how the system compounds over time.

Three tables: notes, constraints, and affinities. Notes are session-scoped context: the things that happened this week that future-Claude needs to know. Constraints are rejection patterns. Every time the model does something wrong, I write it down with the correct behavior.

Affinities are the other side: every time something works especially well, I write that down too. At the start of every session, Claude loads all of it. Both tables have a hit_count field, so patterns that keep recurring are weighted against patterns that fired once.

Nate B. Jones, who developed the rejection encoding concept underlying this system, put it cleanly: corrections to AI output are more valuable than the output itself. Every mistake and every win gets encoded. The model that showed up today is smarter than the one from six months ago because it loaded sixteen active constraints and nine active affinities before typing a word.

The alternative is typing the same correction into chat for the fourth time. I’ve seen people do it. It is not a strategy.


The Session Ritual

Every work session follows a structured initialization sequence. The model reads a Creative Collaborator Profile covering communication style, physical context, and project intent, then loads all active constraints and affinities and checks for pending items. A canon watchdog arms itself for the session: before each response, it scans for anything in the behavioral library relevant to what I just said.

The ritual is implemented as a library of named skills, each scoped to a specific type of work. A novel writing session loads character voice, canon data, and narrative architecture; a Substack session loads writing standards, analytics, and post history. The model doesn’t get handed everything at once. It gets handed what it needs for the next two hours.

At session close, a matching close sequence logs what was accomplished, retires completed items, and flags anything that needs documentation. Session duration is calculated from the init timestamp to the clock at close. There is no “roughly an hour.” There is 1h 47m.

This sounds like overhead. What it buys is a model that arrives oriented, not repeating last week’s mistakes, not making me re-explain what I meant by “voice drift” for the third time this month.


The Automation Layer

Nineteen scheduled tasks run on a cron-based schedule across five categories.

Health monitoring: two separate sleep reports pull from the Eight Sleep pod sensor, the BiPAP device, a blood pressure monitor, and the bedroom environment sensor, then deliver a consolidated morning report and create a calendar event for the exercise window. Both are personalized, because two people sleep in that house and they have different physiology.

Information delivery: three recipients get daily or weekly news briefs with source sets tuned per person. A fourth task monitors one RSS feed, extracts the latest post, and delivers a bottom-line summary before the recipient has had coffee.

Job search: a remote job report generates an HTML digest of positions matching specific search criteria, filtered for remote eligibility, and delivers it on a daily schedule.

Analytics and housekeeping: Substack analytics pull from Google Analytics 4, get stored in SQLite, and refresh a local dashboard. A grocery task syncs the shopping list. A weight and biometric pull keeps the health database current. SQLite housekeeping runs cleanup on the canon database.

The architecture across all of it is generate-then-send. Each task has two phases: a generate phase that pulls data and writes a report file, and a send phase that verifies the file is fresh before delivering it. If generation fails, the send phase catches the missing file, writes a force-retry flag, kicks off the generate task inline, and completes delivery without the recipient ever knowing something went wrong.

This is a standard reliability pattern from production engineering. In AI workflow design, most people are still running single-step prompts with no error handling. Those fail silently. The user finds out from the recipient, not from a log.


The Documentation

Everything is documented in a local HTML reference site served by IIS on my own machine. The workflow diagram is a clickable node graph of every component and how they connect; the data architecture page covers every field in the Excel workbook and MCP schema. The operations reference lists every scheduled task, every API dependency, and a troubleshooting decision tree. The notes system reference explains how the behavioral memory works.

The rule is: work is not done until the documentation reflects the change. This is the rule I break most often. It is also the rule I most regret breaking.

Two sessions after you skip it, you’re staring at a script you wrote and genuinely cannot remember why the cron runs at 6:31 instead of 6:30.

(It staggers API calls to avoid rate-limiting collisions. I know that now because I wrote it down. Eventually.)


Where the Data Lives

All of it is local. The MCP server is a Python process running on my machine, not a hosted service. The canon database and the behavioral memory are SQLite files on my hard drive. Nothing in this architecture requires a cloud database, a SaaS platform, or a subscription beyond the AI itself.

The only data that intentionally leaves the machine is what I send: emails from the delivery tasks, Substack analytics written back to the local database. The API calls to Eight Sleep, Google Analytics, and MyAir pull data in. It stays in.

This matters more for writers than for most people. The canon database holds the psychological architecture of 94 characters, the theological framework of an eleven-book series, and chapter-level plot tracking across nine active books. That is the unpublished work. It does not live in someone else’s API logs.

The health data makes the same case. Sleep scores, blood pressure, CPAP compliance, weight trend over ninety days: the scheduled tasks pull it, process it, and write it to a local file. The model reads the local file. The chain never passes through a third-party cloud storage layer.

This was a deliberate platform choice. Claude’s MCP protocol is designed for local integration: the server runs on your machine, the model queries it over a local connection, and nothing routes through an intermediary. That’s the constraint that drove the build. The architecture exists because the platform supports it.


What It Actually Costs

Building this took time. The workbook schema exists because I designed it. The export pipeline runs because I wrote the PowerShell. The constraint library has sixteen entries because I noticed sixteen patterns worth encoding.

None of this is passive. Out of the box, Claude is capable and amnesiac. What you build on top of that determines whether you have a tool or an infrastructure. “Nothing” is a valid answer right up until you’ve been re-explaining the same character notes for six months straight.

The canyon floor is patient.


What It Enables

At peak output, this workflow produced over 100,000 words a month of fiction holding consistent voice across 94 characters, a coherent theological framework, and a nine-book narrative architecture. That number doesn’t come from the AI working faster. It comes from the AI working correctly, inside a system designed to catch mistakes before they compound.

You don’t need all of this to start. You need a notes file, a constraints list, and enough discipline to write down what goes wrong. The rest scales.

I took it seriously. The infrastructure is what serious looks like.


You may also like: - Local MCPs or how not to expose your data to the Internet - Two-Phase Pipelines, Persistent Memory, and Why RSS Still Wins - Not All Data Is Created Equal

All entries
Support My Writing

No paywall here, and nothing is gated. If a piece was worth something to you, the tip jar is open.

All writing on this site contains elements of both human and AI produced material. This author uses all resources at his disposal.