Builds reliable product features on top of LLMs — prompts, tools, evals, and guardrails. Use when adding AI/LLM functionality, designing prompts or agent tools, fixing flaky model behavior, or shipping and maintaining a model-powered feature in production.
Builds reliable product features on top of LLMs — prompts, tools, evals, and guardrails. Use when adding AI/LLM functionality, designing prompts or agent tools, fixing flaky model behavior, or shipping and maintaining a model-powered feature in production.
LLM Feature Engineering
An LLM is a non-deterministic dependency — it can be wrong, slow, expensive, or manipulated.
Treating it like fetchUser(id) produces flaky, unsafe features. Engineer around its nature: define a
contract, constrain output, ground facts, measure quality with evals, handle failure
modes, and never trust raw model text as correct ([[hardening]]).
LLM features are products — users need predictable behavior, fallbacks when AI fails, and clarity
when output is machine-generated. "Demo magic" is not shipping.
Pairs with [[context-curation]] for prompt payload size, [[source-first]] for grounding, [[interface-design]]
for tool schemas, [[resilience]] for timeouts/retries, [[observability]] for cost/quality/latency,
[[test-first]] mindset for eval sets, [[incremental-delivery]] to ship slices, and [[launch-readiness]]
for gradual rollout of AI behavior.
Designing prompts, system instructions, RAG pipelines, or tool/function definitions
A model-powered feature is inconsistent, hallucinating, slow, or too expensive
Putting an LLM feature into production or preventing quality regression after prompt/model changes
Reviewing AI-related PRs for safety and contract discipline
Also ask: should this be an LLM at all? Rules, regex, search, or classical ML often beat a general
model for narrow tasks — cheaper, deterministic, auditable. Use LLM when language understanding,
open-ended generation, or flexible reasoning is genuinely required.
Skip heavy LLM engineering for one-off internal scripts with no user impact — still validate outputs
if they touch production data.
Process
Work in order. Prompt tuning before task definition is wasted iteration.
1. Define the task contract — before prompts
Write what the feature must do in testable terms ([[spec-first]]):
Field
Example
Input
User question + retrieved docs; ticket text; form fields
≥90% category match on eval set; summary contains all key facts; p95 < 3s
Failure cost
Wrong medical dose = critical; wrong emoji suggestion = low
Out of scope
Model must not execute purchases, access arbitrary data
Vague goals ("be helpful") are unmeasurable. One sentence output contract minimum.
Choose pattern:
Pattern
Use when
Avoid when
Classification / extraction
Fixed labels, fields from text
Need creative prose
Generation
Drafts, explanations, transforms
Facts without sources
RAG
Answers must cite company data
Tiny static FAQ (use search)
Tool/agent
Multi-step actions in product
Simple single API call
Hybrid
Retrieve → extract → generate with schema
Over-agent for one lookup
2. Pick model and budget — fit task to model
Don't default to the largest model:
Factor
Tradeoff
Quality
Hard reasoning, long context → larger model
Latency
Chat UX → smaller/faster or streaming
Cost
High volume → smaller model + better prompt/RAG
Determinism
Lower temperature for extraction; higher for creative drafts
Set token budgets — max input/output tokens, max retrieval chunks ([[context-curation]]).
Instrument cost per request from day one ([[observability]]).
Re-evaluate when volume grows — a cheap model at scale beats a premium model on every request.
3. Structure the prompt — role, task, format, constraints
System prompt — stable rules: role, safety boundaries, output format, what never to do.
User/content — task instance; separate from untrusted data when possible ([[hardening]]).
Effective structure:
Role: You extract order issues from support tickets.
Task: Return category and one-line summary.
Output: JSON only, schema: { "category": enum, "summary": string, "confidence": 0-1 }
Rules:
- If unsure, category "unknown" and confidence < 0.5
- Do not invent order IDs not in the ticket
- Max summary 200 chars
Examples:
Input: "..." → Output: { ... }
Few-shot examples — 2–5 representative cases, including edge cases (empty input, ambiguous).
Update examples when evals fail — don't grow prompts without measurement.
Keep prompts minimal ([[context-curation]]) — every token is cost, latency, and distraction.
4. Constrain and validate output — never trust raw text
Model text is untrusted input to your app ([[hardening]]):