Ти вже кілька годин вбиваєш у модель деталі проєкту: ідеї, бачення, як ти хочеш, щоб усе працювало. Файли, залежності, рішення. Вона киває, відповідає по суті.
Потім — БАМ, повідомлення 40, і вона пропонує саме те, що ти відкинув у повідомленні 5.

Ну й око та око за цими LLM-ами, що тут скажеш!

Вітаю — ви вперлися в контекстне вікно.

Це все, що модель «бачить» у процесі розмови: ваші повідомлення, її відповіді, системні інструкції, описи інструментів, вміст прочитаних файлів. Один великий шматок тексту, який вимірюється в токенах.

Але все має межу, і контекстне вікно теж. Деякі моделі зараз підтримують розмір контекстного вікна до ~1M токенів в окремих конфігураціях API. Звучить вражаюче, доки не усвідомлюєш: один файл на 2000 рядків — це вже ~20k токенів. П’ять файлів… і ви вже витратили 100k на контекст.

Також LLM нічого не пам’ятає між викликами. Щоразу, коли ти надсилаєш повідомлення, клієнт (Claude Code, Cursor, ChatGPT) збирає всю історію і надсилає її моделі одним шматком. Модель читає, генерує відповідь і забуває все.
Те, що виглядає як «пам’ять», — це пам’ять клієнта, а не моделі. Він просто пересилає історію.

sequenceDiagram
    participant Client as Client<br/>(Claude Code / Cursor / ChatGPT)
    participant LLM as LLM<br/>(stateless)
    Note over Client: Stores history
    rect rgb(197, 224, 203)
        Note left of Client: Call 1
        Client->>LLM: system prompt + tools + project files + msg1
        LLM-->>Client: resp1
        Note right of LLM: Forgets everything
    end
    Note over Client: History: msg1 + resp1
    rect rgb(197, 224, 203)
        Note left of Client: Call 2
        Client->>LLM: system prompt + tools + project files + msg1 + resp1 + msg2
        LLM-->>Client: resp2
        Note right of LLM: Forgets everything
    end
    Note over Client: History: msg1 + resp1 + msg2 + resp2
    rect rgb(197, 224, 203)
        Note left of Client: Call 3
        Client->>LLM: system prompt + tools + project files + msg1 + resp1 + msg2 + resp2 + msg3
        LLM-->>Client: resp3
        Note right of LLM: Forgets everything
    end
    Note over Client: Stores everything
    Note over LLM: Stores nothing

Окей, історія надсилається повністю. Тоді чому модель усе одно «забуває»?

Причин три:

1. Розмиття уваги.
Модель розподіляє увагу між усіма токенами. При 1000 токенах кожен має свою вагу. При 500 000 — вага розмазується, і якщо все однаково важливе, то нічого не важливе. Ключова інструкція фізично є в контексті, але модель на неї просто не звертає уваги. Приблизно як ти перестаєш помічати деталі у величезному документі.

2. Ефект “lost in the middle”.
Модель найкраще «пам’ятає» початок і кінець контексту. Середина — сліпа зона. Якщо твоє ключове рішення опинилося на токені 200 000 із мільйона… ну що ж, удачі тобі з цим.

3. Накопичення сміття.
Кожна невдала спроба, кожен прочитаний файл, кожен довгий вивід команди залишається в контексті. Після години роботи значна частина вікна, умовні 60%, це мотлох від провалених спроб. Модель бачить усе це разом і не може відрізнити корисне від сміття.

Коли вікно заповнюється повністю, відбувається одне з двох: або найстаріші повідомлення обрізаються, або починається компакція. У Claude Code це компакція: окремий LLM-виклик, який стискає стару історію в коротке резюме.

Але деталі втрачаються назавжди: точні значення, конкретні рядки коду, причини, через які ті чи інші підходи були відкинуті, — усе зникає.

Після компакції модель може впевнено галюцинувати за обривками. І найнеприємніше: вона не знає, чого вона не знає.


Гаразд, тепер зрозуміло, чому контекст розвалюється. Що з цим робити?

У мене є кілька правил:

  1. Додавай файл лише тоді, коли він потрібен для поточного завдання, — не «про всяк випадок». Зайвий контекст не допомагає, він розмиває увагу.
  2. Якщо інструкція має закріпитися — помісти її в головний конфіг-файл клієнта: CLAUDE.md, .cursorrules і подібні.
    Так не доведеться повторювати моделі одне й те саме знову і знову. Можна спокійно перезапускати сесії, оскільки клієнт завантажить ці інструкції заново на початку наступної.
    Ці файли зазвичай опиняються на самому початку контексту. Якщо цей початок не змінюється, сервер може повторно використати вже виконані обчислення (якщо час кешу ще не закінчився). Що економить і час, і токени.
  3. Перемикаєшся на інше завдання? Почни нову сесію. Шум від попереднього завдання просочується в якість відповідей на наступне.
  4. Компакція — це не обов’язково погано. Якщо ти працюєш над тим самим завданням і розмова просто затягнулася — нехай компакція робить свою справу. Суть завдання залишається в резюме. Втрачаються невдалі спроби й конкретні деталі. Але ти ж дотримуєшся правила 2 — тож усе гаразд!
  5. Уся агентна архітектура — субагенти, MCP, ліниве завантаження інструментів, файли пам’яті — це різні способи обійти одну й ту саму проблему: контекст скінченний, і з часом він псується. Детальніше — в mcp і agents.
  6. Бачиш дивну поведінку в довгій сесії? Це симптом зіпсованого контексту. Почисть контекст або почни нову сесію.

Але що щодо кешу?

Тут часто плутаються: клієнт (Claude Code, Cursor і подібні) усе одно щоразу надсилає повний контекст мережею. Кешується не передача даних. Кешуються обчислення на стороні сервера.

Коли модель отримує 100k токенів, вона не читає їх як текст. Вона виконує величезну кількість матричних обчислень. Сервер перевіряє, що вже було пораховано минулого разу, і перераховує лише нове. Під капотом провайдери можуть повторно використовувати вже обчислені частини промпта через механізми prompt caching / KV-cache. Тож та частина контексту, яка не змінилася, може не перераховуватися з нуля щоразу.

flowchart TD

A["User / Client (Claude Code, Cursor)<br/>sends full context, every request over the network"] --> B["Server receives N tokens"]

B --> C{"Is cached prefix<br/>still valid? TTL not expired?"}

C -->|"No — expired or prefix changed"| F["Recompute context<br/>(full matrix pass)"]

C -->|"Yes — same prefix, still within TTL"| D["Reuse cached K/V<br/>for the unchanged prefix"]

D --> G["Compute only new tokens<br/>added after the cached prefix"]

F --> H["Generate response"]

G --> H

classDef client fill:#dee3c6,stroke:#758879,stroke-width:1.5px,color:#2d2d30
classDef server fill:#e3d7c6,stroke:#8b7e7a,stroke-width:1.5px,color:#2d2d30
classDef decision fill:#ddc6e3,stroke:#7e7a8b,stroke-width:1.5px,color:#2d2d30
classDef cached fill:#c5e0cb,stroke:#758879,stroke-width:1.5px,color:#2d2d30
classDef compute fill:#e3c6d2,stroke:#8b7a87,stroke-width:1.5px,color:#2d2d30
classDef response fill:#c5e0cb,stroke:#758879,stroke-width:1.5px,color:#2d2d30

class A client
class B server
class C decision
class D,G cached
class F compute
class H response

Це важливо на практиці: провайдери реалізують кеш по-різному. Варто стежити за тим, як довго кеш зберігається на сервері. Це може змінюватися з часом, але розуміння цих обмежень може зіграти тобі на руку.

Якщо кеш живе годину або п’ять хвилин, можна постаратися не йти на довгу каву прямо посеред сесії, щоб зекономити. Але не жертвуй якістю сесії заради грошей.

Бо планування, читання власних планів і чітке формулювання думок та ідей — значно важливіші, а зрештою можуть бути й дешевшими, ніж пояснювати LLM, що вона робить не те, і намагатися підштовхнути її в правильний бік.

Іноді здається, що продовжувати сесію далі — означає не витрачати зайві токени. Але якщо продовжувати з неправильним або зламаним контекстом, це може обійтися дорожче, ніж зупинитися, оцінити ситуацію і почати заново.

Одна порада щодо цього: збережи плани, вийди із сесії, уважно їх перечитай, сформулюй думки і почни нову сесію з чистого аркуша.

У всього є своя користь і свій компроміс — треба просто знайти правильний.

how-llm-works grounding mcp agents