LLM Context Engineering
Design effective context windows — managing conversation history, injecting knowledge, handling long documents, and optimizing token budgets.
Real-World Scenario
A customer support LLM handles queries about a 500-page technical manual. Stuffing the full manual into the context is expensive and causes the “lost in the middle” problem. Context engineering solves this: retrieve the 3 most relevant sections, format them clearly, inject them in the right order, and give the model explicit instructions about how to use them.
Structuring the System Prompt
import anthropic
from datetime import datetime
client = anthropic.Anthropic()
def build_system_prompt(
persona: str,
capabilities: list[str],
constraints: list[str],
knowledge_context: str = "",
output_format: str = "",
) -> str:
"""Build a well-structured system prompt."""
sections = [f"# Role\n{persona}"]
if capabilities:
cap_list = "\n".join(f"- {c}" for c in capabilities)
sections.append(f"# Capabilities\n{cap_list}")
if constraints:
con_list = "\n".join(f"- {c}" for c in constraints)
sections.append(f"# Constraints\n{con_list}")
if knowledge_context:
sections.append(f"# Context\n{knowledge_context}")
if output_format:
sections.append(f"# Output Format\n{output_format}")
sections.append(f"# Current Date\n{datetime.now().strftime('%Y-%m-%d')}")
return "\n\n".join(sections)
# Example: support agent system prompt
system = build_system_prompt(
persona="You are a technical support specialist for CloudDB, an enterprise database product.",
capabilities=[
"Answer questions about CloudDB configuration and usage",
"Diagnose connection and performance issues",
"Guide users through step-by-step troubleshooting",
],
constraints=[
"Only provide information specific to CloudDB — do not compare to competitors",
"Escalate billing questions to the sales team ([email protected])",
"Never share internal pricing tiers or discount structures",
],
knowledge_context="CloudDB version 4.2 was released on 2025-03-01. Major changes: new indexing engine, deprecated XML support.",
output_format="Use numbered steps for procedures. Use code blocks for configuration. Be concise.",
)
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=512,
system=system,
messages=[{"role": "user", "content": "How do I optimize slow queries in CloudDB?"}]
)
print(response.content[0].text)
Managing Long Conversation History
import anthropic
from dataclasses import dataclass, field
client = anthropic.Anthropic()
@dataclass
class ContextManager:
"""Manages context window usage with summarization and trimming."""
max_context_tokens: int = 100_000 # leave headroom below model limit
messages: list[dict] = field(default_factory=list)
summaries: list[str] = field(default_factory=list)
def estimate_tokens(self, messages: list[dict]) -> int:
"""Rough token estimate: 4 characters ≈ 1 token."""
total_chars = sum(len(str(m.get("content", ""))) for m in messages)
return total_chars // 4
def add_message(self, role: str, content: str) -> None:
self.messages.append({"role": role, "content": content})
self._trim_if_needed()
def _trim_if_needed(self) -> None:
"""Summarize oldest messages when approaching context limit."""
if self.estimate_tokens(self.messages) < self.max_context_tokens * 0.8:
return
# Keep the most recent 10 messages, summarize the rest
to_summarize = self.messages[:-10]
self.messages = self.messages[-10:]
if not to_summarize:
return
history = "\n".join(f"{m['role']}: {m['content']}" for m in to_summarize)
resp = client.messages.create(
model="claude-haiku-4-5-20251001",
max_tokens=512,
messages=[{
"role": "user",
"content": f"Summarize this conversation, preserving key facts and decisions:\n\n{history}"
}]
)
summary = resp.content[0].text
self.summaries.append(summary)
def get_messages(self) -> list[dict]:
"""Return messages with summary prepended if available."""
if not self.summaries:
return self.messages
summary_msg = {
"role": "user",
"content": f"[Conversation history summary: {' '.join(self.summaries)}]"
}
ack_msg = {"role": "assistant", "content": "I have the context from our previous discussion."}
return [summary_msg, ack_msg] + self.messages
def token_usage(self) -> dict:
tokens = self.estimate_tokens(self.messages)
return {
"current_tokens": tokens,
"max_tokens": self.max_context_tokens,
"utilization": f"{tokens / self.max_context_tokens:.1%}",
"summaries": len(self.summaries),
}
Injecting Retrieved Context Effectively
import anthropic
from typing import Literal
client = anthropic.Anthropic()
def format_retrieved_context(
chunks: list[dict],
strategy: Literal["numbered", "xml", "markdown"] = "xml"
) -> str:
"""Format retrieved chunks for injection into the prompt."""
if strategy == "xml":
# XML tags help the model locate specific sources
parts = ["<retrieved_context>"]
for i, chunk in enumerate(chunks, 1):
parts.append(f"""<source id="{i}" title="{chunk['title']}" relevance="{chunk.get('score', 0):.2f}">
{chunk['content']}
</source>""")
parts.append("</retrieved_context>")
return "\n".join(parts)
elif strategy == "numbered":
parts = []
for i, chunk in enumerate(chunks, 1):
parts.append(f"[{i}] {chunk['title']}\n{chunk['content']}")
return "\n\n".join(parts)
else: # markdown
parts = []
for chunk in chunks:
parts.append(f"### {chunk['title']}\n{chunk['content']}")
return "\n\n".join(parts)
def rag_with_context_engineering(
question: str,
retrieved_chunks: list[dict],
strategy: str = "xml",
) -> str:
context = format_retrieved_context(retrieved_chunks, strategy=strategy)
system = """You are a precise technical assistant.
Rules for using the retrieved context:
1. Answer ONLY from the provided sources
2. Cite the source ID [1], [2], etc. for each claim
3. If sources conflict, note the discrepancy
4. If the answer is not in the sources, say "This information is not in the provided documentation"
5. Never speculate or add information beyond what's provided"""
# Critical ordering: question first, then context (reduces "lost in the middle")
user_message = f"""Question: {question}
{context}
Please answer the question using only the sources above."""
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system=system,
messages=[{"role": "user", "content": user_message}]
)
return response.content[0].text
# Test
chunks = [
{"title": "Installation Guide", "content": "Run pip install clouddb>=4.0. Python 3.10+ required.", "score": 0.92},
{"title": "Configuration", "content": "Set DB_HOST and DB_PORT env vars. Default port is 5432.", "score": 0.87},
{"title": "Performance Tuning", "content": "Enable connection pooling with POOL_SIZE=10 for production.", "score": 0.71},
]
answer = rag_with_context_engineering(
question="How do I install and configure CloudDB for production?",
retrieved_chunks=chunks,
)
print(answer)
Document Chunking Strategies
import re
from typing import Iterator
def chunk_by_token_count(
text: str,
max_tokens: int = 512,
overlap_tokens: int = 64,
) -> list[str]:
"""Split text by approximate token count with overlap."""
words = text.split()
# Approximate: 0.75 words per token
words_per_chunk = int(max_tokens * 0.75)
overlap_words = int(overlap_tokens * 0.75)
chunks = []
start = 0
while start < len(words):
end = min(start + words_per_chunk, len(words))
chunks.append(" ".join(words[start:end]))
start += words_per_chunk - overlap_words
return chunks
def chunk_by_markdown_headers(text: str) -> list[dict]:
"""Split markdown document at header boundaries — preserves section integrity."""
header_pattern = re.compile(r'^(#{1,3})\s+(.+)$', re.MULTILINE)
matches = list(header_pattern.finditer(text))
if not matches:
return [{"title": "Content", "content": text}]
chunks = []
for i, match in enumerate(matches):
title = match.group(2).strip()
start = match.end()
end = matches[i + 1].start() if i + 1 < len(matches) else len(text)
content = text[start:end].strip()
if content:
chunks.append({"title": title, "content": content, "level": len(match.group(1))})
return chunks
def chunk_by_sentences(text: str, max_sentences: int = 5, overlap: int = 1) -> list[str]:
"""Split text by sentences with overlap for dense content."""
sentences = re.split(r'(?<=[.!?])\s+', text)
chunks = []
for i in range(0, len(sentences), max_sentences - overlap):
chunk = " ".join(sentences[i:i + max_sentences])
if chunk:
chunks.append(chunk)
return chunks
# Demonstrate chunking strategies
sample_doc = """# Introduction
CloudDB is a high-performance database system designed for cloud-native applications.
It supports both OLTP and OLAP workloads with automatic scaling.
## Installation
Install using pip: `pip install clouddb`. Requires Python 3.10 or later.
Set the DATABASE_URL environment variable before starting the server.
## Configuration
Connection pooling is enabled by default with a pool size of 5.
For production workloads, increase POOL_SIZE to 20 and enable read replicas.
"""
header_chunks = chunk_by_markdown_headers(sample_doc)
print("Header-based chunks:")
for chunk in header_chunks:
print(f" [{chunk['title']}]: {len(chunk['content'])} chars") Frequently Asked Questions
What is context engineering?
Context engineering is the discipline of deciding what information goes into an LLM's context window, in what order, and how it's formatted. The context is everything the model sees — system prompt, conversation history, retrieved documents, tool results. Engineering it well is often more impactful than changing the model.
What is the 'lost in the middle' problem?
LLMs tend to recall information at the beginning and end of their context better than information in the middle. When injecting long retrieved documents, put the most critical content first or last. This is why RAG results should be reranked — the most relevant chunk should appear first.