Prompt Engineering for Production: Patterns Beyond Basic Instructions
Introduction
Prompt engineering in production is not about clever one-liners—it is systems design for nondeterministic models. You define inputs, constraints, output schemas, failure modes, evaluations, and versioning so LLM features behave reliably across model updates and edge cases.
This guide covers structured prompts, few-shot examples, chain-of-thought with guardrails, tool calling patterns, prompt templates, A/B testing, and building eval pipelines—the practices that separate demos from shipped products.
Table of Contents
- Production vs Playground Prompting
- Structured Output and JSON Mode
- Few-Shot and Example Selection
- Chain-of-Thought and Reasoning
- System Prompt Architecture
- Tool Calling and Agents
- Evaluation and Versioning
- Best Practices
- Common Mistakes
- Interview Questions
- Summary
- References
Production vs Playground Prompting
Playground prompts assume:
- Single user, manual retry
- No PII logging constraints
- Latest model, fixed temperature
Production requires:
- Deterministic-ish outputs (low temperature, structured formats)
- Latency and cost budgets
- Regression tests when prompts or models change
- Safety filters and injection resistance
Treat prompts as configuration—store in git, review in PRs, deploy with version tags.
Structured Output and JSON Mode
Free-form text breaks downstream parsers. Use schema-constrained outputs:
const response = await openai.chat.completions.create({
model: "gpt-4o",
messages: [
{
role: "system",
content: "Extract meeting action items. Respond only with valid JSON.",
},
{
role: "user",
content: transcript,
},
],
response_format: {
type: "json_schema",
json_schema: {
name: "action_items",
schema: {
type: "object",
properties: {
items: {
type: "array",
items: {
type: "object",
properties: {
task: { type: "string" },
assignee: { type: "string" },
due_date: { type: "string" },
},
required: ["task"],
},
},
},
required: ["items"],
},
},
},
});
Validate with Zod after parse—models still occasionally violate schema under stress.
Few-Shot and Example Selection
Examples teach format and tone:
System: Classify support tickets.
User: Example 1: "Can't login" → category: account
User: Example 2: "Export CSV broken" → category: bug
User: Now classify: "How do I upgrade plan?"
Dynamic few-shot: retrieve similar labeled examples from a vector store (RAG over examples) rather than static list—improves accuracy on diverse inputs.
Keep examples representative and balanced—skewed examples bias classification.
Chain-of-Thought and Reasoning
For math, logic, and multi-step tasks, explicit reasoning helps—then strip reasoning from user-facing output:
Think step by step in a <reasoning> block, then give final answer in <answer>.
Guardrails:
- Cap reasoning length
- Refuse to expose reasoning to end users if policy requires
- Use reasoning models (o-series) when budget allows—less prompt hacking
For production, prefer verification step—second pass checks answer against constraints.
System Prompt Architecture
Layer prompts:
[LAYER 1: Role and policy]
You are a billing assistant. Never disclose other customers' data.
[LAYER 2: Task instructions]
Help users understand invoices. Escalate disputes to human.
[LAYER 3: Output format]
Use markdown. Max 200 words.
[LAYER 4: Dynamic context]
User plan: Pro. Current invoice: {{invoice_json}}
Inject context last—models weight recent tokens heavily. Sanitize {{invoice_json}}—users can inject via uploaded content (prompt injection).
Tool Calling and Agents
Let models call functions instead of hallucinating data:
const tools = [
{
type: "function",
function: {
name: "get_order_status",
description: "Fetch order status by order ID",
parameters: {
type: "object",
properties: { order_id: { type: "string" } },
required: ["order_id"],
},
},
},
];
Execute tools server-side with authorization—model suggests call; your code validates user can access order_id.
Limit agent loops—max iterations, timeout, cost ceiling.
Evaluation and Versioning
Build eval datasets:
- Golden inputs with expected outputs (exact or rubric-scored)
- Edge cases: empty input, adversarial injection, non-English
- Regression suite run on every prompt/model change
const results = await runEval({
promptVersion: "v2.3.1",
model: "gpt-4o",
cases: goldenSet,
scorer: semanticSimilarity,
});
if (results.passRate < 0.95) blockDeploy();
Track metrics: accuracy, latency p95, token cost, refusal rate.
Best Practices
- Version prompts like code—
prompts/support/v2.yaml. - Structured outputs with schema validation.
- Separate system and user content—never concatenate unsanitized user text into system role without delimiters.
- Log prompt hash + model, not always full PII payloads.
- Human review queue for high-stakes outputs.
- Fallback when model fails—cached response, simpler model, or human.
Common Mistakes
- Brittle regex on free-form LLM output instead of JSON schema.
- Huge prompts—every token costs money and adds latency.
- No evals—silent quality regression on model deprecation.
- Trusting model arithmetic—use code execution or calculators.
- Prompt injection ignored—user content in system prompt.
- Temperature > 0 for extraction tasks needing consistency.
Interview Questions
- How is production prompt engineering different from demos?
- Explain few-shot prompting and when it fails.
- How to get reliable JSON from LLMs?
- What is prompt injection and mitigations?
- How do you evaluate prompt changes?
- Tool calling vs fine-tuning—tradeoffs?
- Chain-of-thought risks in production?
- How to handle model version upgrades?
Multimodal and Vision Prompts
Production vision pipelines separate system constraints from image context:
const response = await client.chat.completions.create({
model: "gpt-4o",
messages: [
{
role: "system",
content: "Extract text from invoice images. Output JSON only.",
},
{
role: "user",
content: [
{ type: "text", text: "Extract vendor, date, total." },
{ type: "image_url", image_url: { url: signedImageUrl } },
],
},
],
});
Resize images before upload—token cost scales with resolution. Validate extracted amounts against business rules in code, not prompts alone.
Prompt Injection Defenses
Layer defenses:
- Input sanitization — strip control characters
- Delimiter blocks — wrap user content in
<user_input>tags; instruct model to treat as data - Output filtering — block PII patterns, secrets, competitor names per policy
- Separate models — cheap classifier flags injection attempts before main call
- Least privilege tools — tools expose minimal data per user session
No defense is perfect—monitor for jailbreak attempts and rotate prompts when attacks adapt.
Cost Optimization
- Cache embeddings and completions for identical inputs
- Route simple queries to smaller models with escalation on low confidence
- Batch non-urgent jobs off peak hours
- Track cost per feature in product analytics—not only engineering dashboards
Prompt length directly maps to dollars at scale; trim redundant examples and verbose system prompts during quarterly audits.
Template Libraries and Version Control
Store prompts as files, not scattered strings:
prompts/
support/
v1.0.0/system.txt
v1.0.0/extract_ticket.yaml
v2.0.0/system.txt
Load by version in config; A/B test v2 on 10% traffic before full rollout. Git history provides audit trail for prompt changes linked to quality regressions.
Pair with feature flags (LaunchDarkly, Unleash) for model and prompt experiments without redeploying application code.
Reducing Hallucination in Production
Layered approach:
- Retrieve authoritative context (RAG)
- Constrain output format (JSON schema)
- Require citations in prompt
- Post-generation groundedness check
- Block publish if confidence below threshold
if (groundednessScore < 0.7) {
return { status: "needs_review", draft: completion };
}
Human-in-the-loop is acceptable for high-stakes outputs—legal, medical adjacency, financial advice.
Summary
Production prompt engineering combines structured outputs, layered system prompts, tool calling with auth, eval pipelines, and strict versioning. Treat nondeterminism as a risk to manage—not a surprise to debug in prod. Measure quality, cost, and latency on every change.