Prompting

No magic phrases, no superstition. Practical prompting advice from actually using these tools every day.

  • 'It works on my prompt' is the new 'it works on my machine'

    Every developer who has been around a while has heard the excuse, usually delivered with a shrug: "works on my machine." The bug is real, the user is not lying, and the developer genuinely cannot reproduce it, because their laptop has a library version, an environment variable, or a cached file that the server does not. The phrase became a joke because it was always technically true and completely useless. We are now watching the exact same failure reappear in a new costume, and it says "it works on my prompt."

    You have seen it. Someone demos a prompt that produces a perfect answer. It goes into the product. Within a day the support channel fills with outputs that are wrong, malformed, or unhinged, and the author is baffled, because it worked when they ran it. It did work when they ran it. That is precisely the problem, and it is the same problem we thought we solved twenty years ago.

    Same disease, new organ

    The old bug came from an environment you did not control and could not see. Your machine had state that the deployment target did not share, so behavior that depended on that hidden state broke the moment it moved.

    A prompt has the same hidden state, just in different places. When you tested it, you fed it your clean example, in your phrasing, on the model version you happened to be pointed at that afternoon. Production feeds it a user who writes in fragments, pastes an emoji, switches to Spanish halfway through, or sends the empty string. Same prompt, wildly different input distribution. The prompt did not change. The world around it did, and the prompt had no defenses because you only ever tested it in the world where it worked.

    There is a second layer that makes it worse than the original. The old bug was at least deterministic. Given the same machine and the same input, you got the same result every time. A language model is not deterministic by default. The identical prompt with the identical input can return a good answer now and a broken one on the next call. "Works on my prompt" is therefore weaker than "works on my machine," because it does not even reliably work on your prompt. It worked the three times you tried it, and you called that done.

    We already know the cure

    Here is the part that should be encouraging. The industry did not just complain about "works on my machine" for two decades. We killed it, with a set of practices so ordinary now that juniors assume they always existed: version everything, test against realistic inputs in an environment that mirrors production, put it all in a pipeline that runs before anything ships. The discipline was the answer. The same discipline is the answer here, and prompt engineering is mostly refusing to relearn it the hard way.

    What that looks like in practice is not exotic. Pin your model version, because a silent upgrade is a config change that can break every prompt at once. Keep a real test set of messy, adversarial, empty, and multilingual inputs, and run your prompt against all of them, not against the one clean example that made the demo look good. Run each case more than once, because a single pass through a non-deterministic system tells you almost nothing. And gate deployment on those results, so a prompt cannot reach users until it has survived the ugly inputs.

    None of this is new thinking. It is testing and version control and continuous integration, pointed at a prompt instead of a binary. The reason teams skip it is that prompts feel like writing, not engineering. You type a sentence in plain English, the model does something clever, and it looks less like code than a note to a coworker. That feeling is the trap. A prompt is a program with an input space larger and stranger than any function you have ever written, and treating it as casual text is how you end up shipping the empty string straight into production.

    The teams that will be trusted with AI features are not the ones with the cleverest prompts. They are the ones who looked at "it works on my prompt," recognized an old enemy in a new coat, and reached for the boring tools that beat it the first time. The excuse was funny once. Please do not make us laugh at it twice.

  • Building your own eval when benchmarks do not fit your task

    A model tops the leaderboard, you swap it into your product, and your users complain more, not less. This happens constantly, and it is not a mystery. The benchmark measured the model's ability to answer graduate physics questions. Your product summarizes support tickets for a plumbing company. The two have almost nothing to do with each other, and the leaderboard never claimed otherwise. If you want to know which model is best at your job, you have to measure your job. That means building your own eval, and it is far less work than it sounds.

    Why public benchmarks mislead

    Public benchmarks are useful for one thing: telling model builders whether they are making progress on broad, general capability. They are close to useless for telling you whether a model will do your specific task well. There are a few reasons for this, and they compound.

    The tasks do not match yours. A high MMLU score says a model knows a lot of trivia. It says nothing about whether it can follow your formatting rules or refuse politely when a customer asks something out of scope. Worse, popular benchmarks leak into training data over time, so a strong number can partly reflect memorization rather than skill. And a single averaged score hides exactly the failures you care about. A model that is right ninety percent of the time can still be catastrophically wrong on the ten percent that is your core use case.

    None of this means models are bad. It means the benchmark is answering a question you did not ask.

    Building the thing

    An eval is just a set of real inputs, a definition of what a good output looks like, and a way to score outputs at scale. You can start with thirty examples in a spreadsheet.

    Collect real cases. Do not invent test inputs. Pull them from your actual logs, your support queue, the messy things users really send. Include the easy ones, but hunt specifically for the hard, weird, and embarrassing cases, because those are where models differ and where averages lie. Aim for enough variety that a model cannot pass by getting one category right.

    Define pass and fail before you look at any output. This is the step people skip, and skipping it poisons everything downstream. For each case, write down what makes an answer acceptable. Sometimes it is an exact value. More often it is a checklist: did it cite the right ticket, did it stay under the word limit, did it avoid promising a refund. Vague criteria give you vague evals, which are worse than none because they feel rigorous while measuring nothing.

    Automate the scoring. You will run this hundreds of times, so it cannot be manual. Three approaches, roughly in order of how much you should trust them:

    • Exact or programmatic checks: string match, regex, JSON schema validation, a number within tolerance. Cheap, fast, and never lies. Use these wherever the answer is checkable.
    • Model-as-judge: another model grades the output against your criteria. Useful for fuzzy qualities like tone, but the judge has its own biases and needs its own sanity checks.
    • Human review: the gold standard and the bottleneck. Reserve it for the cases automation cannot handle, and for periodically auditing whether your automated scores still agree with human judgment.

    Iterate. An eval is not a document you write once. Every time the model surprises you in production, that failure becomes a new test case. Over a few months your eval becomes a precise portrait of your task's hard edges, and the moment a new model comes out you can answer the only question that matters, which is whether it is better at your job, in an afternoon instead of a quarter.

    The payoff you do not expect

    The obvious benefit is that you can compare models honestly. The bigger benefit sneaks up on you: the act of defining pass and fail forces you to say, in plain terms, what your product is actually supposed to do. Most teams cannot do this cleanly, and it shows in their prompts. Writing an eval is the most productive argument your team will have about what good even means.

    You will never top a public leaderboard, and you should not want to. You want to top the only leaderboard your users vote on, which has one entry, and it is you. Build the eval, keep it close, and let the people selling benchmark numbers argue about whose model knows more physics.

  • Getting AI to write in your voice instead of its own

    Every model has a default voice, and it is the same voice: smooth, agreeable, faintly corporate, allergic to a strong opinion. It is the tone of a brand apologizing. If you want AI to help you write without sounding like everyone else who uses AI, you have to actively drag it away from that default. Here is how.

  • Guardrails: keeping a model from saying something you will regret

    You ship a chatbot on a Friday. By Monday someone has convinced it to write a phishing email, and a screenshot is doing numbers on social media. This is the fear that sells guardrails, and it is a real fear. What people rarely tell you is that guardrails are less a wall and more a series of speed bumps, and that a determined person in a car will clear all of them. The goal is not perfection. The goal is to make the bad outcome rare, boring, and logged.

    The four layers that actually do something

    Think of a guardrail system as filters wrapped around the model, not as changes to the model itself. There is what goes in, and there is what comes out, and you can inspect both.

    Input filtering catches trouble before the model ever sees it. This is where prompt-injection detection lives, where you strip or flag attempts to smuggle instructions into user text, and where you block obvious abuse. Tools like LLM Guard run scanners for injection patterns, personal data, and banned topics. They add maybe 10 to 50 milliseconds and can run in parallel with the main call, so latency is rarely the reason to skip them.

    Output filtering reads the model's answer before your user does. A moderation model scores the text, and anything over a threshold gets blocked or rewritten. OpenAI's approach here is almost quaint in its simplicity: you describe the content domain, give grading criteria, and get back a score from one to five, blocking anything at three or higher. Llama Guard, which is a fine-tuned Llama model, frames the whole thing as an instruction-following task across a taxonomy of unsafe categories: violent crime, self-harm, weapons, and so on. It works because language models are genuinely good at following instructions, which is the same reason they are so easy to trick.

    System prompts are the cheapest guardrail and the most oversold. You tell the model who it is and what it will not do. This shapes default behavior well and stops nothing determined. Treat the system prompt as tone and policy, not as security.

    Allow and deny lists are the least glamorous and often the most reliable. A deny list of exact strings, regexes, or topics will never be clever, but it also will never be talked out of its job by a clever user. If your product must never output a competitor's name or a specific slur, a hard string match beats a probabilistic classifier every time.

    Where each one breaks

    Every layer has a failure mode, and knowing them is the whole job.

    • System prompts leak and get overridden. "Ignore previous instructions" is a cliche because it kept working.
    • Moderation classifiers miss novel phrasings and flag harmless ones. They were trained on yesterday's attacks.
    • Deny lists are brittle. Users route around them with spacing, synonyms, or another language.
    • Input filters cannot see intent that is spread across a long, innocent-looking conversation.

    The pattern underneath all of these: any guardrail built out of a language model can be attacked with language, and any guardrail built out of fixed rules can be stepped around by changing the words. You do not get to pick a layer that has no weakness. You get to stack layers so that a single trick has to beat several different mechanisms at once.

    What a sane setup looks like

    Do not reach for the heavyweight toolkit on day one. Start with a moderation call on both input and output, a short and specific system prompt, and a deny list for the handful of things that are truly non-negotiable for your business. Log every block with the input that triggered it. Those logs are the actual product here, because they show you the attacks you did not imagine, and next month's deny list writes itself from them.

    Reserve the programmable frameworks, NeMo Guardrails and its relatives, for when you have real conversational flows to constrain: topic steering, tool-call gating, structured dialogue where you need the bot to refuse to leave a lane. They are powerful and they are also a lot of configuration to maintain, so earn your way up to them.

    The uncomfortable truth is that a public embarrassment is usually a monitoring failure, not a filtering failure. The teams that get burned are not the ones without guardrails. They are the ones who set up guardrails, saw the demo work, and never looked at the logs again. A speed bump you are watching is worth more than a wall you have forgotten about.

  • How to fact-check an AI before you trust it with anything important

    The single most dangerous thing about a good AI model is how convincing it sounds when it is wrong. It does not hedge, it does not sweat, it just states the confident falsehood in the same tone as the truth. Here is how to catch that before it costs you something, without turning every answer into a research project.

  • How to write a prompt that does not waste everyone time

    Most prompt engineering advice is either obvious or superstition. You do not need a 2,000-word mega-prompt or a secret phrase that unlocks the model true power. You need to say what you want the way you would say it to a sharp, literal-minded colleague who has no context and will take you at your word.

  • Prompt engineering is not a career, and that is fine

    For about two years, "prompt engineer" was a job you could put on a resume and watch people's eyebrows go up. Six-figure listings, breathless threads about the magic phrase that cracked GPT open, whole courses selling the secret incantations. I want to be careful here, because the backlash overcorrected. Writing good prompts is a genuine skill and it will stay one. It is just not a career, and pretending otherwise did nobody any favors.

    Here is the distinction that got flattened. A skill is something you use inside a job. A career is the job. Spreadsheet formulas are a skill. "Excel engineer" was never a role, even in the years when knowing Excel cold made you far more valuable than the person next to you. Prompting is heading down the same road, and quickly.

    The tricks are decaying on purpose

    Think about what the famous prompt hacks actually were. "Let us think step by step." "You are a world-class expert." "I will tip you 200 dollars." "Take a deep breath." These worked because early models needed a nudge to behave, and people found the nudges by trial and error. They were patches for the model's weaknesses.

    But every one of those weaknesses is a bug the labs are actively fixing. Reasoning models now think step by step without being asked, because that behavior was trained in. Newer models shrug off the fake tip and the flattery because they were tuned to ignore that kind of manipulation. The clever phrase that earned you a screenshot last year does nothing this year, and that is not an accident. The whole direction of model development is to understand what you meant, so you have to say less. A skill built entirely on the model failing to understand you has a short shelf life by design.

    I have watched people memorize prompt templates the way you would memorize keyboard shortcuts, and then act surprised when a model update makes half of them pointless. The templates were never the skill.

    What actually survives

    Strip away the incantations and look at what makes one person consistently get better results than another. It is not secret words. It is that they can state what they want. They know what a good answer looks like before they ask. They give the relevant context and leave out the noise. They notice when an output is subtly wrong and can say why. They break a fuzzy goal into parts a machine can actually chew on.

    Notice that none of that is about the model. That is editing, specification, and clear thinking, the same muscles a good manager uses to brief a new hire or a good writer uses to structure an argument. Those skills were valuable before language models and they will be valuable after, because they are about knowing your own mind well enough to hand the intent to someone, or something, else.

    The parts of prompting that do stay technical are drifting toward normal engineering anyway. Structuring context, wiring up tools, chaining calls, evaluating outputs at scale, managing what goes in the window. That work is real and growing, but it looks like software work, and the people doing it call themselves engineers, not prompters.

    So what should you do with this

    Learn to prompt well. Seriously. Anyone who uses these tools daily should get fluent, the same way anyone in an office should be able to write a clear email. Fluency compounds and it is cheap to acquire. Just do not build an identity on it, and do not pay a lot for a certificate in it.

    If you want the durable version of this skill, practice saying exactly what you mean to a smart colleague who takes you completely literally and has no idea what is in your head. That is most of prompting, and it happens to be most of thinking clearly, which was always the thing worth getting good at. The models will keep meeting you halfway. Your job is to have something worth meeting them with.

  • Prompt patterns that survive contact with real work

    Once you have the basics of prompting down, the next step is not a longer list of tricks. It is a small set of reliable patterns, reusable moves that keep working on real tasks, under pressure, across model versions. These are the ones I actually reach for, stripped of the hype.

  • Temperature and top-p: the two settings most people get wrong

    Somewhere in every LLM tutorial there is a line that sets temperature to 0.7, and a remarkable number of people copy it, ship it, and never think about it again. Then the output goes weird and they have no idea which knob to turn. Temperature and top-p are the two settings that decide how the model picks each next word, they are genuinely simple once explained, and most people are using them on autopilot. Here is what they actually do.

    The model is always guessing, these settings pick how

    At every step, the model produces a ranked list of possible next tokens, each with a probability. It does not know the answer, it has a distribution over answers. Temperature and top-p are two different ways of deciding how to draw from that distribution.

    Temperature reshapes the whole distribution. Low temperature, near zero, sharpens it so the single most likely token almost always wins, which makes the output predictable and repeatable. Crank it up toward one and beyond and you flatten the distribution, giving unlikely tokens a real shot and making the output more varied and, past a point, more unhinged. At temperature zero the model is effectively deterministic: same prompt, same answer, every time.

    Top-p, also called nucleus sampling, works differently. Instead of reshaping probabilities, it draws a cutoff. Top-p of 0.9 means "consider only the smallest set of tokens whose probabilities add up to 90 percent, and ignore the long tail." The clever part is that it adapts to the model's confidence. When the model is sure, one token already holds most of the probability, so top-p samples from just a token or two. When the model is unsure and fifty tokens each hold a little, top-p keeps all fifty in play. It widens and narrows on its own.

    Where people go wrong

    The first mistake is turning both knobs at once. Temperature and top-p both constrain the same sampling step, and stacking them makes the effect of either impossible to reason about. The standard advice, which I agree with, is to move one and leave the other at its neutral setting. Pick temperature or pick top-p. Do not choreograph both and then wonder why the behavior is unpredictable.

    The second mistake is believing high temperature equals creativity. It does not. High temperature buys you randomness, and randomness is not the same thing as good ideas. Past a certain point you are not getting a more imaginative model, you are getting a model that picks worse words more often. There is a real ceiling where interesting tips over into incoherent, and it arrives sooner than people expect. If you want surprising-but-good, a modest bump plus a better prompt beats cranking the dial to the roof.

    The third mistake is silent and nasty: tuning these values on one backend and deploying on another. The OpenAI API, vLLM, and llama.cpp do not necessarily apply samplers in the same order, so the same numbers can produce different text on different stacks. Always tune against the exact backend you will actually run.

    Sane defaults to start from

    For anything where there is a correct answer, set temperature to 0. Code generation, data extraction, classification, factual questions, anything you would run twice and want the same result. Randomness here is pure downside: it introduces inconsistency across identical inputs and buys you nothing. This is the setting most people should be using far more than they do, because most real work has a right answer and they leave it at 0.7 out of habit.

    For creative writing, brainstorming, generating varied options, raise it. Somewhere around 0.7 to 1.0 is a reasonable playground, and this is genuinely where a warmer setting earns its place: you want the model to wander a little, and repeating the exact same story every time defeats the point.

    The default that ships with most APIs, around 0.7, is a compromise aimed at open-ended chat. It is a fine middle for conversation and a poor fit for either extreme. If you are extracting invoice fields at 0.7, you are inviting the occasional wrong number for literally no benefit.

    The whole thing takes five minutes to understand and saves you a lot of confused debugging. When output feels too samey, you know which way to push. When it feels unreliable and you want the same answer twice, you know to pull temperature to the floor. That is the entire skill: not memorizing magic numbers, but knowing what the two knobs move so you can reach for the right one instead of copying 0.7 from a tutorial and hoping.

  • The most useful AI skill in 2026 is knowing when to turn it off

    There is a huge industry teaching people how to use AI: prompt courses, tool roundups, productivity threads without end. Almost nobody teaches the skill that is quietly becoming more valuable than any of them: knowing when not to use it. In 2026, the people doing the best work are not the ones using AI the most. They are the ones who know when to close the tab.

  • Why the same prompt gives you a different answer every time

    You run a prompt, get a good answer, run the exact same prompt again, and get something different. Sometimes it is a rephrasing. Sometimes it is a different conclusion. If you come from normal software, where the same input gives the same output forever, this feels like the thing is broken. It is not broken. It is doing exactly what it was built to do, and understanding why will change how you use these tools.

    The model does not pick a word, it picks from a distribution

    At every step, a language model does not decide on the next word. It produces a probability for every possible next token. The word "blue" might get 60 percent, "green" 20 percent, "warm" 5 percent, and a long tail of everything else splitting the rest. Then a sampler reaches into that distribution and draws one.

    Temperature is the knob that reshapes those odds before the draw. Turn it up and the flat, unlikely options get more weight, so the output wanders and surprises you. Turn it down and probability piles onto the front-runners, so the model plays it safe. This is a feature. You want a brainstorming assistant to roam and a data-extraction call to stay boring. The variation you are seeing at normal temperature is the model exploring, on purpose.

    So the obvious move is to set temperature to 0. Now it always takes the single most likely token, greedy decoding, no dice roll. Same prompt, same answer, forever. Right?

    Temperature 0 is not the guarantee you think it is

    In practice, temperature 0 gets you close but not all the way. People assumed for years that the leftover wobble was just floating-point noise, some vague hand-wave about GPUs being messy. That answer was never satisfying, and in 2025 researchers at Thinking Machines laid out the actual culprit, and it is more interesting than randomness.

    The real cause is batch invariance, or rather the lack of it. When you send a request to a hosted model, you are not alone. The serving system bundles your request together with whatever other requests arrived at the same moment and runs them through the GPU as one batch. That batch is different every time, because it depends on who else is calling the API at that instant, something you have zero control over.

    Here is why that matters. Floating-point addition is not associative. Adding a set of numbers in one order can give a very slightly different result than adding them in another order, down in the last bits. When the batch size changes, the GPU kernels split and sum their work in a different order, so the model's internal numbers drift by a hair. Almost always that hair is invisible. But every so often two candidate tokens are nearly tied, the drift nudges one above the other, and the model picks a different word. From there the two answers diverge, because each new token conditions on the last one.

    Sit with that for a second. The nondeterminism you see is not the model being random. It is your request sharing a GPU with strangers. The cause is numerical, not magical, and it is fixable. Batch-invariant kernels that pin the reduction order now ship in serving engines like vLLM and SGLang, and with them you can get genuinely reproducible output. Most hosted APIs do not turn that on by default, because it costs a bit of throughput, so the wobble stays.

    How to actually think about it

    Stop treating a single model output as a fact and start treating it as a sample. One run tells you what the model tends to say. It does not tell you what it always says. That reframe fixes a lot of bad habits.

    If you need the same answer every time, do not lean on the model's internals to give it to you. Cache the result keyed on the input, and serve the cached copy. That is deterministic by construction and it is cheaper. If you are extracting structured data, run the call, but validate the shape and constrain the output with a schema so a reworded answer cannot break your parser. If you are evaluating a prompt, never judge it on one run. Sample it ten times and look at the spread, because the spread is the real behavior and a single lucky run is a trap that will embarrass you in production.

    And when a demo shows you one perfect output, remember what you are looking at. You are seeing one draw from a distribution, chosen and probably cherry-picked. The honest question is not whether it can produce that answer. It is how often, and what the other draws look like. Ask for a few more and you will learn more in thirty seconds than the polished screenshot will ever tell you.