Development

A Token Budget That Leaves Room for the Model to Answer

Antonio Evans8 min read

A diagram of a horizontal bar representing the model's context window, split into two labeled segments: a larger blue segment on the left for input tokens and a smaller green segment on the right for output tokens.
Key points

Key points

  1. 1The context window is shared by input and output, so reserving output tokens first is what keeps a prompt from crowding out the answer.
  2. 2A per-task output reservation (small for classification, larger for summarization) plus a safety margin gives you a hard input cap.
  3. 3Count tokens while you assemble the prompt, not after, and stop adding content the moment the cap is reached.
  4. 4Estimate with about four characters per token for English, but verify with the model's own tokenizer before you trust the budget.

The context window is one shared budget

Every API call has a single token ceiling, and it covers both what you send and what the model writes back. The OpenAI documentation states plainly that the context window limits the tokens a model can work with in a request, and that models also have a separate output limit the OpenAI token guide. Practitioners often describe this as input plus output must fit inside the context length, and setting the output cap too high relative to a long input produces an error a Stack Overflow thread on managing token limits.

This matters because teams usually do the arithmetic backwards. They build the prompt to fill the window, then hand whatever is left to the model as output. When the prompt consumes the whole budget, the model has nowhere to put its answer. The fix is to reverse the order: decide how much output you need first, subtract it, and treat what remains as the prompt's spending money.

The OpenAI help page also notes that reasoning models spend internal reasoning tokens that count toward output usage and are billed as output tokens, so a short visible answer can consume more of the window than its text suggests the OpenAI token guide. Your reservation needs headroom for this, which is why we add a margin rather than using the full context length.

The other reason not to max out the window: performance degrades before you hit the hard limit. Model recall and reasoning degrade as the context fills, even well inside the advertised window, a phenomenon often called context rot the foojay analysis of context as a budget. Attention concentrates on the beginning and end of the input, so information in the middle gets less reliable processing the Redis guide to context window overflow. A budget that leaves slack is both correct and kinder to the model.

Reserve output first, then cap the input

The rule is simple to state: input cap equals context length minus output reservation minus safety margin. For each task, you set the output reservation once, based on what a good answer actually needs, and then the input cap falls out of that number.

Here is a worked example with two tasks on a 128,000-token context model. The numbers are illustrative but follow the arithmetic the OpenAI documentation describes for staying within model limits the OpenAI token guide.

TaskContext lengthOutput reservationSafety marginInput capRoom left for retrieved context
Ticket classification128,0005121,488126,000Large; the label plus a one-line reason is tiny
Document summarization128,0001,5002,500124,000Still large, but the summary needs real room
Short-answer QA with citations32,0001,0001,00030,000Moderate
Multi-step agent turn200,0008,00012,000180,000Generous, because tool schemas and history compete

The insight the first search result usually misses is that the output reservation should be set per task, not per model. A classification returns a label and maybe a sentence, so 512 tokens is generous. A summarization returns several paragraphs, so 1,500 is a floor, not a ceiling. Reserving 512 for a summarization does not save you anything on input; it just truncates good summaries. Reserving 8,000 for a classification wastes window that better retrieval could use.

For budgeting, remember that a token is roughly four characters or about three-quarters of a word in English, and that 100 tokens is about 75 words the OpenAI token guide. Use those estimates to plan, but never to enforce the cap in production. The same text can produce different token counts depending on the model, its encoding, and the language, so always count with the real tokenizer the OpenAI token guide.

Count tokens while you assemble the prompt

Context assembly is the step where your app stitches together system instructions, retrieved documents, conversation history, tool schemas and the query into one sequence before the call the Redis guide to context assembly. That is exactly where the cap belongs, because it is the last point where you can decide what goes in.

Two practical rules make this manageable:

  1. Put the fixed, precious content first: system instructions and the user query. They almost never get dropped.
  2. Add retrievable content in relevance order and stop at the cap. If a chunk does not fit whole, stop rather than slicing it mid-sentence.

The reader can verify the general mechanics against the OpenAI guidance on counting a complete request, which notes that message structure, tools, schemas, images and files all affect the full input count the OpenAI token guide. That means a plain-text count of your strings is a lower bound; the real count includes formatting tokens. Budget for that in your margin.

Chunking choices feed directly into this budget. Content-aware chunking significantly improves retrieval over naive fixed-length splitting, and in one large cross-domain evaluation the top strategy (paragraph grouping) reached a mean nDCG@5 of roughly 0.459 while simple fixed-size character chunking fell below 0.244 the chunking study on arXiv. Smaller, coherent chunks that fit your input budget are usually better than a few oversized ones you have to cut. A general survey of chunking strategies makes the same trade-off explicit: recursive or sentence-aware splitting at roughly 400 to 512 tokens with modest overlap is a solid default for prose Firecrawl's chunking guide.

The ordering of your assembled prompt also affects cost and quality. Static content belongs at the top where it can be cached, and dynamic content at the bottom, because a stable prefix is the cacheable one the foojay analysis of context as a budget. This is a nice side effect of building the prompt in a fixed order: the same structure that makes truncation predictable also makes caching work.

A hard cap in Python

The function below does three things: it computes the input cap from the context length, output reservation and margin; it walks through messages in a fixed order and measures the running token total; and it refuses to exceed the cap, preferring to truncate a long message or drop lower-priority context than to send an oversized request.

import tiktoken

# One tokenizer per model family. Swap the encoding name to match your model.
ENC = tiktoken.get_encoding("o200k_base")

def count_tokens(text: str) -> int:
    return len(ENC.encode(text))

# Per-task budget. Set these from measurement, not guesswork.
TASK_BUDGETS = {
    "classify_ticket": {"context": 128_000, "reserve_output": 512,  "margin": 1_488},
    "summarize_doc":   {"context": 128_000, "reserve_output": 1_500, "margin": 2_500},
}

def build_messages(task: str, system: str, query: str, context_chunks: list[str]):
    b = TASK_BUDGETS[task]
    input_cap = b["context"] - b["reserve_output"] - b["margin"]

    messages = [
        {"role": "system", "content": system},
        {"role": "user", "content": query},
    ]
    used = sum(count_tokens(m["content"]) + 4 for m in messages)  # +4 per message, approximate

    kept, dropped = [], 0
    for chunk in context_chunks:  # already sorted most relevant first
        n = count_tokens(chunk) + 4
        if used + n <= input_cap:
            kept.append(chunk)
            used += n
        else:
            dropped += 1

    if kept:
        messages.insert(1, {"role": "system", "content": "\n\n".join(kept)})

    return messages, {
        "input_cap": input_cap,
        "estimated_input_tokens": used,
        "chunks_kept": len(kept),
        "chunks_dropped": dropped,
        "max_output_tokens": b["reserve_output"],
    }, b["reserve_output"]

A few details that matter when you adapt it:

  • The +4 per message is an estimate for role and boundary tokens. The exact count comes from the provider's own counting tool, and the OpenAI documentation points to tiktoken.encoding_for_model for plain text and a dedicated input-token counting API for complete requests the OpenAI token guide.
  • Pass the returned max_output_tokens straight into the request. The OpenAI help page confirms parameter names vary by endpoint, with Chat Completions using max_completion_tokens and Responses using max_output_tokens the OpenAI token guide.
  • If a single chunk is bigger than the whole cap, truncate it to the remaining budget at a sentence boundary rather than sending it whole. The cap is a hard stop, not an aspiration.

For teams running many task types against different providers, keeping the reservation, margin and cap in one config table pays off, because the same arithmetic applies to every model even when the tokenizer differs. Quanta Inference exposes text, image, video, audio and embedding models through one OpenAI-compatible API key priced in US dollars, which means one budget table can cover your whole stack: Quanta Inference.

Choosing the output reservation

The hardest number in the budget is the reservation itself. A method that works: run the task without a cap, log the output token counts, and set the reservation at roughly the 95th percentile rounded up.

Worked example: you run 2,000 summarizations and find output lengths cluster between 700 and 1,300 tokens, with a tail reaching 1,900. Set the reservation at 2,000. That leaves 126,000 tokens for input on a 128,000-token model, and the rare verbose summary still fits. If instead you had guessed 800, the model would be cut off on a meaningful share of real documents, and the user would blame the prompt, not the budget.

For classification, run the same exercise and you will typically see outputs under 100 tokens. A 512 reservation is already generous; the extra is your insurance against a reasoning-heavy model. Do not shrink it to 64 just because typical outputs are short, because reasoning tokens are billed and counted as output even when the visible answer is brief the OpenAI token guide.

The margin deserves similar care. It absorbs tokenizer drift, message-format overhead, tool schemas and any provider-side framing. Roughly 1,500 to 2,500 tokens on top of the reservation is comfortable for chat-style requests without tools. If you attach tool definitions, note that they can dominate the request; five connected servers can easily contribute 5,000 to 10,000 tokens before you have typed a word the foojay analysis of context as a budget. In that case, put the tool schemas inside your margin accounting, and check them against the cap like any other content.

When truncation is not enough

A hard cap does not answer every question. Sometimes the content genuinely needs to be there: a long conversation, a multi-document comparison, or an agent that has been running for twenty turns. Before you simply drop the oldest material, consider the cheaper and more accurate options.

Summarize older turns into a compact state, then keep recent turns verbatim. This is a standard move in context management, where history is trimmed, deleted, or summarized when it outgrows the window the Redis guide to context assembly. Cache the stable prefix (system prompt, schemas, skills) so it is not re-billed at full price on every call, because a cache read costs a fraction of a fresh input token the Firecrawl guide to token optimization. And route easy tasks to smaller models; the gap between top and bottom tiers is enormous, so a classification does not need the same model as a long analysis the Firecrawl guide to token optimization.

If you are building a retrieval-heavy app rather than tuning an existing pipeline, a specialist can do the setup work with you; you describe the site, app, document or plan you need and a specialist picks it up: Quanta.

One more check worth building into your tests: measure retrieval quality separately from generation quality, so a truncation bug does not look like a bad model. Recall and precision at K are the standard tools for this; precision at K measures how many of the top K results are relevant, and recall at K measures what share of relevant items appear in the top K Evidently AI on precision and recall at K. Offline evaluation against a labeled query set is repeatable and cheap, which makes it the right tool for catching a cap that is too tight Unstructured on evaluating search quality.

FAQ

FAQ

What happens if I set the output cap but leave the input unmanaged?

You will still get an overflow. The context window covers input plus output, so a runaway prompt can leave no room for the answer no matter how small the output cap is the OpenAI token guide. Manage both ends of the budget, with the input cap enforced during assembly.

Can I estimate tokens with four characters per token?

For planning, yes; for enforcement, no. The four-characters-per-token rule is a rough estimate for English, and the same text can tokenize differently across models, encodings and languages the OpenAI token guide. Count with the actual tokenizer before you send.

Why not just use the full context window if the model supports it?

Because quality falls before the hard limit. Recall and reasoning degrade as the window fills, and information in the middle of a long input gets less reliable processing the Redis guide to context window overflow. Leaving slack is a quality decision, not only an error-avoidance one.

Should the output reservation be the same for every task?

No. Set it per task from measured output lengths, as in the worked classification and summarization examples above. A reservation that is too small truncates good answers; one that is too large wastes window that retrieval could use.

How does chunking interact with the input cap?

Smaller, coherent chunks that fit the cap are usually retrieved and used better than oversized chunks you have to cut. Content-aware chunking measurably outperforms naive fixed-length splitting on retrieval metrics the chunking study on arXiv, so chunk to your budget rather than to an arbitrary character count.

Sources

Sources

  1. Understanding and counting tokens
  2. Managing Token Limits in GPT-4o for Variable-Length ...
  3. Context Is a Budget, Reducing Token Usage in AI- ...
  4. Context Window Overflow in 2026: Fix LLM Errors Fast
  5. Context Assembly: Building the Prompt the Model Sees
  6. A Systematic Investigation of Document Chunking Strategies and ...
  7. Best Chunking Strategies for RAG (and LLMs) in 2026 - Firecrawl
  8. LLM Token Optimization: 9 Techniques in the Order to ...
  9. Precision and recall at K in ranking and recommendations - Evidently AI
  10. Evaluating Search Quality in Information Retrieval Systems
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles