Chief, the on-device AI chief of staff I'm building, writes me a daily brief: a short rundown of the next few meetings and whatever's sitting in my queue. It runs entirely on a small local model, which sounds like a nice, contained feature until you actually try to make a cheap model behave the way you want. Two separate problems turned up while I was building it, and neither one was really about the model being wrong. Both were about trusting it to keep a promise it never actually agreed to.

An instruction the model wouldn't keep

The brief's first version told the model, in plain language, to keep it to five bullets or fewer. That worked right up until it didn't. Some days the list crept to seven or eight items, especially once the day had a few meetings and a longer queue to summarise. The instruction wasn't ambiguous. The model just didn't reliably follow it, and "reliably" is the word that matters here. It worked often enough in testing to look fixed, then failed on a day with more to say.

The fix wasn't a better sentence. It was giving the model less to work with. The brief now only ever receives the next three meetings and the top three queue items, full stop, and the code itself appends a line noting what got left out. The model has nothing to summarise down to five bullets, because there's never more than six items in front of it to begin with, and the "left out" line is written by the code, not generated, so it can't drift either.

This is the same argument I've made before about keeping orchestration in code rather than in a prompt, just showing up in a smaller, more mundane place. A count limit isn't a decision the model should be making turn by turn. It's a decision about what the model is even allowed to see, and that belongs upstream of the model entirely.

A setting that traded accuracy for repetition

The second problem was subtler and took longer to notice. Small models tend to loop: repeat a phrase, restate a point, occasionally get stuck circling the same three words. The standard fix is a repeat penalty, a setting that makes the model less likely to output a token it's already used recently. Turn it up, loops mostly stop. Turn it up too far, and it starts erasing facts.

The failure mode is quiet. A repeat penalty doesn't know the difference between a model stuck in a loop and a model correctly repeating a name, a date, or a meeting time that legitimately appears twice in the source material. Push the penalty high enough to kill loops reliably, and you're also pushing the model away from repeating anything it's already said, including the bits it should say again because they're true.

I only caught this because Chief had, by then, grown a 39-scenario persona test runbook for exactly this kind of regression hunting. Running the same brief generation across every repeat penalty value and checking fact retention against the source data gave an actual curve instead of a feeling: 83 percent retention with the penalty off, 86 percent at 1.05, dropping to 53 percent by 1.15. The gain from 0 to 1.05 is real and worth having. The cost from 1.05 to 1.15 isn't a rounding error. It's roughly a third of the correct facts in the output quietly gone.

Chief now runs every model at 1.05. Not because that number felt right, but because it's the one point on the curve that's actually been measured rather than assumed.

What the move to Qwen3 also forced

Both problems surfaced around the same time as a model swap. Chief's lightest tier moved from Llama 3.2 1B to Qwen3 1.7B, after Llama started inventing meetings outright on the eight-gigabyte, two-core Mac it was running on. The benchmark said Qwen3 was slower. It still won, because slower and correct beats fast and wrong for a feature whose entire job is telling you what's actually on your calendar. The swap brought its own cleanup. Qwen3's thinking mode gets disabled on every request through chat_template_kwargs, because nobody needs a chief of staff narrating its own reasoning before it answers. And the standup request, which used to offer the model a set of tools it never actually needed for that particular job, is now a single user turn with none offered at all: fewer places for the model to go wrong, and about 500 fewer tokens of prefill on every request.

None of these fixes are really about Qwen3 or Llama specifically. They're about what happens once you stop assuming a small model will do the thing you asked just because you asked clearly. An instruction can be ignored under load. A setting tuned to fix one problem can create a different, less visible one. The only way to know which is happening is to measure the actual output against the actual source, not to read a few briefs and decide they look fine.