How to Build an AI Summarizer With Claude
Building an AI summarizer with Claude comes down to three decisions: how you chunk input text, how you structure the prompt, and how you handle output length and streaming. This guide walks through all three with working code, so you end up with a summarizer that handles anything from a short email to a 50-page PDF without falling apart.
The short answer: send your text to Claude with a prompt that specifies summary length, tone, and format, split long documents into chunks and summarize each before doing a final "summary of summaries" pass, and stream the response if you're showing it in a UI. Everything below expands on that.
What you actually need to build
A summarizer isn't just "call the API with a prompt." For anything beyond toy demos you need:
- Text extraction — pulling clean text out of PDFs, HTML, or transcripts before it ever reaches Claude
- Chunking logic — because every model has a context limit, and summarizing one giant blob badly loses nuance anyway
- A consistent prompt template — so output format doesn't drift between requests
- A way to call the model over HTTPS — directly against Anthropic, or through a proxy like SubToAPI if you want API keys, usage tracking and team billing without building that infrastructure yourself
If you're prototyping, you can skip the infrastructure and just get an API key — see /docs/quickstart for a five-minute setup.
Step 1: Design the prompt first
Before writing code, nail the prompt. A vague instruction like "summarize this" produces inconsistent length and tone across requests. Be explicit:
You are a summarization engine. Summarize the following text in 3-5
sentences, written in plain neutral language. Do not add opinions or
information not present in the source. If the text contains no
substantive content, say so.
Text:
"""
{document_text}
"""
Pin down:
- Length (sentences, words, or bullet count — not "briefly")
- Format (prose paragraph, bullet list, or structured JSON)
- Scope (abstractive summary vs. extractive key points)
- Audience (technical reader vs. general reader changes vocabulary choices)
If you need structured output (e.g., {summary, key_points, action_items}), say so explicitly and show an example shape in the prompt — Claude follows a demonstrated schema far more reliably than a loose description.
Step 2: Handle documents longer than one context window
Most real documents — reports, transcripts, support threads — exceed what you want to send in a single request, both for cost and quality reasons. The standard pattern is map-reduce summarization:
- Split the document into chunks (by paragraph or heading, not arbitrary character counts — breaking mid-sentence hurts quality)
- Summarize each chunk independently
- Concatenate the chunk summaries
- Run a final pass that summarizes the summaries into one coherent output
async function summarizeChunk(chunkText) {
const res = await fetch("https://api.subtoapi.app/v1/messages", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "claude-sonnet-4",
max_tokens: 300,
messages: [{
role: "user",
content: `Summarize this excerpt in 2-3 sentences, factual only:\n\n${chunkText}`
}]
})
});
const data = await res.json();
return data.content[0].text;
}
async function summarizeDocument(chunks) {
const partials = await Promise.all(chunks.map(summarizeChunk));
const combined = partials.join("\n\n");
const final = await fetch("https://api.subtoapi.app/v1/messages", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "claude-sonnet-4",
max_tokens: 500,
messages: [{
role: "user",
content: `These are summaries of sequential sections of one document. Merge them into a single coherent summary, removing redundancy:\n\n${combined}`
}]
})
});
const finalData = await final.json();
return finalData.content[0].text;
}
This pattern scales to documents of almost any length because chunk summarization runs in parallel, and only the final merge step is sequential. Full request and response fields are documented at /docs/messages.
Step 3: Stream output for long or interactive use cases
If users are watching the summary generate in real time — a browser extension, a dashboard widget — stream the response instead of waiting for the full completion:
curl -N https://api.subtoapi.app/v1/messages \
-H "Authorization: Bearer $SUBTOAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4",
"max_tokens": 400,
"stream": true,
"messages": [{"role": "user", "content": "Summarize this article in bullet points: ..."}]
}'
Streaming matters most for the final merge step, where output can run a few hundred tokens — users perceive it as faster even though total latency is similar. Details on event formats are in /docs/streaming.
Step 4: Add structure when summaries feed other systems
If the summary output is consumed by another program rather than a human — e.g., stored in a database or passed to a downstream workflow — ask Claude to return JSON directly and parse it, rather than regex-scraping free text. Keep the schema small: summary, key_points as an array, and optionally sentiment or category fields. For summarizers that also need to extract specific fields (dates, names, action items) alongside the narrative summary, tool use can enforce a strict schema — see /docs/tools if your pipeline needs that level of reliability.
Choosing a model and managing cost
Longer or more nuanced documents benefit from larger models; short transcripts and emails summarize well with smaller, cheaper ones. A practical rule: use a faster model for the per-chunk pass (volume is high, each summary is short) and a stronger model for the final merge (one call, needs coherence). This cuts cost significantly on long documents without hurting final quality, since the last pass is doing the real synthesis work.
Getting this running quickly
If you already have Claude access through a Pro or Team plan and want to expose it as a proper HTTPS API — with application keys, request logging, and usage metadata per key — SubToAPI turns that access into an API you can call from the code above without managing separate billing. Plans start at Solo for solo projects, Team for shared seats, and Scale for higher-volume usage; see /pricing for the breakdown, or start with a free trial at /signup.
Questions
Does Claude have a built-in summarization mode? No. There's no dedicated "summarize" endpoint — you get summarization behavior by prompting a general chat/completion model with clear length, format, and scope instructions, as shown above.
How do I summarize a document longer than Claude's context window? Use map-reduce: split the document into chunks, summarize each chunk independently, then run one more pass that merges the chunk summaries into a single final summary.
Should I stream the summarizer's output? Stream it if a human is watching the result appear live (UI widgets, chat-style tools). For batch jobs or pipelines where the summary is stored or passed to another system, a single non-streamed response is simpler to parse.