← Vytvářejte agenty na Cloudflare / agents / concepts
Stav konverzace a paměť
Aby byli Agents užiteční dlouhodobě, potřebují paměť. Bez ní každá konverzace začíná od nuly. Agent zapomene, kdo je uživatel, co se naučil a co dělal. Právě paměť mění bezstavové volání LLM v trvalého agenta, který si je vědom kontextu.
Session API poskytuje vrstvu paměti pro agenty postavené na Cloudflare Agents SDK. Spravuje dva druhy paměti: historie konverzace (zprávy a volání nástrojů, které tvoří relaci) a kontextová paměť (trvalé bloky vložené do systémového promptu, které agent může číst, zapisovat, prohledávat a načítat).
Použijte tuto stránku, pokud potřebujete více než jednoduchý synchronizovaný stav nebo plochou historii chatu. Pro malý stav UI použijte Ukládání a synchronizace stavu. Pro základní perzistenci chatu AIChatAgent za vás uchovává zprávy. Pro účelově navrženou dlouhodobou paměť Think staví na Session a kontextových blocích.
Historie konverzace
Nejzákladnějším typem paměti je samotná konverzace: zprávy mezi uživatelem a agentem, volání nástrojů, která agent provedl, a výsledky, které obdržel. Session ukládá to všechno do stromové historie zpráv, kterou zajišťuje Session Provider s výchozím nastavením na SQLite.
import { Session } from "agents/experimental/memory/session";
// Append messages as the conversation progresses
await session.appendMessage({
id: `user-${crypto.randomUUID()}`,
role: "user",
parts: [{ type: "text", text: "What's the status of the deployment?" }],
});
// Read the full conversation history
const history = await session.getHistory();import { Session } from "agents/experimental/memory/session";
// Append messages as the conversation progresses
await session.appendMessage({
id: `user-${crypto.randomUUID()}`,
role: "user",
parts: [{ type: "text", text: "What's the status of the deployment?" }],
});
// Read the full conversation history
const history = await session.getHistory();Historie konverzace přetrvává i přes hibernaci a vyřazení Durable Object z paměti. Když se agent probudí, je celá historie k dispozici v SQLite. Není potřeba ji přehrávat ani rekonstruovat.
Zprávy jsou uloženy ve stromové struktuře prostřednictvím parent_id, který umožňuje větvení konverzací. Když appendMessage s parentId která už má potomky, vytvoříte větev, což se hodí u funkcí jako regenerace odpovědi. getHistory(leafId) prochází libovolnou zvolenou cestu stromem.
Session navíc poskytuje fulltextové vyhledávání v historii konverzace:
const results = await session.search("deployment Friday", { limit: 10 });const results = await session.search("deployment Friday", { limit: 10 });Jak se konverzace prodlužují, komprimace sumarizuje starší zprávy, aby kontextové okno zůstalo zvládnutelné, aniž by se ztratila podkladová data.
Kontextová paměť
Kontextová paměť představuje trvalé informace vkládané do systémového promptu, oddělené od historie konverzace. Agentovi dává v každém kole přístup k identitě, instrukcím, naučeným faktům, znalostním bázím a referenčním materiálům.
Session API podporuje čtyři typy kontextové paměti, z nichž každý se hodí pro jiný druh informací. Typ je určen poskytovatel která stojí za kontextovým blokem. Session automaticky rozpozná možnosti poskytovatele.
Kontext pouze pro čtení
Toto je váš tradiční systémový prompt: identita agenta, jeho osobnost a instrukce. Můžete ho napsat přímo do kódu, nebo ho načíst z SOUL.md soubor v R2, nebo jej načtěte z API. Obsah se vloží do systémového promptu a agent jej nemůže upravovat.
Kódovací asistent může mít duši, která definuje jeho osobnost a omezení:
import { Session } from "agents/experimental/memory/session";
const session = Session.create(this).withContext("soul", {
provider: {
get: async () =>
"You are a senior TypeScript engineer. You write concise, " +
"well-tested code. You prefer composition over inheritance. " +
"When you are unsure, you say so rather than guessing.",
},
});import { Session } from "agents/experimental/memory/session";
const session = Session.create(this).withContext("soul", {
provider: {
get: async () =>
"You are a senior TypeScript engineer. You write concise, " +
"well-tested code. You prefer composition over inheritance. " +
"When you are unsure, you say so rather than guessing.",
},
});Nebo jej načtěte z R2, abyste mohli aktualizovat osobnost agenta bez nového nasazení:
const session = Session.create(this).withContext("soul", {
provider: {
get: async () => {
const obj = await env.CONFIG_BUCKET.get("soul.md");
return obj ? obj.text() : "You are a helpful assistant.";
},
},
});const session = Session.create(this).withContext("soul", {
provider: {
get: async () => {
const obj = await env.CONFIG_BUCKET.get("soul.md");
return obj ? obj.text() : "You are a helpful assistant.";
},
},
});Bloky pouze pro čtení definujete poskytnutím objektu, který obsahuje pouze get() metodu. Nevygenerují se žádné nástroje. Obsah se zobrazí v systémovém promptu a agent jej nemá jak změnit.
Zapisovatelný kontext v krátké podobě
Představte si to jako poznámkový blok, který si agent vede sám pro sebe, místo, kam si zapisuje věci, které si potřebuje zapamatovat. Podobně jako si Claude Code vede seznam úkolů k vyřešení, nebo jako si agent zákaznické podpory může poznamenávat, co se během konverzace o uživateli dozvěděl.
const session = Session.create(this)
.withContext("memory", {
description: "Important facts learned during conversation",
maxTokens: 1100,
})
.withContext("todos", {
description: "Task list, track what needs to be done and what is complete",
maxTokens: 2000,
});const session = Session.create(this)
.withContext("memory", {
description: "Important facts learned during conversation",
maxTokens: 1100,
})
.withContext("todos", {
description: "Task list, track what needs to be done and what is complete",
maxTokens: 2000,
});Když vynecháte provider možnost v builderu, Session se automaticky propojí se zapisovatelným poskytovatelem s podporou SQLite. Agent získá set_context nástroj, který mu umožňuje nahrazovat obsah těchto bloků nebo do nich přidávat obsah. Vynucují se limity tokenů, takže agent nemůže zapsat víc než maxTokens rozpočet dovoluje.
Systémový prompt vykresluje zapisovatelné bloky s ukazatelem využití tokenů, aby agent věděl, kolik místa mu ještě zbývá:
══════════════════════════════════════════════
MEMORY (Important facts learned during conversation) [45% — 495/1100 tokens] [writable]
══════════════════════════════════════════════
User prefers dark mode.
User's project uses React and TypeScript.
Deployment target is Cloudflare Workers.
══════════════════════════════════════════════
TODOS (Task list) [12% — 240/2000 tokens] [writable]
══════════════════════════════════════════════
- [x] Set up project scaffolding
- [ ] Add authentication middleware
- [ ] Write integration testsObsah přetrvává napříč zprávami a přežije i hibernaci. Je vždy vidět v systémovém promptu, takže ho agent vidí v každém kole, aniž by cokoli musel načítat.
Prohledávatelný kontext
Máte-li k dispozici velké množství informací (znalostní bázi, dokumentaci, logy, nashromážděné poznámky), nechcete je všechny natlačit do systémového promptu. Prohledávatelný kontext udržuje v systémovém promptu jen souhrn (například „indexováno 42 položek“) a agentovi umožňuje konkrétní položky načíst, až je bude potřebovat.
Provideru předáte search() metodu. Způsob, jakým vyhledávání funguje, je zcela na vás: fulltextové vyhledávání, vektorové vyhledávání přes Vectorize, volání externího API nebo cokoli jiného. Relaci nezajímá implementace, jen to, že poskytovatel má search() metoda.
Vestavěný AgentSearchProvider jako výchozí používá Durable Object SQLite s FTS5:
import { AgentSearchProvider } from "agents/experimental/memory/session";
const session = Session.create(this).withContext("knowledge", {
description:
"Searchable knowledge base, search for relevant information before answering",
provider: new AgentSearchProvider(this),
});import { AgentSearchProvider } from "agents/experimental/memory/session";
const session = Session.create(this).withContext("knowledge", {
description:
"Searchable knowledge base, search for relevant information before answering",
provider: new AgentSearchProvider(this),
});Můžete si ale implementovat vlastního poskytovatele podporovaného libovolným vyhledávacím mechanismem:
const session = Session.create(this).withContext("knowledge", {
description: "Searchable knowledge base",
provider: {
get: async () => "Product documentation and FAQs",
search: async (query) => {
// Use Vectorize, an external API, whatever you need
const results = await env.VECTORIZE_INDEX.query(
await generateEmbedding(query),
{ topK: 5 },
);
return results.matches.map((m) => m.metadata.text).join("\n\n");
},
set: async (key, content) => {
// Index new content
},
},
});const session = Session.create(this).withContext("knowledge", {
description: "Searchable knowledge base",
provider: {
get: async () => "Product documentation and FAQs",
search: async (query) => {
// Use Vectorize, an external API, whatever you need
const results = await env.VECTORIZE_INDEX.query(
await generateEmbedding(query),
{ topK: 5 },
);
return results.matches.map((m) => m.metadata.text).join("\n\n");
},
set: async (key, content) => {
// Index new content
},
},
});Agent získá search_context nástroj pro dotazování a set_context nástroj pro indexování nových záznamů. Ten rozhoduje, co se má hledat, a vy rozhodujete, jak vyhledávání funguje.
Je to správná volba ve chvíli, kdy agent potřebuje najít konkrétní útržky informací z velké kolekce, místo aby načítal celé dokumenty.
Načitatelný kontext (Skills)
Skills jsou rozsáhlé bloky kontextu (kompletní dokumenty, referenční příručky, provozní postupy, šablony), které agent může na vyžádání objevit a načíst. Představte si je jako referenční materiály na poličce: agent uvidí seznam názvů a popisů, vybere, co je relevantní pro aktuální úkol, načte to, použije to a po dokončení odstraní.
Na rozdíl od prohledávatelného kontextu, kde agent načítá malé úryvky z většího souboru dat, jsou dovednosti navržené tak, aby se načítaly vcelku. Když agent načte dovednost, získá do svého kontextového okna celý dokument.
Skills jsou podporovány prostřednictvím SkillProvider rozhraní. Poskytovatel dovedností má tři metody:
get()vrátí výpis metadat (názvy a popisy), který se objeví v systémovém promptuload(key)načte celý obsah konkrétní dovednostiset(key, content, description?)zapisuje nebo aktualizuje záznam skill (volitelné)
Systémový prompt zobrazuje dostupné dovednosti jako výpis. [loadable] značka říká LLM, že tyto položky nejsou vložené přímo v textu. Model musí pro přístup k celému obsahu použít nástroj:
══════════════════════════════════════════════
SKILLS [loadable]
══════════════════════════════════════════════
- api-ref: API Reference documentation
- style-guide: Company style guide
- deploy-checklist: Production deployment checklistAgent vidí názvy, rozhodne, který skill je pro aktuální úkol relevantní, a použije load_context ke stažení celého obsahu do svého pracovního kontextu. Jakmile je hotovo, použije unload_context k uvolnění místa. Když poskytovatel dovedností implementuje set(), agent může také zapisovat zpět, aktualizovat existující dovednosti nebo vytvářet nové.
Agent sees: "- deploy-checklist: Production deployment checklist"
User asks: "Walk me through a production deployment"
Agent calls: load_context({ block: "skills", key: "deploy-checklist" })
→ Full checklist content is loaded into the agent's working contextSkills uložené v R2
Vestavěný R2SkillProvider uchovává skills v bucketu Cloudflare R2. Každý skill je objekt R2 s volitelnými vlastními metadaty pro popisy.
import { Session, R2SkillProvider } from "agents/experimental/memory/session";
const session = Session.create(this)
.withContext("soul", {
provider: {
get: async () =>
[
"You are a helpful assistant with access to skills.",
"When a user asks you to do something, check the SKILLS section",
"for a relevant skill and use load_context to load it.",
].join("\n"),
},
})
.withContext("memory", {
description: "Learned facts",
maxTokens: 1100,
})
.withContext("skills", {
provider: new R2SkillProvider(env.SKILLS_BUCKET, { prefix: "skills/" }),
})
.withCachedPrompt();import { Session, R2SkillProvider } from "agents/experimental/memory/session";
const session = Session.create(this)
.withContext("soul", {
provider: {
get: async () =>
[
"You are a helpful assistant with access to skills.",
"When a user asks you to do something, check the SKILLS section",
"for a relevant skill and use load_context to load it.",
].join("\n"),
},
})
.withContext("memory", {
description: "Learned facts",
maxTokens: 1100,
})
.withContext("skills", {
provider: new R2SkillProvider(env.SKILLS_BUCKET, { prefix: "skills/" }),
})
.withCachedPrompt(); prefix možnost omezuje poskytovatele na podadresář v bucketu. Klíče dovedností ve výpisu metadat se zobrazují bez prefixu, takže skills/api-ref se změní na api-ref v systémovém promptu.
Použijte keys pro povolení konkrétních skills vázaných na prefix pro get() a load():
new R2SkillProvider(env.SKILLS_BUCKET, {
prefix: "skills/",
keys: ["deploy-checklist", "api-ref"],
});new R2SkillProvider(env.SKILLS_BUCKET, {
prefix: "skills/",
keys: ["deploy-checklist", "api-ref"],
});Přidejte vazbu na bucket R2 do vaší konfigurace Wrangler:
{
"r2_buckets": [
{
"binding": "SKILLS_BUCKET",
"bucket_name": "my-agent-skills"
}
]
}[[r2_buckets]]
binding = "SKILLS_BUCKET"
bucket_name = "my-agent-skills"Skills jsou běžné objekty R2. Nahrajte je přes libovolné rozhraní R2 (přes Wrangler CLI, dashboard nebo Workers API):
# Upload a skill from a file
wrangler r2 object put my-agent-skills/skills/style-guide --file ./docs/style-guide.md --content-type text/markdownChcete-li přidat popisy (zobrazují se ve výpisu metadat), nastavte u objektu R2 vlastní metadata:
await env.SKILLS_BUCKET.put("skills/api-ref", content, {
customMetadata: { description: "API Reference documentation" },
});await env.SKILLS_BUCKET.put("skills/api-ref", content, {
customMetadata: { description: "API Reference documentation" },
});Vlastní poskytovatelé dovedností
Skills můžete podepřít libovolným úložištěm implementací SkillProvider rozhraní:
class DatabaseSkillProvider {
db;
constructor(db) {
this.db = db;
}
async get() {
const rows = await this.db
.prepare("SELECT key, description FROM skills ORDER BY key")
.all();
if (rows.results.length === 0) return null;
return rows.results
.map((r) => `- ${r.key}${r.description ? `: ${r.description}` : ""}`)
.join("\n");
}
async load(key) {
const row = await this.db
.prepare("SELECT content FROM skills WHERE key = ?")
.bind(key)
.first();
return row ? row.content : null;
}
async set(key, content, description) {
await this.db
.prepare(
"INSERT INTO skills (key, content, description) VALUES (?, ?, ?) " +
"ON CONFLICT(key) DO UPDATE SET content = ?, description = ?",
)
.bind(key, content, description ?? null, content, description ?? null)
.run();
}
}import type { SkillProvider } from "agents/experimental/memory/session";
class DatabaseSkillProvider implements SkillProvider {
private db: D1Database;
constructor(db: D1Database) {
this.db = db;
}
async get(): Promise<string | null> {
const rows = await this.db
.prepare("SELECT key, description FROM skills ORDER BY key")
.all();
if (rows.results.length === 0) return null;
return rows.results
.map((r) => `- ${r.key}${r.description ? `: ${r.description}` : ""}`)
.join("\n");
}
async load(key: string): Promise<string | null> {
const row = await this.db
.prepare("SELECT content FROM skills WHERE key = ?")
.bind(key)
.first();
return row ? (row.content as string) : null;
}
async set(key: string, content: string, description?: string): Promise<void> {
await this.db
.prepare(
"INSERT INTO skills (key, content, description) VALUES (?, ?, ?) " +
"ON CONFLICT(key) DO UPDATE SET content = ?, description = ?",
)
.bind(key, content, description ?? null, content, description ?? null)
.run();
}
}Session rozpozná load() metodu pomocí duck-typing a automaticky vygeneruje odpovídající nástroje.
Skills oproti jiným typům paměti
| Aspekt | Skills | Zapisovatelný kontext | Prohledávatelný kontext |
|---|---|---|---|
| V systémovém promptu | Pouze výpis metadat | Úplný obsah | Počet souhrnů |
| Vzor přístupu | Načíst celý dokument podle klíče | Vždy viditelné | Vyhledávání podle dotazu |
| Vhodné pro | Rozsáhlé dokumenty, referenční materiály | Krátké poznámky, preference | Velké kolekce malých položek |
| Náklady na kontext | Nízká (dokud není načteno) | Úměrné obsahu | Nízká (dokud není vyhledáno) |
| Zapisuje Agent? | Volitelné (pokud set implementováno) |
Ano (přes set_context) |
Ano (přes set_context) |
Klíčový rozdíl: dovednosti jsou líné. V systémovém promptu prakticky nic nestojí, dokud se agent nerozhodne, že některý z nich potřebuje. Díky tomu se skvěle hodí pro rozsáhlé referenční materiály, z nichž je pro danou konverzaci relevantní jen část.
Jak agenti pracují s pamětí
Session automaticky generuje nástroje na základě typů poskytovatelů vašich kontextových bloků. Tyto nástroje pak předáte svému LLM spolu s vlastními nástroji specifickými pro danou aplikaci:
const sessionTools = await session.tools();
const allTools = { ...sessionTools, ...myApplicationTools };
const result = streamText({
model: myModel,
system: await session.freezeSystemPrompt(),
messages: await convertToModelMessages(await session.getHistory()),
tools: allTools,
});const sessionTools = await session.tools();
const allTools = { ...sessionTools, ...myApplicationTools };
const result = streamText({
model: myModel,
system: await session.freezeSystemPrompt(),
messages: await convertToModelMessages(await session.getHistory()),
tools: allTools,
});Generované nástroje
Session generuje nástroje dynamicky podle toho, jaké typy poskytovatelů jsou přítomné:
| Nástroj | Generováno, když | Co dělá |
|---|---|---|
set_context |
Existuje zapisovatelný blok, blok typu skill nebo blok typu search | Zapíše obsah do pojmenovaného bloku. U zapisovatelných bloků obsah nahradí nebo připojí. U bloků typu skill/search zapíše položku podle klíče. |
load_context |
Existuje blok typu skill | Načte úplný obsah dokumentu podle klíče do kontextu agenta. |
unload_context |
Existuje blok typu skill | Uvolní prostor v kontextu odstraněním dříve načteného dokumentu. Dokument zůstává k dispozici pro opětovné načtení. |
search_context |
Existuje blok typu search | Fulltextové vyhledávání v prohledávatelném bloku. Vrací nejlepší výsledky seřazené podle relevance. |
session_search |
Použití SessionManager |
Vyhledává napříč všemi relacemi (vyhledávání mezi konverzacemi). |
Nástroje obsahují popisy a schémata parametrů, které LLM sdělují, které bloky jsou k dispozici a k čemu slouží. Agent na základě konverzace rozhoduje, kdy a jak je použít.
Úplné signatury nástrojů a všechny metody Session najdete v Referenční dokumentace Session API.
Systémový prompt
Kontextové bloky se skládají do strukturovaného systémového promptu s jasnými hlavičkami a metadaty. Každý blok dostane označenou sekci se štítky, které udávají jeho typ a kapacitu:
══════════════════════════════════════════════
SOUL (Identity) [readonly]
══════════════════════════════════════════════
You are a helpful coding assistant who speaks concisely.
══════════════════════════════════════════════
MEMORY (Important facts) [45% — 495/1100 tokens] [writable]
══════════════════════════════════════════════
User prefers dark mode.
User's project uses React and TypeScript.
══════════════════════════════════════════════
KNOWLEDGE (Searchable knowledge base) [searchable]
══════════════════════════════════════════════
12 entries indexed.
══════════════════════════════════════════════
SKILLS [loadable]
══════════════════════════════════════════════
- api-ref: API Reference documentation
- style-guide: Company style guideTagy ([readonly], [writable], [searchable], [loadable]) sdělují LLM, jaký typ interakce je s každým blokem možný. Rozpočty tokenů ukazují agentovi, kolik místa zbývá v zapisovatelných blocích, což mu pomáhá spravovat vlastní paměť.
Úskalí
Cachování promptů
Poskytovatelé LLM (Anthropic, OpenAI a další) ukládají prefix systémového promptu do cache. Pokud po sobě jdoucí požadavky sdílejí stejný systémový prompt, poskytovatel může zpracování tohoto prefixu přeskočit, což snižuje latenci i náklady. Změna systémového promptu cache naruší a tuto výhodu tak zmaří.
Session API je navrženo pro práci s ukládáním promptů do mezipaměti:
freezeSystemPrompt()vykreslí systémový prompt ze všech kontextových bloků při prvním volání a při dalších voláních pak vrací hodnotu z mezipaměti. Prompt se mezi koly nemění, ani když agent zapisuje do paměti přesset_context.withCachedPrompt()uloží zmrazený prompt do úložiště, takže přežije hibernaci i vyřazení Durable Object z paměti. Když se agent probudí, načte stejný prompt, aniž by ho musel znovu načítat od všech poskytovatelů.
Když agent použije set_context k aktualizaci zapisovatelného bloku, podkladový poskytovatel se aktualizuje okamžitě (data se uloží), ale zamrzlý systémový prompt zůstává ne znovu vykreslen. LLM uvidí aktualizaci až při dalším kole, pouze pokud explicitně zavoláte refreshSystemPrompt(), což obvykle děláte mezi jednotlivými koly konverzace, nikoli uprostřed kola.
To znamená, že systémový prompt zůstává po celé vícekrokové kolo s voláním nástrojů stabilní, takže se u poskytovatele zachovává prefixová cache napříč všemi kroky.
const session = Session.create(this)
.withContext("soul", {
provider: { get: async () => "You are a helpful assistant." },
})
.withContext("memory", { description: "Learned facts", maxTokens: 1100 })
.withCachedPrompt(); // Persist the frozen prompt across hibernation
// During a conversation turn:
const system = await session.freezeSystemPrompt(); // Same value every call
const tools = await session.tools();
// ... agent calls set_context to update memory ...
// The frozen prompt is NOT changed, prefix cache stays warm
// Between turns (optional, if you want the agent to see its own updates):
await session.refreshSystemPrompt();const session = Session.create(this)
.withContext("soul", {
provider: { get: async () => "You are a helpful assistant." },
})
.withContext("memory", { description: "Learned facts", maxTokens: 1100 })
.withCachedPrompt(); // Persist the frozen prompt across hibernation
// During a conversation turn:
const system = await session.freezeSystemPrompt(); // Same value every call
const tools = await session.tools();
// ... agent calls set_context to update memory ...
// The frozen prompt is NOT changed, prefix cache stays warm
// Between turns (optional, if you want the agent to see its own updates):
await session.refreshSystemPrompt();Komprimace
Dlouhé konverzace nakonec překročí kontextové okno LLM. Komprimace to řeší na dvou úrovních: makrokomprimace sumarizuje rozsahy starších zpráv a mikrokomprimace zkracuje jednotlivé zprávy, které jsou příliš velké.
Makrokomprimace
Makrokomprimace shrnuje starší zprávy, originály ale nikdy nemaže.
Používá překryvy: souhrn se uloží do samostatné tabulky, klíčovaný podle rozsahu zpráv, který pokrývá. Když getHistory() se volá, překryvy se transparentně použijí při čtení. Komprimovaný rozsah se nahradí syntetickou souhrnnou zprávou. Původní zprávy zůstávají v SQLite, takže je zachována celá konverzace pro účely auditu, vyhledávání a větvení.
Messages: [1] [2] [3] [4] [5] [6] [7] [8] [9] [10]
↓ compaction ↓
Overlay: [1] [2] [SUMMARY of 3-7] [8] [9] [10]
↑ tail protectedKlíčové body:
- Nedestruktivní, původní zprávy se nikdy nemažou. Celá konverzace je vždy dostupná v databázi.
- Iterativní, když konverzace znovu naroste a vyvolá další kompaktaci, stávající souhrn se předá LLM k aktualizaci, nikoli se nahradí od nuly.
- Respektuje hranice, hranice komprimace se posouvají tak, aby nedošlo k rozdělení dvojic volání nástroje a výsledku nástroje.
- Konfigurovatelné,
protectHeadzachová prvních N zpráv (obvykle systémový kontext) atailTokenBudgetponechává nejnovější zprávy beze změny.
import { createCompactFunction } from "agents/experimental/memory/utils/compaction-helpers";
const session = Session.create(this)
.withContext("memory", { maxTokens: 1100 })
.onCompaction(
createCompactFunction({
summarize: (prompt) =>
generateText({ model: myModel, prompt }).then((r) => r.text),
protectHead: 3,
tailTokenBudget: 20000,
minTailMessages: 2,
}),
)
.compactAfter(100_000); // Auto-compact when token estimate exceeds thresholdimport { createCompactFunction } from "agents/experimental/memory/utils/compaction-helpers";
const session = Session.create(this)
.withContext("memory", { maxTokens: 1100 })
.onCompaction(
createCompactFunction({
summarize: (prompt) =>
generateText({ model: myModel, prompt }).then((r) => r.text),
protectHead: 3,
tailTokenBudget: 20000,
minTailMessages: 2,
}),
)
.compactAfter(100_000); // Auto-compact when token estimate exceeds thresholdAutomatická komprimace se spustí po appendMessage() když odhadovaný počet tokenů překročí prahovou hodnotu. Selhání komprimace není kritické, zpráva je už uložena.
Mikrokomprimace
Mikrokomprimace pracuje na úrovni jednotlivých zpráv, nikoli napříč rozsahy. Řeší dva problémy:
Oříznutí v době čtení: truncateOlderMessages() zkracuje výstupy nástrojů a dlouhý text ve starších zprávách před jejich odesláním do LLM. Nedávné zprávy (výchozí je posledních 4) zůstávají nezměněné. Pracuje na kopii, uložené zprávy se tak nemění.
import { truncateOlderMessages } from "agents/experimental/memory/utils";
const history = await session.getHistory();
const truncated = truncateOlderMessages(history);
// Pass truncated history to the LLMimport { truncateOlderMessages } from "agents/experimental/memory/utils";
const history = await session.getHistory();
const truncated = truncateOlderMessages(history);
// Pass truncated history to the LLMVynucení velikosti řádku: když se zpráva ukládá (obvykle zpráva asistenta s rozsáhlými výstupy nástrojů), zkontroluje se proti limitu velikosti řádku SQLite. Nadměrně velké výstupy nástrojů se nahradí náhledem a poznámkou doporučující nástroj spustit znovu. Díky tomu jednotlivé zprávy nepřekročí limity úložiště a zachová se plynulost konverzace.