
Context engineering a gyakorlatban: agentek, amik pont eleget emlékeznek
Közzétéve: 2025. december 3.
A legtöbb agent, ami elbukik, nem azért bukik el, mert a modell gyenge. Inkább azért buknak el, mert aki megépítette őket, azt feltételezte, hogy egy összezavarodott agent megoldása egy még nagyobb context window lesz - csak etesd meg vele az egész kontextust, és mindig tudni fogja, mire van szüksége. Ez a feltételezés majdnem minden valódi workflow-nál fordítva igaz, és érdemes végigmenni azon is, hogy miért - egy konkrét eseten keresztül: egy writing agenten, ami blogposztokat ír, szerkeszt és ütemez több turn-ön keresztül.
A naiv verzió gyorsan összeomlik
Egy ilyen agent első verziója szinte mindig egy egyszerű, állapot nélküli hívás: fogd a felhasználó üzenetét, küldd el a modellnek, add vissza a választ. Ez addig működik, amíg a felhasználó azt nem mondja, hogy „bővítsd ki a második szekciót" - a modellnek most tudnia kéne, mi az a „draft", de semmilyen emlékezete nincs semmiről.
Ilyenkor a kézenfekvő javítás, hogy a teljes beszélgetés-előzményt beleteszed minden promptba. Ez egy darabig működik. Aztán a felhasználó elkezd valódi tartalmat írni - ötszáz szavas draftokat, több kör revíziót, hosszú feedback szálakat -, és a kontextus felfúvódik, a költségek emelkednek, a latency megugrik, és a modell egyre kevésbé kiszámíthatóan viselkedik, minél tovább tart egy beszélgetés.
A tool-ok megoldják a memória-problémát, és csinálnak egy újat
A tool-ok hozzáadása - create_post, get_post, update_post, list_posts - megoldja az állapot-problémát. Az agent most már tud valódi tárolt adatot manipulálni, ahelyett hogy azt hallucinálná, mi van a „draftban".
Csakhogy a tool eredmények közvetlenül bekerülnek a modell következő promptjába, és ezt könnyű alábecsülni. Ha az agent meghívja a get_post-ot egy 2500 szavas drafton, hogy szerkessze, az egész draft - cím, body, minden - a modell következő inputjának része lesz. Ez nem bug; a modell nem tud olyan szöveget szerkeszteni, amit nem lát. De azt jelenti, hogy minden lekérdezés visszateszi a teljes dokumentumot a kontextusba, még egy olyan kis kérésre is, mint „változtasd meg a bevezető hangvételét". Kérj három kicsi szerkesztést egymás után, és háromszor tetted vissza ugyanazt a 2500 szót.
A beszélgetés-előzmény vágása egy kicsit segít, de nem érinti ezt a problémát, mert ami igazán felfújja a promptot, azok nem a régi üzenetek - hanem az aktuális tool eredmény, és a modellnek tényleg látnia kell a tartalmat, amit szerkeszt.
Csak azt add a modellnek, amire szüksége van, csak akkor, amikor szüksége van rá
A tényleges megoldás strukturális lesz: a modellnek pontosan azt kéne látnia, ami az aktuális lépéshez releváns, nem a beszélgetés teljes felhalmozott állapotát. A gyakorlatban ez azt jelenti, hogy a promptot rétegekre bontod egyetlen növekvő blob helyett - egy rövid, gördülő összefoglaló arról, mi történt eddig, egy kis strukturált state objektum, mint {"current_draft": "9e3d", "mode": "editing"}, a felhasználó aktuális kérése, és csak azután, ha tényleg szükséges, egy tool eredmény, ami a releváns részre van szűkítve.
Ha a felhasználó a második szekciót szerkeszti, a tool-nak a második szekciót kéne visszaadnia - nem a teljes dokumentumot. Ez az egyetlen változtatás az, ami megakadályozza, hogy egy több-turn-ös szerkesztési session az ötödik váltásra 40 000 tokenes prompttá fúvódjon, nem pedig a history-vágás.
A tool-válaszok tömörítése a valódi kulcs
Mivel a tool eredmények egyenesen a kontextusba kerülnek, az, hogy egy tool mekkora eredményt ad vissza, ugyanannyira számít, mint bármi más a prompt templateben. Néhány minta végzi a munka nagy részét: adj vissza metaadatot teljes tartalom helyett bármi lista-szerű dologra, adj vissza egy szeletet a teljes dokumentum helyett, ha a felhasználó csak egy részét érinti, adj vissza egy diffet a teljes új verzió helyett egy verziózott dokumentumnál, engedd meg a modellnek, hogy egy follow-up hívással kérje a többit, ahelyett hogy előre betöltenél mindent, amire esetleg szüksége lehet, és adj vissza egy cache-elt összefoglalót nyers szöveg újraszerializálása helyett, ahol egy összefoglaló is elég jó.
A mentális modell, ami itt tényleg segít: kezeld az LLM-et úgy, mint egy senior editort, és csak a releváns oldalt tedd az asztalára, ne az egész mappát.
A hozadék, és ami nélküle történik
Ha jól csinálod, ez alacsonyabb token-használatban, alacsonyabb latency-ben mutatkozik meg. Olyan agentekben, amik nem felejtik el csendben, mit csináltak a task közepén, és - ami nem elhanyagolható - egy olyan rendszerben, ami tényleg debug-olható, mert pontosan meg tudod nézni, mit látott a modell az egyes lépéseknél, ahelyett hogy egy 30 000 tokenes transcriptből próbálnál találgatni.
Ha rosszul csinálod, szerencsére a hibák specifikusak és felismerhetők: az agent rossz szekciót szerkeszt, elveszti a fonalat, mit csinált néhány turnnel korábban, olyan lépéseket hallucinál, amik meg sem történtek, vagy beragad egy tool-hívás loopba. Ezek szinte mind modellhibának tűnnek. A legtöbbjük valójában egy kontextushiba, ami modellhibának álcázza magát.
Az ösztön, hogy „több memóriát" adj egy agentnek, érthető, de sosem a memória volt a szűk keresztmetszet. Amire egy több-turn-ös agentnek tényleg szüksége van, az a fókusz - az a minimális információ, ami szükséges ahhoz, hogy a megfelelő állapotot a megfelelő pillanatban rekonstruálja, tudatosan összeválogatva, nem pedig felhalmozva.
