Research · Build it

The optimal summary interval for NPC conversations

Resending the whole conversation every turn makes NPC cost grow with the square of conversation length. Summarising every k exchanges makes it linear, and the best k turns out to be independent of conversation length: about 3.6 here, or ~11 with a warm prompt cache.

Ammighty ResearchPublished 22 September 20266 min read

The quadratic you didn't budget for#

The simplest way to give an NPC memory of a conversation is to resend the whole conversation every turn. It works, it's what most prototypes do, and it makes cost grow with the square of conversation length. A character who gets twice as chatty costs four times as much. This post derives the cost of full history, the cost of a common alternative (summarise the last exchanges, then drop them), and the interval that minimises spend. Then it checks the formula against an exact turn-by-turn count.

Code: research/context_budget.py. Prices are illustrative (, per million tokens). Only their ratio affects the optimum.

Cost of full history#

Each turn sends a static prompt of tokens (character sheet, rules, world state) plus every previous exchange of tokens, and gets tokens back. Turn carries previous exchanges, so over turns:

At 60 turns that's 391,200 input tokens, 72% of them repeated history. The static prompt is a rounding error by the end of a long conversation.

Summarise-and-flush, and its optimum#

Instead, keep at most raw exchanges. When the buffer fills, a summarisation call compresses the old summary plus those exchanges into a new summary of tokens (with tokens of instructions), and the buffer empties. The raw history in context then cycles from 0 to exchanges, on average. Approximating for :

The middle term grows with (more raw history per turn); the last shrinks with (fewer summarisation calls). Setting :

Note what's missing: and . The optimal interval doesn't depend on how long the conversation runs or how big the character sheet is. It's a ratio of what a summary costs to what a raw exchange costs to carry. With our numbers, .

Checking it against an exact count#

Session cost vs summary intervalSession cost vs summary interval$0.40$0.60$0.80$1.00$1.2010203040Full history: $1.25k* ≈ 3.57 (formula)Exact cost, 60-turn sessionSummarise every k exchanges$ per session

Exact per-session cost at 60 turns for k = 1…40, counting every token turn by turn, including the cold start before the first summary exists.

The exact discrete optimum is , next to the continuous , and the curve is flat near the bottom: anything from 3 to 5 is within 1% of optimal, and 6 is within about 2%. That flatness is useful in practice. You can choose for narrative reasons (summarise at scene boundaries) without paying much.

Quadratic vs linear: cost per conversationQuadratic vs linear: cost per conversation$0$2.5$5$7.5$1050100150200Full historySummarise-and-flush at best kTurns in the conversation$ per conversation

Cost per conversation as length grows. Summarisation wins from about 10 turns.

TurnsFull-history input tokensFull history $Best kSummarise $Saving
1025,200$0.0885$0.0835%
2066,400$0.2234$0.17322%
40196,800$0.6384$0.35345%
60391,200$1.2464$0.53457%
100972,000$3.0364$0.89471%
2003,544,000$10.8724$1.79683%

Summarisation starts paying off at around 10 turns and saves 57% at 60. For the long companion-style conversations where players talk for hundreds of turns, it's the difference between a viable game and one that can't be priced.

How prompt caching changes the answer#

The analysis above assumes every input token costs . With prompt caching, history that was already sent last turn can be read from cache at roughly a tenth of the price. That makes carrying raw history ~10× cheaper, so the denominator shrinks by ~10 and

With a warm cache you should summarise far less often, roughly every 11 exchanges instead of every 4. This is a first-order estimate: it treats every carried token as a cache hit, which only holds if players reply within the cache TTL. Our caching post measures how often that's true.

What the model doesn't price: memory quality#

Every summary loses detail, and a character who forgets the name of your dog is a worse character. Two practical points from shipped titles:

  • Summaries should be structured, not prose. A summary that records facts as key–value pairs ("player_promised: return lantern by day 9") survives repeated re-summarisation far better than a paragraph, which drifts a little each time.
  • Pair summaries with retrieval. Store the raw exchanges outside the prompt and retrieve the few that matter. Summaries carry the gist; retrieval brings back exact quotes when the player asks "what did I say?". See NPC memory architecture.

Measure the trade-off directly. Run your eval suite at and at , and if quality scores don't move, take the cheaper one.

Reproduce it#

The full script is research/context_budget.py (Python 3.10+, numpy, scipy; fixed seeds, so you'll get the same numbers). This is the core of it:

def summarize_flush(n, k):
    tin = tout = hist = 0; has_summary = False
    for t in range(1, n + 1):
        tin += S + (s if has_summary else 0) + m * hist   # prompt for this turn
        tout += o
        hist += 1
        if hist == k and t < n:                            # compress and flush
            tin += (s if has_summary else 0) + k * m + 120
            tout += s
            hist, has_summary = 0, True
    return tin, tout

Run it with python3 research/context_budget.py; results land in research/out/, and the site's tables and charts are rendered from that JSON at build time. Set S, m and s from your own logs. Average them over a real playtest rather than guessing, because m varies a lot between chatty and terse players.

Frequently asked questions#

Why does LLM conversation cost grow quadratically?

If each turn resends all previous turns, turn t carries t−1 exchanges, so total input tokens over n turns grow with n(n−1)/2.

How often should an NPC summarise its conversation?

The cost-optimal interval is k* = √(2(s+q+ρs)/m), where s is summary size, q summariser instructions, m tokens per exchange and ρ the output/input price ratio. Typical values give 3–5 without caching and 10+ with prompt caching.

Does summarisation hurt NPC quality?

It can. Use structured, fact-based summaries plus retrieval of raw exchanges, and test quality scores at different intervals before choosing.

Got a game that talks back?

Send a build, a deck or two minutes of raw footage. A producer plays every pitch and answers within 10 business days.