Your system prompt isn't instructions. It's data.
My system prompt had an example of a good Slack message in it. It opened with "Morning all, quick one:". The model started opening real Slack drafts with that exact phrase. Then it started saying "Morning." when I typed "hey", which is a small lie, because it cannot see a clock. So I added a rule telling it not to reuse examples from its own instructions. Three rebuilds. No change. Then I deleted the phrase. Fixed on the next build. That is when it clicked. The model does not read your system prompt as a list of instructions. It reads it as text that is likely to appear near its own output. Every finding below falls out of that one idea. The four rules I now write prompts by If a phrase must not appear in the output, it must not appear in the prompt. Banning it does not work. Deleting it...
My system prompt had an example of a good Slack message in it. It opened with "Morning all, quick one:". The model started opening real Slack drafts with that exact phrase. Then it started saying "Morning." when I typed "hey", which is a small lie, because it cannot see a clock. So I added a rule telling it not to reuse examples from its own instructions. Three rebuilds. No change. Then I deleted the phrase. Fixed on the next build. That is when it clicked. The model does not read your system prompt as a list of instructions. It reads it as text that is likely to appear near its own output. Every finding below falls out of that one idea. The four rules I now write prompts by If a phrase must not appear in the output, it must not appear in the prompt. Banning it does not work. Deleting it does. Naming a bad example summons it. "Not the bank balance one" is an excellent way to get the bank balance one. Position beats wording. A rule buried mid-section gets read and traded away. The same words at the top of that section hold. Concrete beats principled. "Call before the rename" lands immediately. "Describe only the guarantee the code actually makes" does nothing. And the one that saved me the most time after it cost me the most time: verify on three seeds before you believe any of it. Here is the evidence for each. The setup Flash Onyx is the model line behind Flash, my local agent shell. There is no fine-tuning involved. Onyx is a base model plus a system prompt that has grown to roughly 680 lines, built into an Ollama tag with a small script: 2.5 is the version where I stopped editing that prompt by feel. The loop is not clever: edit the prompt, rebuild the tag, run a fixed set of prompts at pinned seeds, read the output, decide whether anything actually changed. Seeds are pinned so two runs are comparable. That is the entire method, and it is the difference between "this reads better to me" and "this went from failing on three seeds to passing on three seeds". 1. Your examples are not examples. They are samples. The Slack line was the small version. Here is the expensive one. While fixing how Onyx explains things, I gave it a demonstration answer for "what is a deadlock", complete with two functions taking locks in opposite orders. Onyx pasted that answer back word for word, invented function names included. Then the opener from that demo started showing up as the answer to "what is a race condition". Which is a different concept. A style demonstration had turned into a correctness bug. Demonstrations are still the most powerful tool in the box. They just have to be shaped so that a verbatim paste is either harmless or impossible. If I quote a full answer, it is now for a question nobody asks, and anything I actually want copied gets quoted in fragments the model has to assemble. 2. Six rebuilds on a bug that never existed I spent six revisions trying to stop Onyx answering "explain what a race condition is" with a textbook lecture: definition sentence, numbered trace with two threads, closing line about locks. Nothing I wrote moved it. Then I ran the same prompt at three other seeds. All three had been clean prose for most of those six revisions. Seed 7 was an outlier, and I had been rewriting rules that already worked. Pinned seeds make runs reproducible, which is the point of them. They also make a single unlucky sample look exactly like a deterministic rule failure. Three seeds before touching anything, every time now. 3. Moving a line fixed what four rewrites couldn't The prompt tells Onyx to target Python 3.9, because that is what a Mac hands you as by default. It kept writing annotations, which raise a on 3.9. I rewrote that rule four times. I stripped every pipe union out of the prompt in case they were priming it. I added a correct example signature to copy. Every seed, every build: . The rule was fourteen lines into the PYTHON section. I moved the same words, unchanged in meaning, into that section's opening lines. Fi