On this page

I shipped an upsert I was proud of. Voice notes came back from the field, transcription finished, extraction filled the inspection form, and the row updated. On the happy path it looked like the product working.

Then a beekeeper corrected queen status by hand in the morning. The queue flushed again that afternoon with a cleaner transcript. Six fields got better. Queen status went back to the wrong value, because the model had heard wind and a half sentence and guessed "present" with a straight face.

She had already fixed it. My save undid her.

That is the bug I keep finding in AI features that otherwise test well. The model did its job. The write did not know a person had a better claim on that cell.

🔗The feature is the commit

A wrong answer in a side panel is annoying. Someone reads it, sighs, and types the right thing.

A wrong answer in a column is a different kind of problem. The next report uses it. The next person on shift trusts it. A status change might kick off a task. You do not get the sigh. You get a quiet corruption that looks like data.

I stopped scoring the feature on whether the form filled in. I score it on what is allowed to become the record.

🔗The clobber hides inside a reasonable idea

Nobody files a ticket called "overwrite the human." It falls out of a design you can defend in review.

The transcript got better, so you run extraction again. The new output wins on more fields than the old one. You upsert the whole row, because partial updates feel fussier than they are worth on a Tuesday. Average quality goes up. The one field a person already corrected goes back to the guess.

Both of those can happen on the same save. I have watched an eval set get greener while a live record got worse. The eval was asking whether the model matched the label. It was not asking whether this write was allowed to touch a cell a person owned.

Same shape shows up anywhere a suggestion lands in a system other people act on. A follow-up email. An invoice line. A status that assigns work to somebody else. Smoother text, worse record.

🔗Rules I stopped bargaining with

These showed up one incident at a time. Writing them down is how I stop relearning them.

A human edit sticks. If someone changed a field, the model does not get another turn at it unless that person asks. Their value stays until they clear it. "We reran the pipeline" is not a request.

Blank is a valid answer. Unknown and no are different facts. A blank queen status is safer than a confident "present" pulled out of noise. The screen after that should be able to say we do not know yet, without someone inventing a default to make the form look finished.

Auto-apply has a blast radius. Formatting, tags, a draft note that stays a draft: fine. Anything that changes money, status, or a field another human set: show the diff and wait. If the write will send an email, create a charge, or hand work to someone else, it stays a proposal until a person commits it.

Retries must not mint a second record. Double taps, queue replays, and webhook retries are normal life. The write is keyed to the source capture. Running the model twice is fine. Inserting two inspections for one voice note is how you teach an operator not to trust the app.

Keep the proposal after you save. Store the raw model output next to the committed values, with the capture id and which fields were accepted, skipped, or left blank. Three weeks later, "the model did it" is useless. You want the proposal, the commit, and the rule that allowed the commit.

🔗What the person actually sees

The schema can be picky. The screen should be plain.

Proposed values stay off to the side of the record people read. Fields worth arguing about carry a source: the user, an import, or an accepted suggestion. Old proposals hang around long enough to debug.

On screen that collapses to a sentence. Six fields look fine. Two need a look. Accept the safe ones. Leave the rest.

Per-field acceptance felt fussy when I built it. It felt obvious the first time one bad cell would have ridden along inside an otherwise good save.

🔗Where I still let it write

A confirm dialog on every token teaches people to click through. That is worse than no dialog.

The model can write straight through when all of this is true:

  • nobody has edited that field
  • a wrong value is reversible, or it lives in a draft
  • you can see what changed afterward without hunting for it
  • a wrong value does not wake up another person or another system

Draft the email and leave it in drafts. Stage the follow-up and leave it unassigned. Suggest the cell. Leave the one a person typed where it is.

🔗This is where the labels come from

A rejected field is a labeled miss. If you only store the final record, you throw that label away at the exact second it was created.

I wrote in July about keeping a small folder of real cases and reading every failure. A lot of those cases should come from this moment: someone looked at a proposal and said no. Capture the before and the after, then get out of the way.

🔗Final thought

A model that can fill a form is a decent demo. A model that owns the record will eventually undo someone who was paying attention.

Let it propose. Be specific about which saves are allowed to happen on their own. Leave the human's correction alone.


🔗Next step

If an AI feature in your product writes into the system people actually run the business on, the save path is worth a hard look.