Prompt Engineering for Production — Going Beyond the Basics
9minTL;DR: A deep dive into prompt engineering for production systems: tokenization, system vs user prompts, few-shot learning, chain-of-thought, structured outputs, testing for consistency, and prompt injection defense.
Prompt engineering is the discipline of writing clear, testable specifications for a next-token predictor. It is not about finding magic incantations — it is about understanding how the model processes your input and designing your prompt to work with, not against, that processing. This guide goes deeper than the basics: it covers tokenization mechanics, the system/user prompt distinction, few-shot patterns, chain-of-thought tradeoffs, structured output schemas, testing for reliability, and security against injection attacks.
How Tokenization Explains LLM Failure Modes. A tokenizer converts text into a sequence of integers (tokens) that the model processes. The key insight: tokens are NOT characters. The word "hello" is one token, but "HelloWorld" splits into multiple tokens. Punctuation, whitespace, and case changes affect tokenization. This explains several surprising LLM failure modes that look like intelligence gaps but are actually tokenization artifacts:
Understanding tokenization directly affects prompt design: keep numbers small and human-readable, ask for step-by-step calculation for arithmetic, and when counting letters or words, ask the model to write code to do it rather than doing it directly.
System Prompts vs User Prompts. The distinction matters architecturally, not just stylistically. The system prompt sets the model's behavior, tone, and constraints — it is the "operating system" for the conversation. The user prompt is the specific task within that operating system. System prompts are typically more structured, persistent across turns, and define rules that should not be overridden by user input. User prompts are the actual work being done.
Put invariant rules (format, tone, constraints) in the system prompt. Put the variable task in the user prompt. Structure your user prompt like a function call: inputs, expected output, edge cases.
Few-Shot Prompting — When Examples Outperform Instructions. For many tasks, showing the model examples of the desired input/output pattern is more effective than describing the pattern in words. This is especially true for: formatting tasks (extract fields into JSON), classification tasks (categorize this email as spam/not-spam), tasks where the boundary is fuzzy (this tone is professional vs casual), and tasks where the output must follow a specific but hard-to-describe structure.
Choose 2-5 diverse examples that cover edge cases (null values, unusual formats, boundary conditions). Too many examples waste context and may confuse the model if they contradict each other.
Chain-of-Thought — When to Use It, When to Skip It. Chain-of-thought (CoT) prompts the model to reason step by step before answering. It dramatically improves accuracy on math, logic, multi-step reasoning, and tasks requiring intermediate computations. But CoT is not free — it costs 2-10x more tokens per query and adds latency proportional to the reasoning steps. Use CoT when: correct reasoning requires intermediate steps (math, code generation, multi-hop QA), the task involves conditional logic where later steps depend on earlier results, or you need the model to show its work for auditability. Skip CoT when: the task is a simple classification or extraction (positive/negative sentiment, yes/no, field extraction), the output format is strictly constrained and reasoning adds no value, or latency and cost are the primary constraints and accuracy is already acceptable without reasoning.
When CoT is justified, use the "Think step by step" phrasing or, for more control, provide an explicit reasoning template: "First, identify the problem type. Second, recall relevant facts. Third, apply the facts to solve it. Fourth, verify the answer. Finally, output the answer in this format: ..."
Structured Outputs via Function Calling and JSON Schema. The most reliable way to get consistent, parseable output from an LLM is to constrain it with a schema — not to ask nicely in a prompt. Both OpenAI and Anthropic offer function calling / tool use APIs where you define a JSON schema for the output and the model returns a structured object that conforms to it. This eliminates formatting errors, makes parsing trivial, and gives you validation for free.
Testing Prompts for Consistency. A prompt that works once in a demo is not a production prompt. LLMs generate differently on every call (temperature > 0), so you must test your prompt for consistency across repeated runs. Build a test harness: define 10-20 test inputs including edge cases (empty input, very long input, adversarial input, input with special characters, input that triggers each variant of the expected output), run each input through the prompt 3-5 times, and verify that outputs are valid JSON (if schema-constrained), contain required fields, and have consistent value formats. Automate this in CI. A prompt that fails one time out of twenty in testing will fail one thousand times out of twenty thousand in production.
Prompt Injection as a Security Concern. Prompt injection occurs when untrusted content (user input, retrieved documents, tool outputs) contains instructions that override or subvert your system prompt. This is not a theoretical concern — it is a real attack surface, and it is the most common way production AI applications get exploited.
Further Reading.
- Anthropic Prompt Engineering Documentation
- OpenAI Prompt Engineering Guide
- OpenAI Structured Outputs Guide
- Anthropic Prompt Injection Defense Guide
A deep dive into prompt engineering for production systems: tokenization, system vs user prompts, few-shot learning, chain-of-thought, structured outputs, testing for consistency, and prompt injection defense.