Outlier  ›  learn

How to write a good AI prompt (that works on local models too)

Quick answer
  • A good prompt states the task, states the output format you want, and shows one example of that format. Those three things do more than any clever wording.
  • Put stable, reusable context first and the varying question last, and ask for a measurable constraint ("under 200 words") instead of an adjective ("keep it brief").
  • Smaller local models follow an explicit format instruction well but infer an implied one poorly, so be more literal with them.

Most prompt advice is written like folklore — magic words, secret roles, incantations you're supposed to paste at the top. It isn't that. A prompt is text, the model continues text, and everything that works follows from that one fact. Here's what actually moves the output, in rough order of payoff, plus a bug I shipped that taught me a habit worth more than any of them.

What a prompt actually is

A prompt is the text you send the model. The model predicts a continuation of it. That's the whole mechanism — there's a good explainer in what a large language model is if you want the longer version.

The part people underestimate: the model has no memory of you beyond what's in the current context window. It doesn't know what you asked yesterday, what project you're in the middle of, or what "the usual format" means to you. Every request starts from the text in front of it. That's not a bug in the product, it's how the thing works, and it's covered in why AI forgets conversations. Once that clicks, prompting stops feeling mystical and starts feeling like writing a decent ticket for a competent stranger.

The five things that actually help

Roughly ordered by how much they change the output:

  1. State the task and the desired output format explicitly. Not "help me with this function" but "return one fenced Python block". The format instruction is doing at least as much work as the task instruction, and it's the one people leave out.
  2. Give one example of the shape you want. One-shot beats zero-shot for formatting. You don't need five examples; you need one that looks exactly like what you want back.
  3. Put stable, reusable context first and the varying question last. This makes the prompt easier to read, and on a local runtime it also lets the engine reuse its cached prefix between turns — which makes follow-ups faster.
  4. Ask for the constraint, not the vibe. "Under 200 words" beats "keep it brief". "Three bullets, no preamble" beats "be concise". Adjectives are guesses; numbers are checkable.
  5. Split a multi-part ask into numbered sub-tasks. One prompt asking for four things scattered across a paragraph tends to lose one of them. The same four things as 1/2/3/4 tend to all come back.

Rewrites, before and after

Same intent, different odds of getting what you meant:

Instead ofWriteWhy it works
"Clean up this function""Rewrite this function. Return one fenced Python block, no explanation."Task plus explicit output format
"Keep it brief""Under 200 words"A checkable constraint instead of an adjective
"Summarize and also list risks and suggest next steps""1. Summarize in 3 bullets. 2. List the risks. 3. Suggest next steps."Numbered sub-tasks so nothing gets dropped
"Format it nicely"Paste one example of the exact layout you wantOne-shot beats zero-shot for formatting
Question first, then 40 lines of pasted contextContext first, question lastReads better and lets the runtime reuse its cached prefix

The bug that taught me to suspect the instruction first

On 2026-07-21 I was testing multi-file code requests in Outlier — ask for a small project, get back several files. They kept coming back as one unlabeled blob. No filenames, no separation, just a wall of code you'd have to split by hand. My first instinct was the obvious one: the local model isn't big enough to hold a multi-file structure together.

It wasn't the model. It was our own instruction. Somewhere upstream, the app was telling the model to emit "one fenced code block with nothing around it" — a rule that applied to every code answer. The model was following it perfectly. I swapped in an explicit "label each file" instruction and the same model formatted every file correctly.

The lesson generalizes past our codebase: when the output looks wrong, suspect the instruction before the model. Read the actual prompt that got sent — all of it, including the parts your tool added — before you conclude anything about capability. A format failure is far more often an instruction failure wearing a costume.

Small models need you to be more literal

Here's the difference that matters if you're running locally. Smaller models in the 1.5B–3B range are more format-sensitive than large ones. They follow an explicit format instruction well. They infer an implied one poorly.

So the failure mode isn't that a small model can't do the task — often it can. It's that you assumed something you never wrote down. A large model will frequently guess your intent from context; a small one takes you at your word. Anything you were leaving to inference — the labels, the section order, how many items, whether to explain or just answer — should be written into the prompt.

There's a side effect worth having: a prompt explicit enough for a small model leaves a large one nothing to guess at. Small models are an honest instruction editor.

Padding is not free

The instinct to dump everything in "just in case" is the one habit worth breaking. Context windows are finite. Irrelevant text actively costs you twice: it pushes the useful part further from the answer, and it burns window you may need later in the conversation.

The test is whether the model could do the task without it. The whole file when the function would do, three pages of background for a one-line question — cut it. Length is only worth spending on the task, the format, one example, and context the model genuinely can't guess.

A skeleton you can reuse

Nothing clever, just the five things in an order that works — and because the stable parts sit at the top, the runtime can reuse most of it turn to turn:

  1. Context — the code, the document, the background. Stable across turns, so it goes first.
  2. Task — one sentence on what you want done.
  3. Format — exactly what the reply should look like. Be specific enough to be checkable.
  4. Example — one short sample of that format, if the shape matters at all.
  5. The question — the varying part, last.

If a reply comes back wrong, don't rewrite from scratch. Change one line — usually the format line — and send it again. You'll learn which line was carrying the weight, which is worth more than any prompt you copy off the internet.

Receipts: The multi-file formatting failure above is my own first-hand measurement, run against Outlier on 2026-07-21: the same local model, same request, produced one unlabeled blob under our "one fenced code block" instruction and correctly labeled files under an explicit "label each file" instruction. The prefix-reuse point describes how a local runtime's prompt cache works, not a measured speedup. Everything else here is general model behavior, not a benchmark claim.

Frequently asked questions

Do I need to write prompts differently for a local model?

The same techniques work, but small models need you to apply them harder. A 1.5B or 3B model follows an explicit format instruction well and infers an implied one poorly, so anything you were leaving to inference — labels, section order, how many items — should be written down. A prompt explicit enough for a small model leaves a large one nothing to guess at.

Does the order of a prompt really affect speed?

Yes, on a local runtime it can. Putting stable, reusable context first and the varying question last lets the runtime reuse its cached prefix between turns instead of reprocessing everything. Reorder the same words so the changing part is in the middle and that reuse goes away.

Is a longer prompt a better prompt?

No. Context windows are finite, so padding a prompt with irrelevant text actively costs you: it pushes the useful part further from the answer and burns window you may need later. Length only helps when the added text is the task, the format, an example, or context the model genuinely cannot guess.

My output came back in the wrong format. Is the model too small?

Check the instruction before you blame the model. In July 2026 a batch of multi-file code requests in Outlier came back as one unlabeled blob, and the cause was our own instruction telling the model to emit one fenced code block with nothing around it. With an explicit label-each-file instruction instead, the same model formatted every file correctly.

Try Outlier free

Free Nano + Lite — local, private, no account. Pro $20/mo or $149/yr adds everything (all 7 model tiers incl. Plus 397B). Lifetime Pro from $99 (Founding 200, first 200 seats) or $200 (Founders 500). Apple Silicon only.

Download for Mac