Harness Engineering, Not Just Prompt Engineering
The evolution from single-inference optimization to system-level reliability.
The Evolution of AI Engineering
The field has evolved through three distinct phases:
- 2022-2024: Prompt Engineering β "What should I ask?"
- 2025: Context Engineering β "What information should I provide?" (Andrej Karpathy)
- 2026: Harness Engineering β "What system should I build?" (Mitchell Hashimoto, Anthropic, OpenAI)
What Is Harness Engineering?
Harness engineering is the discipline of building the infrastructure layer that makes AI agents reliable in production. It covers everything the prompt does not: tool integration, verification loops, state management across sessions, cost controls, observability, evaluation pipelines, and graceful degradation.
OpenAI's Harness team (Feb 2026): Built and shipped an internal beta product with ~1 million lines of agent-generated code across ~1,500 pull requests, with zero lines of manually-written code over five months. The secret wasn't a better modelβit was the system wrapped around it.
Five-Layer Architecture
| Layer | Purpose | What Breaks Without It |
|---|---|---|
| 1. Orchestration | Controls agent execution flow | Agent runs without direction or termination |
| 2. Context Management | Curates what the model sees | Hallucination, context rot, lost state |
| 3. Tool Integration | Connects agent to external systems | Tool call failures cascade silently |
| 4. Verification | Validates outputs at each step | Wrong results delivered with confidence |
| 5. Operations | Monitors, controls costs, handles failures | Runaway costs, silent degradation, no debugging |
Key Insight
Prompt engineering optimizes a single inference. Harness engineering optimizes the system that runs many inferences reliably over time. β Harness Engineering Academy
Real-World Example
LangChain's coding agent jumped from 52.8% to 66.5% on Terminal Bench 2.0 (Top 30 β Top 5) by changing nothing about the modelβonly the harness.
Learn More
For a structured deep dive into this discipline, check out the open-source Learn Harness Engineering course by WalkingLabs. It covers the full stack: orchestration patterns, tool integration, verification loops, cost controls, and evaluation pipelines with practical code examples.
Prompt Caching vs. Semantic Caching Tradeoffs
Three layers of caching that can reduce costs by up to 93%.
Three-Layer Caching Hierarchy (2026 Standard)
| Layer | What is Cached | Mechanism | Cost Impact | Latency Impact |
|---|---|---|---|---|
| L1: Provider Prompt Caching | Processed KV states for shared prompt prefixes | Exact/prefix match | 50-90% discount on cached input tokens | Reduces TTFT |
| L2: Semantic Caching | Query-response pairs via vector embeddings | Similarity search (cosine > 0.85-0.95) | Eliminates LLM call entirely (100% savings) | 2.5x-15x faster |
| L3: Response/Edge Caching | Exact response hash | Exact string match | Zero cost on hit | Sub-10ms |
Prompt Caching (L1)
- Anthropic: Explicit
cache_controlbreakpoints. Cache writes cost 25% extra, break-even at 2-3 requests. 90% discount on cached reads. - OpenAI: Automatic prefix detection for prompts over 1024 tokens. No explicit markers β the API detects and reuses matching prefixes automatically. Cached tokens are discounted ~50%.
- Google Gemini: Context caching API β explicitly create a cache resource from content, then reference it in requests. TTL up to 48 hours with periodic access.
- DeepSeek: Disk-based prompt caching with automatic prefix reuse. Context cached to NVMe drives and shared across requests.
- Key design rule: Stable content at the front (system prompts, tool definitions, long documents), variable content at the end (user input, latest messages).
Infrastructure: No external infrastructure needed β this is a provider-side feature. You just structure your prompts correctly. For maximum reuse, place identical system messages and shared context at the very beginning of every request. In multi-tenant systems, put per-tenant instructions before per-user history. Monitor cache hit rate via provider dashboards (Anthropic shows cache_read_input_tokens in usage, OpenAI includes prompt_tokens_details.cached_tokens).
Semantic Caching (L2)
- Production hit rates: 10-20% for open-ended chat, 40-70% for FAQ/support, 60-85% for structured workflows.
- Risk: False positives β semantically similar queries may have different correct answers. Teams monitor cache hit rate + false positive rate separately.
Infrastructure: Requires a vector database plus an embedding model.
- Vector DBs:
pgvector(PostgreSQL extension, zero new infra),Pinecone(managed, serverless),Weaviate(Hybrid search),Qdrant(high-perf Rust, on-prem friendly),Milvus(billion-scale). - Libraries:
LangChain CacheBackedEmbeddings,GPTCache(dedicated caching layer with eviction policies),RedisVL(Redis + vector search in one). - Pattern: On every query, compute its embedding (e.g.,
text-embedding-3-small), search vector DB for nearest neighbors within a cosine similarity threshold (typically 0.85-0.95), return cached response if found. Embeddings are cheap (~$0.02/1M tokens), making this cost-effective even at low hit rates. - Eviction strategy: TTL-based (e.g., 24h for chat, 7d for docs) or LRU with a memory cap. Stale cache is worse than no cache β expired facts poison trust.
Response/Edge Caching (L3)
L3 is the simplest and fastest layer β hashing the full request (prompt + model + parameters) and storing the exact response.
- Infrastructure: A key-value store (Redis, Memcached) or a CDN edge layer (Cloudflare Workers KV, Fastly KV Store). The key is typically
sha256(model + prompt + temperature + max_tokens). No embedding model needed, no vector search. - Latency: Sub-10ms on cache hit β orders of magnitude faster than any LLM call.
- Hit rate: Low for open-ended generation (every response is unique), medium for RAG with stable documents (same doc + same question = same answer), high for deterministic tasks (classification, extraction with temperature=0).
- Tradeoff: The biggest downside is cache staleness. When the underlying model is updated (e.g., GPT-4o gets a new checkpoint), all cached responses become stale. Including the model name in the cache key creates a hard version split, which hurts hit rate. Mitigations: per-model cache namespaces, TTL-based invalidation after model updates, or periodic re-sampling of cached responses against a judge model.
- Best for: High-traffic endpoints with deterministic behavior β classification, structured extraction with temperature=0, fact-based Q&A over static documents, cost-sensitive internal tooling APIs.
Real-World Math
A system processing 500K calls/day:
| Configuration | Daily Cost | Savings |
|---|---|---|
| Baseline (no cache) | $7,800/day | β |
| + L1 Prompt Cache | $2,800/day | -64% |
| + L2 Semantic Cache | $1,150/day | -85% |
| + L3 Edge Cache | $515/day | -93% |
Tradeoff Summary
Prompt Caching
Zero operational overhead, but only handles identical prefixes. Use for long system prompts, RAG contexts.
Semantic Caching
Requires vector DB + embedding model, catches paraphrases, but needs similarity threshold tuning. Use for user-facing chat, support bots.
Production Pattern
Stack all three. Exact-match first (fastest), semantic second (broader), prompt caching third (for novel queries).
KV Cache Management at Scale
The single biggest memory cost in long-context LLM serving.
What Is the KV Cache?
In transformer models, every token generation step requires attending to all previous tokens in the sequence. Naively, this means recomputing the key (K) and value (V) matrices for the entire context on every new token β an O(nΒ²) operation.
The KV cache is a simple but critical optimization: after computing K and V for each token once during the prefill phase (when the prompt is first ingested), these matrices are stored in GPU memory. During decoding (token-by-token generation), only the new token's Q, K, V are computed and appended to the cached K and V, avoiding recomputation of the entire history. This turns generation from O(nΒ²) compute to O(n) memory.
Think of it like a search engine that builds an index once and reuses it for every search, instead of scanning all documents from scratch each time. The tradeoff: you trade compute for GPU memory β and at long contexts (100K+ tokens), this memory cost dominates everything else.
The Problem
For Llama 3.1 70B at 131K context, the KV cache alone is 43 GB per requestβbigger than the model weights at FP8. Every modern serving engine (vLLM, SGLang, TensorRT-LLM) revolves around managing it.
Core Techniques
PagedAttention (vLLM)
- Inspired by OS virtual memory paging
- KV cache partitioned into fixed-size blocks (default 16 tokens)
- Blocks stored non-contiguously, allocated on-demand
- Result: Near-zero memory waste, 2-4x throughput improvement vs. contiguous allocation
Automatic Prefix Caching (vLLM)
- Hash-based KV block sharing across requests
- System prompts, tool definitions shared via reference counting
- TTFT speedup on prefix-sharing workloads: 3-10x
Disaggregated Prefill/Decode (P/D Separation)
- Prefill GPUs: Handle prompt processing (compute-bound)
- Decode GPUs: Handle token generation (memory-bound)
- KV cache shipped over NVLink/RDMA between them
- Result for long-prompt workloads: 2-3x throughput, 2x lower decode latency
KV Cache Quantization
- FP8 KV cache: 50% memory reduction, 30% speedup on Hopper GPUs
- INT4/INT8 hierarchical quantization for speculative decoding (QuantSpec)
Production Configuration (vLLM)
vllm serve meta-llama/Llama-3.1-70B-Instruct \
--tensor-parallel-size 4 \
--kv-cache-dtype fp8_e5m2 \
--enable-prefix-caching \
--block-size 16 \
--max-num-seqs 256
Advanced: Disaggregated Serving
vLLM's MooncakeConnector, BanaServe, and Global KV Cache Store sharing across prefill nodes with layer-wise overlapped transmission hides communication latency.
Speculative Decoding vs. Quantization
Two speedups, two different leversβand a critical interaction to watch.
Speculative Decoding
Uses a small "draft" model to propose K candidate tokens, then a large "target" model verifies them in parallel.
Speedups Achieved (2026)
| Method | Speedup | Notes |
|---|---|---|
| Basic Speculative | 2-3x | Requires separate draft model |
| EAGLE-3 | 2.5-3x | No separate model needed |
| Apple ReDrafter | 2.8x | RNN-based draft head |
| PEARL | 4.43x vs AR | Adaptive draft length |
When to use: Decode-heavy workloads, long outputs, high acceptance rates possible.
Quantization
Reduces numerical precision to shrink memory footprint and accelerate operations.
2026 Standards
| Format | Size Factor | Speedup | Quality | Use Case |
|---|---|---|---|---|
| FP8 (Hopper) | 0.5x | 1.3x | ~99% | Production GPU serving |
| AWQ INT4 | 0.25x | 2.0x | ~95% | Creative writing, coding |
| GPTQ INT4 | 0.125x | 3.5x | ~90% | Max throughput |
The Critical Interaction
Research (Zhang et al., 2025) reveals a fundamental tension:
- Speculative decoding trades memory for speed (maintaining draft + target models)
- Quantization trades precision for memory savings
- Finding: Tree-style verification (EAGLE-2) undermines memory bandwidth benefits of 4-bit weight quantization. The verification-to-decoding time ratio of W4A16 reaches 1.8 vs. ideal 1.0.
Production Guidance
If model barely fits in memory β quantize first. If decode is your bottleneck and quality acceptable β speculative decoding. Combining both: Requires careful profiling. The combined eval must show real improvement in cost-per-accepted-answer and latency-inside-SLO.
Structured Output Failures & Fallback Chains
From JSON mode to constrained decoding: building resilient extraction pipelines.
Three Eras of Structured Output
| Era | Approach | Failure Rate |
|---|---|---|
| 2023 | JSON Mode | 5-10% |
| 2024 | Schema Enforcement | <0.3% |
| 2025-2026 | Constrained Decoding | <0.1% |
Failure Modes (Even with Strict Mode)
- Truncation:
finish_reason="length"cuts mid-JSON - Refusals: Safety filters return
refusalfield + nullparsed - Semantic drift: Schema-compliant but semantically wrong output
- Schema compilation errors: Deep recursion, large enums cause 400 errors
Production Fallback Chain
Level 1: Native structured output (OpenAI parse/Claude tool_use strict)
β failure
Level 2: Retry with validation feedback (Instructor library)
β failure
Level 3: Fallback to simpler schema (cheaper model)
β failure
Level 4: Unstructured extraction + regex/secondary model
β failure
Level 5: Return partial data with _extraction_failed: true
Key Metrics to Track
Schema Validation Failure Rate
Should be <1% with constrained decoding
Retry Rate
0.5-2% baseline normal, >5% signals prompt drift
Semantic Error Rate
Requires LLM-as-judge or human spot-checks
Evals: LLM-as-Judge + Human Evals
The evaluation stack that separates prototypes from production systems.
The Evaluation Stack (2026)
Offline Evals
- Golden set CI: 50-200 hand-labeled examples, run on every prompt change
- Regression blocking: Deploy blocked if pass rate < 95%
Online Evals
- LLM-as-judge sampling 5-10% of production traffic
- Real-time quality scoring with lightweight models
Human Evals
- Spot-check 5-10% of judge verdicts
- Continuous calibration against human labels
LLM-as-Judge Patterns
| Pattern | Description | Best For |
|---|---|---|
| Pointwise | Score single output against rubric (1-5 scale) | Overnight dashboard |
| Pairwise | Compare two outputs, pick winner | Release-gate decisions |
| Reference-based | Score against gold standard answer | When gold data exists |
Known Biases (Must Mitigate)
- Position bias: Judge prefers first/last option in pairwise
- Verbosity bias: Longer outputs rated higher
- Self-preference bias: Judge rates its own family higher
Mitigation Strategies
Both-Directions Pairwise
Run A-then-B and B-then-A, only count if both agree
Ensemble of Judges
3-5 different models, majority vote
Continuous Calibration
Sample 5-10% for human re-grading, track agreement
Distilled Judges (2026 Breakthrough)
Galileo Luna-2 (3B/8B)
Achieves 0.88-0.95 accuracy on agentic evaluation tasks with 97% cost reduction vs. GPT-4-based evaluation.
Production Boundaries for Judge Checks
| Boundary | Judge Type | Rationale |
|---|---|---|
| Before user-facing output | Fast inline judge (β€8B) | Visible to user; latency budget 50-200ms |
| Before irreversible tool calls | Thorough judge (may use large model) | Cost of error is high; extra latency acceptable |
| On memory writes | Lightweight factuality check | Bad memory compounds across future sessions |
Cost Attribution Per Feature, Not Just Per Model
FinOps for LLMs: from monthly invoices to per-feature unit economics.
The Problem
OpenAI/Anthropic dashboards show spend by API key and model. They do not show spend by your feature, route, customer ID, or environment. A $48K/month bill with no per-feature breakdown is unmanageable.
The Four Levers of LLM FinOps
1. Tag Every Call
feature_id, tenant_id, prompt_version, request_id
2. Count Tokens Authoritatively
Use provider response usage fields, not tiktoken estimates
3. Aggregate Per Feature
Daily rolls, alerts at 50%/80%/100% of budget
4. Enforce Per-Feature Budgets
Hard stops at the gateway level
Attribution Schema (Production Standard)
{
"request_id": "uuid",
"feature": "support-chat",
"route": "/api/v1/chat/answer",
"tenant_id": "cust_4291",
"model": "gpt-5.5",
"input_tokens": 180,
"output_tokens": 892,
"cached_tokens": 12000,
"cost_usd": 0.045672,
"prompt_version": "summary_v3"
}
Cost Per Action (The Real Metric)
Don't track cost per requestβtrack cost per business outcome:
- Devtools: cost per accepted suggestion
- Support: cost per resolved ticket
- Sales: cost per qualified lead
Real-World ROI
A team starting at $48K/month typically lands at $18K-$24K after 60 days through:
- Per-feature dashboard (identify top 3 features by spend)
- Model routing (Haiku-first with Sonnet fallback for top 3 features)
- Per-feature budgets with hard caps
Agent Guardrails & Loop Budgets
An agent without guardrails is just a while loop with a credit card.
The Core Problem
Anthropic's data: agents consume ~4x more tokens than standard chat. Multi-agent systems push that to ~15x.
Guardrail Layers
| Layer | Control |
|---|---|
| Input | Prompt injection screening, sensitive data detection |
| Planning | Task scope, allowed tools, required approval |
| Tool call | Authorization, schema validation, rate limits |
| Observation | Sanitize tool output, detect malicious instructions |
| Memory | Tenant isolation, secret exclusion |
| Output | Policy checks, citations, PII screening |
| Loop | Budgets, progress checks, recursion limits |
Budget Dimensions
- Max steps per run
- Max tool calls
- Max input/output/total tokens
- Max wall-clock time
- Max retries per tool
- Max spend ($)
- Max repeated action fingerprints
Loop Detection Signals
Repeated Actions
Same tool name with similar arguments
No Progress
No new facts added to state
Cost Bleed
Token spend increasing while task state unchanged
Runtime Budget Enforcement (Reserve-Commit Pattern)
1. Reserve β Before expensive action, atomically lock estimated budget
2. Execute β Only if reservation succeeded
3. Commit β Report actual cost, return difference to pool
4. Release β On failure/cancellation, return reserved amount
Real-World Example
A runaway loop burning $800 in 4 minutes is stopped at attempt 12 when the reservation exceeds remaining budget.
LLM Observability as a First-Class Discipline
Why traditional APM is insufficient for AI systems.
Why Traditional APM Is Insufficient
Traditional monitoring tracks: latency, error rate, throughput (binary: worked/failed). LLM systems can have perfect uptime while producing garbage output.
The Five Pillars (2026 Standard)
1. Tracing
Full prompt β completion β tool call β eval trace
2. Evals
Quality scoring against rubrics
3. Metrics
Token usage, cost per request, latency decomposition
4. Prompt Management
Versioning, A/B testing
5. Dataset Curation
Production traces β eval datasets β fine-tuning corpora
Critical Metrics by Category
| Category | Metric | Why It Matters |
|---|---|---|
| Performance | TTFT (Time to First Token) | User-perceived responsiveness |
| TPOT (Time Per Output Token) | Streaming smoothness | |
| P50/P95/P99 Latency | Tail latency is the user experience | |
| Quality | Online eval scores | Production quality monitoring |
| Hallucination rate | Safety signal | |
| Retrieval relevance scores | Context quality over time | |
| Cost | Tokens per request | Budget tracking and anomaly detection |
| Cost per request by model | Financial monitoring | |
| Cache hit rate | Cache effectiveness |
Sampling Strategy
- 100% capture of errors, slow traces, low-eval traces
- 10% of successes
- 1% of fast paths
- Never head-sample on input aloneβtail-based sampling only
OpenTelemetry GenAI Semantic Conventions
Standard span kinds: LLM, EMBEDDING, RETRIEVER, RERANKER, TOOL, AGENT, GUARDRAIL, EVALUATOR
Model Routing & Graceful Fallback Logic
Treating LLM selection as a runtime dispatch decision.
Routing Is a System Design Problem
Not a config option. The routing layer lives in the request path, evaluating signals to dispatch to the right model.
Three-Stage Production Routing
- Classify: Task type, complexity, urgency (heuristic or lightweight model)
- Select: Apply routing policies against model capabilities and system state
- Execute: With failover chain
Routing Signals
Task Complexity
Simple factual lookup vs. multi-step reasoning
Latency Budget
Interactive (sub-second TTFT) vs. background
Cost Budget
Remaining allocation for this feature/tenant
System Load
Current provider health, queue depth
Fallback Cascade (Five Levels)
Level 1: Frontier model (primary) β Claude Sonnet, GPT-4
β (throttle/latency spike/error rate > threshold)
Level 2: Cheaper model (same provider) β Claude Haiku, GPT-4o-mini
β (cache miss)
Level 3: Semantic cache hit β zero cost, 52ms latency
β (miss)
Level 4: Cross-provider fallback β different provider, same tier
β (all models unavailable)
Level 5: Deterministic fallback β rules, templates, lookup tables
Circuit Breaker Pattern
- Closed: Normal operation
- Open: Skip provider after failure rate exceeds threshold (e.g., 20% in 60s)
- Half-open: Probe request tests recovery
Critical Design Decisions
Error Classification Drives Routing
400 (malformed prompt) β don't retry; 429 (rate limit) β exponential backoff; 503 (overload) β skip immediately. Streaming failures don't compose: cannot switch providers mid-stream without client buffering.
Knowing When to Fine-Tune vs. In-Context Learning
The decision framework that prevents expensive missteps.
The Decision Framework
| Dimension | Fine-Tuning | In-Context Learning |
|---|---|---|
| Setup time | Days to weeks | Hours or less |
| Upfront cost | High (compute + data) | Low |
| Per-call cost | Lower (shorter prompts) | Higher (longer prompts) |
| Consistency | Very high (baked into weights) | Moderate (prompt-dependent) |
| Flexibility | Low (re-train to change) | High (change prompt anytime) |
| Best for | Stable, high-volume, specific behavior | Flexible, exploratory, fresh data |
What Fine-Tuning Actually Does
Fine-tuning changes behavior, not facts:
- β Style/tone adaptation
- β Output format/schema compliance
- β Domain-specific classification/extraction
- β Teaching new knowledge (produces confident hallucinations)
- β Staying current (requires re-training when facts change)
What In-Context Learning Does
- β Rapid iteration, no training pipeline
- β Fresh external data (RAG)
- β Dynamic behavior changes
- β Token cost scales with example count
- β Context window limits
The Hybrid: Augmented Fine-Tuning
Google DeepMind/Stanford, 2025:
- Use ICL to generate expanded, diverse training examples
- Fine-tune on the augmented dataset
- Result: Better generalization than either ICL or standard fine-tuning alone
Practical Decision Tree
When to Fine-Tune (Checklist)
- β₯500-1,000 high-quality labeled examples
- Task is about behavior/format, not fact retrieval
- Running >100K inferences/month (token cost math favors fine-tuning)
- Consistency is non-negotiable (medical, financial, legal)
- Clear, measurable improvement target
When NOT to Fine-Tune
- Task involves reasoning over documents that change daily β Use RAG
- Prototyping/experimenting β Use ICL
- Only have 50 examples β Use ICL until you have more data
- Trying to teach the model "company knowledge" β Use RAG + prompt caching
The Golden Rule
Fine-tune behavior, not knowledge. This single rule prevents most fine-tuning disasters.
Summary: The Production AI Engineering Mindset (2026)
The teams winning in production right now share these traits:
Invest in harness engineering, not just prompts. The benchmark chasers stare at leaderboards; the winners stare at context windows, tool lists, and constraint architectures.
Stack caching layers. Prompt caching + semantic caching + edge caching = 70-93% cost reduction.
Treat KV cache as a first-class resource. PagedAttention, prefix caching, FP8 quantization, and disaggregated serving are table stakes at scale.
Validate combinations, not assume them. Speculative decoding + quantization can conflict; profile before combining.
Build fallback chains, not single points of failure. Five levels of degradation from frontier model to deterministic rules.
Instrument before optimizing. Per-feature cost attribution, full tracing, and eval pipelines are prerequisites, not nice-to-haves.
Choose the right customization tool. ICL for speed and flexibility, fine-tuning for stable behavior at scale, RAG for factsβand often all three combined.