InterviewPrepKit

Home / Coding / Agent Coding / Memory & Context / Sliding-Window Context Truncation

Sliding-Window Context Truncation

medium 00:00
Solving tips
  • The system message is a fixed cost you pay first, so subtract its tokens from the budget before you start filling the window with recent turns.
  • Walk the non-system messages from newest to oldest and stop the moment the next one would overflow; recency is what you protect, not the oldest history.
  • Keep the returned list in original chronological order even though you decided what to keep by scanning backwards — the model reads top to bottom.

An agent’s context window is finite, but a conversation is not. Every extra turn you carry forward costs tokens, and once the transcript would exceed the model’s budget you have to drop something before the next call. The standard move is a sliding window: pin the system prompt (it holds the instructions the agent must never forget), then keep only the most recent turns that still fit. Old small talk falls off the front; the latest exchange — the part the model actually needs to answer — is protected.

The subtlety is that you decide what to keep by scanning from the newest message backwards, but you must return the survivors in their original order so the model reads the conversation top to bottom.

Task

Complete truncate_context(messages, max_tokens):

  1. If the first message has role == "system", keep it and subtract its token_count from the budget. (If even that one message exceeds max_tokens, keep nothing.)
  2. Walk the remaining non-system messages from newest to oldest. Keep each one whose token_count still fits in the remaining budget, subtracting as you go. Stop as soon as a message would overflow — do not skip it to squeeze in a smaller older one.
  3. Return the kept messages (the system message, if kept, plus the recent ones) in their original chronological order.

Example

messages = [
    {"role": "system",    "token_count": 10, "content": "You are a helpful assistant."},
    {"role": "user",      "token_count": 20, "content": "Hi"},
    {"role": "assistant", "token_count": 30, "content": "Hello!"},
    {"role": "user",      "token_count": 25, "content": "What's 2+2?"},
    {"role": "assistant", "token_count": 15, "content": "4"},
]

kept = truncate_context(messages, max_tokens=60)
# system(10) is pinned -> 50 left.
# newest 15 fits -> 35 left; 25 fits -> 10 left; 30 would overflow, stop.
# kept == [system(10), user(25), assistant(15)]
[m["token_count"] for m in kept]
# [10, 25, 15]

Constraints

  • max_tokens >= 0. The sum of token_count over the returned list must be <= max_tokens.
  • Only the first message can be a system message; treat any later message as ordinary conversation.
  • If there is no system message, spend the whole budget on the most recent non-system messages.
  • Stop at the first message (scanning newest to oldest) that does not fit; do not skip ahead to fit a smaller older message.
  • Every token_count is a non-negative integer. Do not mutate the input list or its dicts; return a new list.

Write your solution, then hit Run tests to check it — or get a mock grade from the AI coach.

The coach remembers this session — revise your code and ask again, and it grades your progress. It gives hints, not the answer.
Report a bug