Art Ellis

A short briefing, not a code review

I execute complex, ambiguous systems to a working outcome.

For the last ten years that's meant clearing and settlement infrastructure at DTCC and Citi. For the last several months it's also meant something I built myself: a production AI system that runs a real household — four assistants, real users, real stakes, and no team to hand the hard calls to.

Role today Product Owner, Fixed Income — DTCC Reading time ~5 minutes, three parts What this proves judgment under real constraints, not a coding sample

01 The Overview

One system, four users, no room to get their boundaries wrong.

The system runs four AI assistants for a real household, each with a distinct owner, purpose, and risk tolerance. They share one platform — but not one posture.

The four assistants
AssistantPurposeBuilt to optimize for
SloanExecutive assistant, research, chief of staffVelocity — new capability proves out here first
ArtieHousehold operations, meal planningStability
EunoiaTutoring & creativity for a child userSafety, above all else
EllisFamily CFO / financial advisorConservative — no unreviewed financial action

New capability is deliberately built and hardened on the lowest-stakes assistant before it's ever allowed near the others. A trick that's merely disappointing coming from an executive assistant is unacceptable coming from a tutor talking to a child — so the safety bar rises as capability moves across the table, never the other way around.

Four decisions that shaped it

  1. 1

    One shared resource, not four. The hardware can only run one AI model at a time, so every assistant shares it. That's a prioritization call, not a technical one — who gets the resource, and on what basis.

  2. 2

    Boundaries by default, sharing by exception. A child's tutoring session and a parent's private planning conversation must never bleed into each other. Information is scoped narrowly unless a boundary is crossed on purpose.

  3. 3

    Nothing that touches the real system runs unreviewed. Diagnostics are pre-approved; anything that changes real state needs a human sign-off first, logged in a way that can't be quietly edited after the fact.

  4. 4

    Every release assumes it might be wrong. Every change is backed up, tested, and health-checked after it ships — and rolls itself back automatically if that health check fails. No one has to be watching.

None of this was designed on a whiteboard up front. It's the shape that emerged from running a real system for real people — and having to explain, afterward, why something went wrong. One of those stories is below.

02 Seven Decisions Under Constraint

Built and run solo — every call below had no team to lean on.

Each one is a decision and a tradeoff, not a feature.

1

Resource scarcity forces a real prioritization call

Four assistants, one shared model. That's a staffing problem before it's a technical one: who gets the shared resource, and on what basis? The rule that shipped — the shared resource handles everything it's good enough for; a more expensive option is reserved for the narrow slice of work where it genuinely isn't — is the same call as staffing a team against a fixed budget: define the bar once, then route to it consistently instead of re-litigating it every time.

2

Boundaries have to be designed, not assumed

Four users, four trust levels, one system. A child's conversation and a parent's private planning session can't be allowed to bleed together by accident. The earlier version of this system had no such boundary at all — it "worked" until it was tested against a real privacy expectation and failed. Fixing it wasn't a performance tweak; it was recognizing that a system serving people with different trust levels needs governance, the same way an organization needs access controls that don't default to "everyone sees everything."

3

Autonomy has to be earned in tiers, not granted wholesale

Once an assistant can take real actions, the question stops being "is it capable" and becomes "what's the blast radius if it's wrong." The answer mirrors how any organization delegates authority: routine, reversible actions are pre-approved; anything that changes real state needs a human sign-off; and one category of action was deliberately left unbuilt rather than rushed — the honest choice was "not yet," not "approved by whoever's around." Every decision in that chain is logged in a way that can't be quietly edited after the fact.

4

Every rollout assumes it might be wrong

Every change goes through the same sequence: verify it's sound, run the test suite, back up what it might affect, ship it, then watch a health check — which rolls the change back automatically if it fails. Nobody has to be awake watching a dashboard. There's also a single, deliberately low-tech kill switch: one file's presence halts the whole release process. The fastest way to stop a bad rollout is the one that doesn't require remembering where the admin panel is at 2am.

5

Not every capability is worth the exposure it creates

Some information should never leave the house, regardless of whether an outside service would technically do a better job with it. The system classifies what it's about to send out before deciding whether it's allowed to — and the fallback only ever runs toward more caution, never less. A feature degrading gracefully beats a feature quietly leaking something it shouldn't have.

6

The bottleneck wasn't the one everyone assumes

For a voice assistant, the obvious instinct is "get a smarter model." The actual bottleneck was somewhere else: the first response in a conversation was consistently slower than every response after it, because of a one-time startup cost. The fix wasn't a better model — it was paying that cost once, in advance, instead of making the first person to speak pay it. Measure before you optimize; the thing that feels like the bottleneck and the thing that is the bottleneck are often different problems.

7

A silent failure is worse than a loud one

Routine maintenance once killed an in-progress job without anyone finding out until later — it simply vanished, no error, no alert. The fix wasn't "stop doing maintenance," which is what keeps the system healthy. It was making sure in-progress work survives the thing that could kill it, and that if it can't, it says so loudly instead of disappearing. A loud failure gets fixed; a silent one gets discovered downstream, much later, by someone who already made a decision based on nothing being wrong.

03 When It Broke

Failure & tradeoff writeup

The assistant started making things up. One fix wasn't enough — it took five.

A routine review of recent chat transcripts turned up something bad: the assistant was fabricating facts. Not vague hedging — specific, confident, wrong claims. Invented sources. Fabricated data presented as if retrieved. At one point it described the platform's own underlying technology using vocabulary borrowed from a completely different industry, as if it had confused what it was being asked about with what it was built out of.

17 of 19recent conversations contained fabricated facts — not an edge case

Why "one root cause" was the wrong assumption

The instinct when you find a bug this bad is to look for the bug — one bad prompt, one missing guardrail. That instinct was wrong here. Assuming it was right would have meant shipping a fix that closed one hole while four others stayed open. Tracing each fabrication back to its actual cause turned up five distinct, unrelated root causes:

  1. 1

    Vocabulary contamination — terminology from an unrelated part of the system was leaking into prompts where it didn't belong, and the model used it confidently, in the wrong context.

  2. 2

    A missing backstop — for research questions, the system was supposed to fall back to a live search when ungrounded. That backstop wasn't triggering for an entire category of questions, so the model filled the gap itself.

  3. 3

    An instruction that collapsed under repetition — meant to vary phrasing, it instead fell into a canned pattern that, under pressure, padded itself with fabricated specifics.

  4. 4

    A voice-transcription error that slipped past its own safety check — a mishearing with high apparent confidence became the false premise for everything said next.

  5. 5

    A misrouted request type — "recall something I told you" was being misread as "set a reminder," handed to a part of the system with no reason not to improvise an answer.

None of these five would have been caught by fixing any of the other four. A narrower investigation that stopped at the obvious cause — "the search backstop is broken" — would have shipped a fix, watched the fabrication rate drop but not disappear, and had no framework for explaining why.

The fix, and what's still open

All five causes were root-caused and fixed together, in one coordinated change, so the fix could be evaluated as a whole rather than re-discovering the same failure five separate times.

Status the day this shipped: fixed in code — runtime proof pending

A code fix isn't the same as proof it works under real, unscripted use. Marking something "done" before that evidence exists is exactly the kind of overconfident claim that caused the original problem — a fix diagnosed in isolation from real-world evidence, and declared finished anyway.

The generalizable lesson: a system that fabricates confidently is worse than one that fails loudly, because confident fabrication doesn't look like a bug to the person reading it — it looks like an answer. The fix that mattered wasn't any single one of the five patches. It was refusing to stop investigating after the first plausible cause, and refusing to call it done until it had been watched work in production, not just read as correct on paper.