← Blog

Building a Summarization Tool with Claude

2026-10-12 · 5 min read · SubToAPI Team

Building a summarization tool with Claude means designing a prompt that produces consistent, length-controlled summaries, handling documents that exceed context limits, and exposing the result through an API your app can call reliably. This article walks through each piece: prompt structure, chunking strategy for long inputs, streaming vs. non-streaming output, and how to wire it all up with an HTTPS API.

The core workflow is simple: send text (or a document) to Claude with instructions on summary length, format, and tone, then return structured output your frontend or pipeline can use. The hard parts are consistency across requests, handling inputs longer than the model's context window, and making the tool fast enough for interactive use cases like dashboards or Slack bots.

Designing the Summarization Prompt

A good summarization prompt specifies three things explicitly: length, format, and focus. Vague prompts like "summarize this" produce inconsistent results — sometimes three sentences, sometimes three paragraphs.

A reliable template:

Summarize the following text in exactly 3-5 sentences.
Focus on: key decisions, numbers, and action items.
Do not include opinions or background that isn't in the source.

Text:
{{document}}

For structured output (useful if you're feeding the summary into another system), ask for JSON:

Summarize the text below and return ONLY valid JSON in this shape:
{"summary": string, "key_points": string[], "word_count": number}

Text:
{{document}}

Claude is reliable at following this format when the instruction is explicit and placed before the content, not buried after it. If you need guaranteed structure for downstream parsing, consider using tool calls instead of parsing free-text JSON — see /docs/tools for how tool-based extraction works through SubToAPI.

Handling Long Documents

Most real-world summarization tools hit the context window problem quickly: PDFs, transcripts, and support tickets often exceed what fits in a single request comfortably, even with large context models. Two common strategies:

1. Map-reduce summarization. Split the document into chunks (by paragraph, page, or token count), summarize each chunk independently, then summarize the summaries into a final output.

async function summarizeChunk(text) {
  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-5",
      max_tokens: 300,
      messages: [{
        role: "user",
        content: `Summarize in 2-3 sentences:\n\n${text}`
      }]
    })
  });
  const data = await res.json();
  return data.content[0].text;
}

async function summarizeLongDocument(chunks) {
  const partials = await Promise.all(chunks.map(summarizeChunk));
  return summarizeChunk(partials.join("\n\n"));
}

This works well for transcripts and reports but can lose cross-chunk context — a decision made in chunk 1 and reversed in chunk 5 may not surface correctly in the final summary.

2. Sliding context with running summary. Instead of summarizing chunks independently, carry forward a running summary and ask Claude to update it with each new chunk:

Here is the current summary so far:
{{running_summary}}

Here is the next section of the document:
{{chunk}}

Update the summary to incorporate this new section. Keep it under 150 words.

This preserves narrative continuity better but is sequential, so it's slower for very long documents. Pick map-reduce for independent sections (e.g., multiple support tickets) and running summary for sequential narrative content (e.g., meeting transcripts, long-form articles).

Streaming for Interactive Use Cases

If your summarization tool is user-facing — a browser extension, a dashboard widget — streaming the response feels faster even when total latency is similar. Full details are in /docs/streaming, but the basic pattern with SubToAPI looks like:

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-5",
    max_tokens: 500,
    stream: true,
    messages: [{ role: "user", content: `Summarize:\n\n${documentText}` }]
  })
});

const reader = res.body.getReader();
const decoder = new TextDecoder();
let output = "";

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  output += decoder.decode(value);
  renderPartialSummary(output);
}

For batch jobs — nightly summarization of support tickets, email digests — skip streaming and just call the endpoint synchronously since nobody is watching the output appear in real time.

Controlling Cost and Consistency at Scale

Once the tool is working for one document, the next problem is running it across hundreds or thousands of documents a day. A few practical tactics:

Getting an API Key

Any summarization tool built on Claude needs an HTTPS endpoint with a key, usage tracking, and ideally team-level visibility if more than one person is building against it. SubToAPI turns your existing Claude access into that endpoint in a few minutes — see /docs/quickstart for setup, and /docs/messages for the full request/response reference. Plans start at €9/month for solo use, with team seats at €19 and scale pricing at €49 (/pricing). You can try it with a free trial via /signup.

questions

Can Claude summarize an entire book in one request? No — even with large context windows, very long books exceed practical limits once you add instructions and formatting. Use a map-reduce or running-summary approach to chunk the text and combine partial summaries.

How do I keep summary length consistent across requests? Specify length explicitly in sentences or word count rather than relative terms like "brief" or "short," and keep max_tokens close to that target so the model isn't tempted to expand.

Should I use streaming for a batch summarization job? No — streaming helps perceived speed for interactive UIs but adds no benefit for background jobs. Use standard synchronous requests and process results as they complete.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →