Summarization Before the Call: Condensing Long Documents for Claude
When a document is too long, too unfocused, or reused across many prompts, the fix isn't to send it whole to your strongest model every time.
It's to condense it once with a cheap model, then send the condensed version to the model doing the real work.
Summary
Pre-call summarization is a two-step pattern: a fast, inexpensive model reads a long document and produces a shorter representation of it.
That shorter representation, not the original document, is what gets sent to the costlier model handling the actual task.
This adds one extra API call, but that call is cheap, so the net cost is lower whenever the document is long or gets reused across multiple prompts.
The technique is most valuable for reference material read many times: a large log file, a long support thread, a lengthy contract, or a big changelog.
This page shows how to build a summarization step with the anthropic Python SDK, when it pays off, and where it can go wrong.
Recipe
Quick-reference recipe card - copy-paste ready.
import anthropic
client = anthropic.Anthropic()
def summarize(document: str, focus: str = "") -> str:
instruction = f"Summarize this document in under 200 words."
if focus:
instruction += f" Focus especially on: {focus}."
response = client.messages.create(
model="claude-haiku-4-5",
max_tokens=300,
messages=[{"role": "user", "content": f"{instruction}\n\n{document}"}],
)
return response.content[0].textWhen to reach for this:
- The source document is long enough that sending it in full to a strong model is expensive on every call.
- The same document will be referenced across multiple prompts, so the summarization cost is paid once.
- You need the gist of a document, not every exact detail (contracts and legal text are an exception, see Gotchas).
- A cheap, fast model is available in your lineup to do the condensing step.
Working Example
import anthropic
client = anthropic.Anthropic()
def summarize(document: str, focus: str = "", max_words: int = 200) -> str:
"""Condense a long document with a cheap model."""
instruction = f"Summarize this document in under {max_words} words."
if focus:
instruction += f" Focus especially on: {focus}."
response = client.messages.create(
model="claude-haiku-4-5",
max_tokens=400,
messages=[{"role": "user", "content": f"{instruction}\n\n{document}"}],
)
return response.content[0].text
def answer_with_summary(summary: str, question: str) -> str:
"""Send the condensed summary, not the original document, to the stronger model."""
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=500,
messages=[{
"role": "user",
"content": f"Based on this summary of a support thread, answer the question.\n\n"
f"Summary:\n{summary}\n\nQuestion: {question}",
}],
)
return response.content[0].text
with open("support_thread.txt") as f:
long_thread = f.read() # 8,000 words of back-and-forth messages
condensed = summarize(long_thread, focus="what the customer's unresolved issue is")
answer = answer_with_summary(condensed, "What's still unresolved for this customer?")
print(answer)What this demonstrates:
summarizeruns on Haiku 4.5, the cheapest tier, since condensing text doesn't require deep reasoning.answer_with_summaryruns on Sonnet 5, the model actually doing the reasoning the user cares about, but it only ever sees the condensed text.- The
focusparameter steers the summary toward what the downstream question needs, instead of producing a generic summary that might drop the relevant detail. - Separating the two functions makes it easy to cache or reuse
condensedacross multiple downstream questions about the same thread.
Deep Dive
How It Works
- The cheap model's job is narrow: compress text while preserving the information a downstream task needs, not to answer the actual question.
- Because summarization is a simpler task than open-ended reasoning, a fast, inexpensive model tier is usually sufficient for it.
- The summary, once produced, can be cached or stored so it's reused across every future question about that document, amortizing the summarization cost further.
- The end-to-end cost is: one cheap summarization call, paid once per document, plus many cheap calls to the strong model using the short summary instead of the long original.
When Summarization Pays Off
| Situation | Pays Off? | Why |
|---|---|---|
| Document used once, in one prompt | Rarely | The summarization call adds cost with no reuse to offset it |
| Document referenced across many prompts | Usually | Summarization cost is paid once; savings compound with each reuse |
| Document is already short (under a few hundred words) | No | The overhead of an extra call isn't worth it |
| Document is long and only the gist matters | Yes | This is the core use case: compress bulk, keep meaning |
Python Notes
# Cache the summary so repeated questions about the same document don't
# re-run the summarization call.
_summary_cache: dict[str, str] = {}
def cached_summarize(doc_id: str, document: str, focus: str = "") -> str:
key = f"{doc_id}:{focus}"
if key not in _summary_cache:
_summary_cache[key] = summarize(document, focus=focus)
return _summary_cache[key]A simple in-memory dict is enough for a single process; a production system would back this with a persistent cache keyed by document hash and focus.
Gotchas
- Summarizing away the detail the downstream task actually needed. A generic summary can drop the one number or clause that mattered. Fix: pass a
focusparameter that tells the summarizer what to preserve, and consider a longer summary length for high-stakes documents. - Summarizing legal, medical, or precise numerical text. Compression is lossy by nature, and exact wording or exact figures can matter in these domains. Fix: for documents where precision is non-negotiable, skip summarization and use minimal-context prompting to extract the exact relevant section instead.
- Re-summarizing the same document on every call. This throws away the entire cost benefit of the technique. Fix: cache the summary by document identity, as shown in the Python Notes example above.
- Using a model too weak to produce a coherent summary. An extremely cheap or small model can produce a summary that's garbled or misses the point entirely. Fix: validate summary quality against a few known documents before relying on a given model tier for this step; move up a tier if quality isn't there.
- Chaining summaries of summaries without checking for drift. Repeatedly summarizing an already-summarized document compounds information loss. Fix: always summarize from the original source, not from a previous summary, when the source is still available.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
| Minimal-context prompting (extract, don't summarize) | You know exactly which section of the document is relevant | The relevant section isn't known ahead of time, or relevance spans the whole document |
| Send the full document every time | The document is short, or used only once | The document is long and reused across many prompts |
| Chunking with retrieval (embeddings) | The document is very large and questions target specific unpredictable sections | A single short summary already captures what most questions need |
| Structured extraction (pull fields into JSON, skip prose) | The document has a predictable structure (invoices, forms) | The document is unstructured prose where a narrative summary is more useful |
FAQs
How is summarization different from just trimming to a relevant snippet?
Trimming selects an existing subset of the text; summarization generates new, shorter text that represents the whole document.
Use trimming when you know which part is relevant, and summarization when the relevant information is spread across the whole document.
Which model should do the summarizing?
The cheapest model in your lineup that produces summaries accurate enough for your downstream task, often Haiku 4.5 in the current Claude lineup.
Validate this choice against a few real documents rather than assuming the cheapest tier is always sufficient.
Does summarization ever cost more than sending the full document?
Yes, if the document is only used once.
- A single-use document pays the summarization cost with no reuse to offset it.
- The technique pays off specifically when a document is referenced across multiple prompts.
Can I summarize a document that's already a summary?
You can, but each summarization pass loses some information, so summarizing a summary compounds that loss.
Prefer summarizing from the original source whenever it's still available.
How do I know if my summary is good enough?
- Test it against a few real documents where you know the "right" answer to common downstream questions.
- Check whether the summary still lets the downstream model answer those questions correctly.
- If it can't, either lengthen the summary, add a
focusinstruction, or move up a model tier for the summarization step.
Should I always pass a `focus` parameter?
It helps whenever you know what the downstream task cares about, since a focused summary is less likely to drop the detail that matters.
For a general-purpose summary that will answer varied future questions, a broader, unfocused summary may be more appropriate.
Is it safe to summarize sensitive or precise documents like contracts?
Be cautious.
- Summarization is lossy, and legal or medical text often depends on exact wording.
- For these document types, prefer extracting the exact relevant clause or section instead of summarizing it away.
How long should the summary be?
Long enough to preserve what downstream questions need, short enough to be meaningfully cheaper than the original.
There's no universal number; a 200-word cap works for many support threads and articles, but a technical document may need more.
Can this be combined with model tiering?
Yes, this technique is itself an application of model tiering: the cheap model handles the simpler task (compression), and the costlier model handles the harder task (reasoning over the result).
What if the document changes after it's been summarized and cached?
A cached summary becomes stale once the source document changes.
Key the cache by a hash or version identifier of the source document, not just its name, so a change invalidates the cached summary automatically.
Does summarization help with context rot, not just cost?
Yes.
A focused summary removes noise the original document may have carried, which can reduce the risk of irrelevant material diluting the model's attention on what matters.
Related
- How Context Engineering Reduces Token Spend - where summarization fits among the other context-reduction techniques.
- Prompt and Context Engineering Basics - hands-on examples of measuring token savings.
- Trimming Context: Dependency Graphs Instead of Full Repos - the extraction-based alternative to summarization for code.
- Model Tiering Checklist - criteria for picking which model handles the summarization step.
- Context Rot: Why More Tokens Doesn't Mean Better Answers - why a focused summary can also improve answer quality.
Stack versions: Written against the Claude model lineup current as of ~June 2026 - Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5 (the default), and Claude Haiku 4.5 - and the official
anthropicPython SDK (latest 0.x release). Model names, pricing, and SDK versions move quickly - verify current specifics at platform.claude.com/docs before relying on them.