← Home

AI Agent as Mentor

9 July 2026

AIMentorship

The agent replies below are AI-generated, reproduced from a real working session (lightly edited for formatting and to anonymize client names).

AI agents make for great mentors, but you need to explicitly invite them into this role by saying “here is my POV on what happened, can you pressure test it”.

After completing this discussion, I make two further asks of the agent:

  1. “Create a durable artifact of these lessons learned” — which in my case means create an .md file in the dedicated directory for these lessons.
  2. “Wire this in to the repo” where you have your agent-driven work system.

“Wire this in” is the agent equivalent of asking a team “how do we prevent this type of mistake from reoccurring in the future?”

Here is a sample of a conversation I had:


Me:

I think a big miss for me that wasted a huge amount of time for the BBC cross-check was first working on the level of individual bugs. Then I leveled up in a beneficial way to the level of software architecture, but I was still looping, and then I think I reached the final solution by leveling up to the level of the data model.

For me, the lesson is to always begin the process by creating a data model, since a data model often has an implied software architecture — or said otherwise, the software architecture should be downstream of the data model, not vice versa. What’s the best way to wire this into the repo?

Give me your proposal.

Also, what do you think of my conclusion about starting with the data model? Pressure test it.

Agent:

๐Ÿงช Pressure test of “always begin with the data model”

Where it holds strongly: for systems whose job is producing and maintaining facts — registries, ledgers, pipelines, reconciliation — the data model is the architecture. Your own root-cause diagnosis in the design doc (“files serve as both storage and interface with no single owner per fact”) is a data-model failure, not a code failure. And the economics have shifted: agents regenerate code cheaply, so code-level architecture is disposable; the durable contract worth your scarce attention is the data model. Today proved the iteration speed — the whole redesign happened in a spreadsheet in a morning, versus weeks of bug-loops.

Where I’d push back:

  1. Hindsight bias in the “always begin” framing (confidence: high). You could not have written this model on day one — the canon/raw split, term-level vs doc-level supersession, and operative views were learned by doing the work. The honest lesson isn’t “the right model comes first”; it’s “an explicit model must exist from day one so its wrongness becomes visible early and revisions are cheap.” The failure mode was implicit schemas living in filenames and response-file dialects for months, not insufficient upfront design.
  2. The load-bearing ingredient may not be the model itself (confidence: moderate). Your diagnosis says the root cause was no single-writer rule and no regeneration contract. A tables-and-columns model without per-column ownership (who writes each fact, what’s derived vs authored) would have still drifted. Any rule you wire in should require ownership annotations, not just schema.
  3. It doesn’t generalize to all work (confidence: high). Slack frontends, browser automation, email drafting, calendar workflows — thin data models, and forcing a modeling step there is ceremony. The rule needs a scope trigger: work that creates or mutates durable data surfaces.
  4. Overcorrection risk: data-model-first can slide into big-design-up-front — speculative entities, premature normalization. Guard with 80/20: one page, entities + grain + uids + owners, revised freely until code consumes it.
  5. One refinement to your ladder story: you did level up to architecture and still looped — because it was component/control-flow architecture. For fact-producing systems, the data model isn’t a level above architecture; it’s what the architecture level should have meant.

Net: I agree with the scoped version — architecture downstream of the data model, for any system whose job is maintaining facts — and that covers most of your fact-producing work.

๐Ÿ“‹ Proposal for wiring it in:

  1. Canonical standard — a new data_model_first_standard.md in the repo’s standards directory: when a data model is required (work creating/mutating durable facts — registries, ledgers, manifests, queues, trackers); the minimal deliverable (a long-format table of entities, grain, and columns — plus key-naming rules and per-column ownership); where it lives; and a same-pass sync rule (a code change that implies a model change updates the model in the same pass).
  2. Admission-gate hook — one added check in the new-build-work admission gate in the repo’s issue runbook: build work touching a durable data surface is inadmissible unless a data-model artifact exists or is updated. This is the enforcement point with real teeth, since all work flows through it.
  3. Agent-instructions invariant — one line in the shared agent instructions file: software architecture is downstream of the data model; fact-producing systems start with the model. Pointer to the standard. Shared surface, so every agent inherits it.
  4. Architecture-review ladder amendment — in the architecture-escalation trigger: for fact-producing systems, the architecture review pass starts with a data-model audit (entities, grain, one-writer-per-fact) before component architecture — encoding exactly the miss you described.
  5. Explicitly not proposing tooling (validators, generators) yet — the smallest useful version is one standard doc and three pointer edits, about an hour.

Say the word and I’ll implement 1–4.

Me:

Re: point 3 (doesn’t generalize to all work) — This is a good point. I think in my mind I neglected to consider those since they’re relatively straightforward. The place where I get into trouble is always the items that create or mutate facts, which is most of what we do within our product repos and services.

Re: point 5 (you leveled up to architecture and still looped — because it was component/control-flow architecture; for fact-producing systems, the data model isn’t a level above architecture, it’s what the architecture level should have meant) — Can you unpack this in more detail for me in an emoji-forward skimmable way?

Also, can you speak to the specific importance of numeric UIDs as it relates to the data model?

Agent:

๐Ÿชœ Unpacking why “architecture” didn’t stop the looping

  1. ๐Ÿ› Bug level — you were fixing symptoms one at a time: 27 phantom-stale rows, the BBC-ref field dialect mismatch, each patched where it surfaced. Whack-a-mole, because every fix left the generator of bugs intact.
  2. ๐Ÿ—๏ธ What “architecture” usually means is code architecture — components, module boundaries, who-calls-what, cron vs manual paths, control flow. That’s the level you escalated to, and it did help: it’s how you found the multi-writer ledger and the fragmented registries. But it kept looping because…
  3. ๐Ÿ•ณ๏ธ In a fact-producing system, the bugs don’t live inside components — they live in the seams between them. Every one of your recurring bugs was two pieces of code disagreeing about a fact: what counts as a doc, which BBC is current, who updates the ledger, which field carries the reference. Each component’s control flow was locally correct; the disagreement was in the files they share. Code architecture treats those files as implementation detail, so the true defect stayed invisible at that level.
  4. ๐Ÿ“Š The data model is boxes-and-arrows about facts, not code — entities, grain, identity, supersession, one writer per column. That’s the level where “which field holds the BBC ref” is a first-class design question instead of a runtime surprise.
  5. ๐Ÿงญ Once the fact layer is fixed, the code architecture is nearly forced: readers and writers per column fall out of the ownership annotations; the pipeline is just the derivation edges (registry → operative view → cross-check). That’s what “architecture downstream of the data model” cashes out to — control flow becomes a derived view of the model, the same way an operative legal-term registry is a derived view of the underlying registry.
  6. ๐Ÿงช Litmus test for next time: if a bug can be phrased as “two places disagree about a fact,” you’re still below the right level — go straight to the data model, don’t route through component architecture first.

๐Ÿ”ข Why numeric UIDs specifically matter

  1. ๐ŸŽฏ Meaninglessness is the feature. A numeric uid carries zero facts, so no correction can ever invalidate it. Every meaningful candidate key in your model is provably unstable: filenames get revised (“(Revised) Borrower_BBC…”), borrower names get respelled, and the as-of date might switch from filename-derived to workbook-derived — if doc identity were borrower + date, resolving that question would re-key the whole registry and break every doc-uid reference downstream.
  2. ๐Ÿ”— Supersession and correction need identity that survives edits. Superseded-by chains and provenance references must keep pointing at the same row even after you fix a typo in a raw term or re-extract a field value. Content changes; identity doesn’t.
  3. ๐Ÿงน Raw strings are the mess you’re managing, so they can’t be the key. The whole canon-mapping layer exists because raw field spellings vary per borrower per doc. Numeric uids keep the mess in a data column and out of the join path.
  4. โœ… Joins become deterministically checkable. Numeric equality has no case, whitespace, or unicode traps (invisible narrow-space characters in text files are exactly the failure class), and a dumb script can verify the entire model: every uid an integer, unique within its family, every FK resolving. That’s a cron-able integrity check — the drift detection the old ledger never had.
  5. ๐Ÿ–‹๏ธ A numeric sequence forces a single mint point. Someone has to allocate “next id” — which forces you to decide who mints identity for each entity family. That’s the single-writer rule in miniature, imposed by the key design itself. Name-derived keys let any writer compute an id independently, which is how two pipelines silently create the same entity twice.
  6. โš ๏ธ Two cautions: declare uniqueness scope per family (make each uid globally unique within its family, not per-borrower), and a uid is a cell value, never a row position — sheet row numbers change on sort/insert, so ids must live in the column and survive reordering. Keep human-readable composites (borrower + date) as display columns if useful, but never as join keys.

Me:

Can you write a reflection memorializing this specific episode, and then at the bottom have sections for what’s generalizable and not generalizable?

← Home