Context Window Management in Agentic Systems

Building autonomous AI agents (“agentic systems”) involves coordinating large language models (LLMs) with tools, code execution, and memory. A key challenge in these systems is context window management – deciding what information to include in the LLM’s prompt (context) at each step. LLMs have a fixed context window (token limit) that constrains how much conversation history, retrieved knowledge, and instructions can be given at once[1]. Poor context management can lead to inefficiencies, hallucinations, and cost bloat[2]. As agents tackle complex multi-step tasks (coding, data analysis, etc.), effective strategies are needed to keep the prompts relevant, concise, and within token limits. This whitepaper analyzes the challenges of context window management in agentic systems and surveys current best practices to address them, with a focus on cloud-based agents (while noting local deployment considerations). We also discuss how these technical strategies influence product design for AI-powered applications.

Challenges with Long Contexts in Autonomous Agents

Agentic systems often operate in extended conversations or iterative tool-using loops. Without careful control, the prompt can grow until it hits the maximum context size, degrading performance and reliability. Key issues include:

  • Context Overload and Irrelevant Information: Agents may fetch large documents, code libraries, or logs as context. Often only a small portion is relevant, yet the entire content stays in the prompt unless managed. Inserting entire session transcripts or documents into the prompt is “expensive and computationally inefficient”, leading to higher inference costs and slower responses[3]. Irrelevant or stale details in the prompt can confuse the model(a phenomenon dubbed “context rot”), causing output quality to decline[4]. Long chat histories can likewise pollute the prompt – Moveworks notes that when conversation history grows too long, it “can confuse the LLM, leading to less accurate, less relevant, or slower responses.”Their system mitigates this by automatically clearing context older than 24 hours[5].
  • Latency and Cost of Large Prompts: Prompt processing time increases with length. Especially in local deployments or on edge devices, encoding a long prompt can dominate total runtime (previous research showed that "on a mobile CPU [prompt processing] might be >90% of the total runtime for a long prompt, and even on a mobile-class GPU it can be ~50–90% of the latency"). Even on cloud infrastructure, more tokens mean higher API costs and slower responses. In summary, the more context we stuff into each LLM call, the more it taxes performance and budget[3]. This creates pressure to keep prompts lean.
  • Token Limit Constraints: If the agent exceeds the model’s token limit, developers must drop or truncate some content. Naïve strategies like truncating the middle of the prompt (as some UIs allow) risk discarding important information arbitrarily, which can lead to incoherent behavior. The research paper “Lost in the Middle” (Liu et al. 2023) showed that models struggle to use information buried in the middle of a long context – they have a bias to prioritize the beginning (primacy) and end (recency) of the prompt[6][7]. Thus, blindly removing “middle” context can be catastrophic if that middle contained critical task state. Agents might forget prior steps or requirements, causing them to repeat actions or get stuck in loops.Indeed, insufficient context or improper truncation can cause an agent to repeatedly invoke the same tool or logic (a known AutoGPT limitation) because it “forgets” that it already accomplished a sub-task[8]. Maintaining continuity of important state is essential to avoid such failure modes.
  • Context Drift and Garbage Accumulation:As an agent conversation progresses, some earlier details become irrelevant (“garbage”) and can be dropped, but others remain important. If irrelevant context isn’t pruned, it can distract the LLM or consume tokens needlessly. If relevant context is mistakenly dropped, the model may fill the gaps with hallucinations or incorrect assumptions. Balancing what to keep vs. discard is non-trivial. For example, compressing the prompt too aggressively can cause the model to lose track of the task,leading to a form of model collapse where it either loops or regresses to generic responses.

In summary, without proper management, an agent’s context window can easily overflow, slowing the system and causing confusion. The good news is that a variety of strategies have emerged to tackle these challenges, ranging from prompt compression techniques to architectural changes in how the agent plans and remembers information.

Best Practices for Context Window Management

To build robust and efficient agentic systems, developers should adopt a multifaceted approach to context management. The goal is to give the LLM just the information it needs, just in time, and no more. Below we outline the best practices, including prompt summarization, retrieval of relevant snippets, controlled tool outputs, external memory, and hierarchical planning. These techniques often work in combination.

Summarization and Prompt Compression

One fundamental technique is summarizing or compressing context so that the gist of earlier content is preserved in fewer tokens. As the conversation or task progresses, the agent (or a separate compression module) can generate an abstractive summary of older dialogue turns, decisions, or observations. This summary replaces the raw transcript of those interactions in the prompt. By doing this iteratively, the system retains important context while freeing up space[9].

How to apply summarization: Many agent frameworks implement this as a “rolling summary” memory. For example, LangChain provides a ConversationSummaryMemory that automatically summarizes the conversation history beyond the most recent turns[10]. After each agent-user exchange, the new messages are distilled into a running summary, which is then prepended in the next prompt while older verbatim messages are dropped. This keeps the prompt length roughly constant. OpenAI’s function-calling agent patterns also encourage summarizing state – the developer can store a concise state of the world (e.g. what subgoals are completed) and include that in the system message of subsequent calls, instead of the full history.

When summarizing, it’s important to preserve critical details. A good summary captures key facts, user intents, and any decisions made by the agent[11][12]. Trivial chit-chat or low-priority details should be omitted or compressed aggressively[13]. Effective summarization may involve combining techniques: abstractive summary for general context, plus extracting key-value facts or entities to a structured memory. For example, an agent might record “User’s name is Alice; user is allergic to shellfish” as facts in memory, while summarizing the rest of the conversation narrative. This ensures that specific crucial data isn’t lost in a vague summary.

One must also consider quality trade-offs. Summarization is lossy by nature – if done poorly, it might omit a nuance that later becomes important. This can degrade answer quality or cause the agent to ask the user to repeat information. To mitigate this, design the summarization prompt to explicitly include anything that might be relevant later (names, numbers, objectives, constraints, decisions, etc.). Some systems use two-tier summaries: a brief summary for the prompt and a more detailed log stored externally in case deeper recall is needed.

Despite these caveats, summarization is a powerful tool to “reduce context to concise and complete” form[14][15]. OpenAI’s guidance suggests that if you have lengthy supporting text, it can be summarized or excerpted rather than included in full. In practice, a combination of summarization and truncation yields the best results: keep the latest dialogue turns verbatim (for recency and clarity of immediate question), include a summary of older turns for continuity, and drop truly irrelevant content. Many conversational agents today follow this pattern to fit months-long chat sessions into a fixed window.

Retrieval of Relevant Information (Selective Context Injection)

Instead of pre-loading all possibly relevant data into the prompt, a better practice is retrieval-on-demand. In this paradigm, the agent uses tools or embeddings to fetch only the most relevant snippets of information from a larger corpus, and injects those into context when needed. This is commonly referred to as Retrieval-Augmented Generation (RAG)[16].

How it works: The system maintains an external knowledge base or vector database (for documents, code, prior conversations, etc.). When the agent faces a query or subtask that might require external knowledge, it formulates a search query (this can be a vector similarity search or traditional keyword search) to find the top-K relevant pieces. Those snippets (and only those) are then added to the LLM prompt as contextual data. Crucially, the agent doesn’t see the entire library or document at once – just the parts deemed relevant by the retrieval step[17][18]. This drastically reduces prompt size while ensuring the model gets needed information.

For example, rather than inserting a whole 50-page API document into the prompt of a coding agent, the system can index the API docs in an embedding store. When the agent needs to use a specific function, it queries the store for that function name or related description. The resulting few paragraphs are provided to the LLM. This approach was one of the earliest solutions to LLM context limits and remains a best practice for any kind of knowledge-intensive agent.

Integration with agent frameworks: Modern agent frameworks offer retrieval tools out-of-the-box. OpenAI’s Agents SDK allows defining tools that perform searches or database lookups, which the model can call when it determines more context is required[17]. Google’s ADK goes a step further with a Memory Search API – agents can call search_memory(query) to query a configured memory service[19][20]. The retrieved results are then returned via the tool interface for the LLM to incorporate in its reasoning. This design keeps the context window usage minimal until extra knowledge is truly needed, implementing “on-demand context”[17].

By using tools or sub-agents for retrieval, we effectively “hide the full details behind tool calls”. The main agent doesn’t carry all reference material in its prompt; it can always ask a retrieval tool for specifics. This aligns with the principle of context adaptability – dynamically bringing in information based on the task at hand[21][22].

Selective Context Injection also means prioritizing what enters the prompt. Relevant chunks come in, and anything not immediately relevant stays out (or remains only in long-term storage). As one guide puts it, “prioritize information critical to the task”[23] and “prune irrelevant exchanges” from the working context[24]. Agents can maintain a sliding window of recent interactions plus any newly retrieved facts for the current query. Irrelevant or completed-topic content can be archived to memory (and perhaps summarized) but not included going forward unless context shifts back to it.

This strategy directly addresses the earlier point about large fetched content – rather than dumping an entire library or database, the agent fetches small, relevant chunks. Not only does this fit the context window, it improves accuracy (since the model focuses on pertinent info). It also mitigates the “lost in the middle” effect: if only a few focused snippets are given, they are less likely to be lost among thousands of tokens of fluff. Empirically, systems built on RAG have shown strong results in maintaining factual accuracy over long sessions[25].

Managing Tool Output and Noisy Logs

Agentic systems often execute external tools (e.g. a compiler, a database query, web search) and feed the results back into the prompt for the LLM to observe. These tool outputs can be extremely verbose. For instance, running a build command in a coding agent might produce pages of compiler warnings and logs, most of which are not relevant to the task except the final error message. If we naively include the entire tool output in the prompt, we quickly clog the context window with noise. A best practice is to capture and inject only the salient output from tools.

There are a few ways to achieve this:

  • Tool Design for Quiet Mode: Design the tools or their wrappers to run in a “silent” or summarized mode. Many CLI tools have flags for minimal output. For example, running tests with a --quiet flag or redirecting debug logs to a file can ensure that the agent only sees the final result (e.g., “All tests passed” or the summary of failures). In a build tool, one might capture just the error count and first N error messages instead of thousands of lines. By having the agent prefer such quiet execution modes, the prompt remains tidy. This approach was noted as significantly reducing prompt length in practice – showing only a summary and error messages instead of every intermediate log.
  • Post-Processing Outputs: If a tool doesn’t have a quiet mode, the agent’s runtime can post-process the output before putting it into the prompt. For instance, after a shell command, programmatically filter the output for lines that match certain patterns (like “ERROR:” or important keywords). Or apply a truncation: if the output is over X lines, take the last 50 lines which often contain the summary or the error traceback. The assumption is that early parts of a long output are setup noise and only the end is relevant (which often holds for logs). Some systems even apply an LLM-based summarizer on tool output – e.g., use a smaller local LLM to summarize a log file into a paragraph, then feed that paragraph to the main agent.
  • Pagination or Scoping: Another approach is to treat reading large output as its own task. Instead of blindly dumping a 20KB text file output to the LLM, the agent can be instructed to read it in chunks with human-like strategy: e.g., “The log is very long. Skimming for the word‘ERROR’ ... found something relevant in section 4.” In effect, the agent could call a specialized tool to search within the output for relevant info. This is a more advanced pattern and not common in simple agents, but it underlines the idea that the agent doesn’t always need verbatim outputs.

By managing tool outputs this way, we prevent context window pollution by irrelevant data. The LLM is less likely to get distracted or hit token limits because of some lengthy printout. It also accelerates processing – fewer tokens for the model to read, and less cognitive load for it to parse. In product terms, this yields a cleaner user experience: the user sees concise results rather than overwhelming raw dumps. Many agent implementations in enterprise settings filter out or summarize tool outputs for exactly this reason (imagine a user watching an agent that shows 1000 lines of npm log versus one that says “✅ Build succeeded without errors” – the latter is clearly preferable).

Short-Term vs Long-Term Memory Separation

Human-like AI agents benefit from having both a working memory for recent context and a long-term memory for facts and preferences that persist across sessions. Externalizing long-term memory is emerging as a best practice to handle context beyond the immediate window. Instead of relying on the LLM to carry all historical information in each prompt, the agent stores important knowledge in a memory store (which could be a database, vector store, or a managed service). This is then accessed when relevant, rather than kept continuously in the prompt.

Cloud providers have begun offering such memory frameworks. For example, AWS’s AgentCore Memory and Google’s Vertex AI Memory Bank provide managed solutions to store and retrieve agent memory. These systems automatically handle things like conversation history storage, semantic embedding of facts, and summarization in the background[26][27]. A key insight from Google: “directly inserting entire session dialogues into an LLM’s context window is… inefficient” and doesn’t scale[3]. Instead, Google’s Memory Bank extracts key facts and summaries asynchronously (using an LLM like Gemini behind the scenes) and stores them indexed by topics or user ID[28][29]. When a new session or query begins, the agent can retrieve the relevant pieces from this memory (for example, via a similarity search for related topics)[30][31]. This approach “provides scalable, long-term agent memory that is more efficient than repeatedly populating a large context window.”[32] In other words, the agent doesn’t have to see the entire history every time – it asks the Memory Bank for what’s relevant now.

Figure 1: Example of an external memory architecture (Google’s Vertex AI Memory Bank). The agent’s conversation events are stored in a Session log. A background process generates structured long-term memories (facts, preferences, summaries) which are stored in the Memory Bank. When needed, the agent retrieves relevant memories (using a memory search tool) and incorporates them into the prompt instead of relying on the full raw history.[3][28]

OpenAI’s Agent SDK similarly encourages separating local state from prompt. It provides a context object (for developer use) that is “not sent to the LLM… purely local”[33], which can hold arbitrary state, including past interaction info or user metadata. If the agent needs that data, the developer can choose to inject it via the system prompt or expose it through a function call[34]. This design mirrors the short-term vs long-term memory split: keep long-term or less frequently needed data out of the prompt by default, but have it accessible when required.

In practice, implementing this might involve a few components: - A short-term memory buffer (limited number of recent turns or the current task context) that is always in the prompt to maintain coherence in the immediate exchange. - A long-term memory store (database or files) that accumulates important information from past interactions, possibly processed into embeddings or summaries. - A Memory retrieval function in the agent’s toolset that queries the long-term store (by user ID, conversation topic, or semantic similarity) to bring back relevant memories when the current query seems to need them. For example, if the user says “Can you remember what I told you about my server setup last week?”, the agent would do a memory search for “server setup” under that user’s memory and include the result in the answer.

An important aspect is designing what to extract into long-term memory. AWS’s AgentCore Memory defines multiple memory strategies for extraction[35][11]: e.g., “Summary Strategy” for a running conversation summary, “Semantic Facts Strategy” for factual assertions to remember, “User Preferences Strategy” for capturing user-specific settings[11]. These correspond to different namespaces in the memory store (like a section for summaries vs preferences)[36]. Developers can customize these or add their own. The general guidance is to extract information that will likely be useful in the future, in a form that’s easy to retrieve. Preferences and key facts are classic examples – they should persist and be readily accessible next time that user interacts with the agent, without relying on an old conversation staying in prompt.

By offloading long-term knowledge to an external memory, we avoid carrying “conversation baggage” in every prompt. This not only saves context space and cost, it also improves privacy (since you’re not repeatedly sending potentially sensitive history to the LLM API; the history lives in a secure database and only pertinent facts are pulled when needed). It also makes it feasible for agents to maintain continuity over indefinite time periods (weeks, months) – far beyond the fixed context length of any single model. From a system architecture perspective, you end up with a memory layer that can be scaled and managed (e.g., you can expire or archive old events, compress older memories, etc., independent of the LLM calls).

One must ensure that memory retrieval is done smartly: retrieving too much (or irrelevant memories) can reintroduce the original problem of an overloaded prompt. The current best practice is to retrieve only a handful of items (e.g., top 3-5 relevant memory records) and perhaps even summarize those if they are long. The agent might preface to the user, “Here’s what I know from our past sessions:” and then integrate that into solving the current query. Also, memory should be kept up-to-date – as new interactions happen, update the stored facts (e.g., if the user’s preference changed, the old memory should be superseded). Google’s Memory Bank mentions using the LLM to consolidate new information with existing memory, resolving contradictions and updating the stored record[37].

In summary, persistent memory for agentic systems provides continuity without context window overflow. It’s an essential technique for cloud-based agents that serve returning users and need personalization[38]. Product-wise, this enables features like the agent “remembering” user preferences across chats, which greatly improves user experience (no one likes repeating themselves). At the same time, it demands careful handling of privacy (ensure stored data is encrypted and access-controlled[39][40]) and data quality (avoid memory becoming a grab-bag of outdated or incorrect info).

Hierarchical Planning and Execution (Divide and Conquer)

Another significant strategy to manage context (and complexity) is to structure the agent’s reasoning process into planning and execution phases, possibly with multiple specialized sub-agents. Instead of one monolithic prompt where the agent tries to plan and execute in a single context thread, the system can force a separation: first get the model to produce a plan, then have it (or other models) execute each step of that plan in isolation or with minimal context. This limits the amount of information the model needs to hold at any one time and can prevent the prompt from ballooning with the entire chain of reasoning.

Plan-and-Execute Pattern: This approach has been advocated in recent agent research and implementations[41][42]. For example, LangChain’s “Plan-and-Execute” agents use one LLM call to generate a high-level multi-step plan given the user’s goal[43]. The plan is essentially a structured list of steps (possibly with tool calls or subgoals). Then, for each step, a separate executor (which could be a smaller model or a different prompt) handles the step and produces an outcome. The system then may call the planner again to re-evaluate or refine the plan based on results. Crucially, each execution step only sees the context relevant to that step: typically the step instruction and the necessary inputs, not the entire conversation or entire chain of thought.

This yields multiple benefits: - The context for each sub-task is kept minimal. If step 3 involves calling an API, the prompt for step 3’s LLM (if any) doesn’t need to include steps 1 and 2’s full details, just the information needed (perhaps references to outputs of E1 and E2 as variables)[44][45]. The plan itself acts as a kind of succinct context for the overall task, preventing the need to repeatedly enumerate what has been done. - By not having the “larger agent” think through every intermediate action in one go, we reduce the number of times the full context (user request + all prior actions) must be processed by the model. This can make the system faster and more token-efficient[46]. The LangChain team notes that plan/execution agents can be “faster and cheaper… the larger model is only called for planning steps, while smaller models (or no model at all) handle execution”[47][48]. This is a direct way to cut down prompt size and frequency. - It can improve success rates on complex tasks by ensuring the model thinks through the whole problem at a high level (in the plan) before acting[49]. This explicit reasoning often yields a better organized solution, and since the plan is externalized, the system can verify or adjust it (even involve a human or a “judge” model to approve the plan if needed) before wasting tokens on incorrect actions.

From a context management viewpoint, hierarchical agents limit context by scope. The planner deals with high-level context (maybe just the user’s goal and constraints). The executors deal with narrow context (the specific sub-problem, plus perhaps the relevant result from a previous step). This is essentially “divide and conquer” for the prompt. Each piece of the problem is solved with a focused prompt, rather than one mega-prompt that tries to solve everything.

A concrete example: Suppose the user asks an agent to “Analyze my sales data and draft an email with key insights.” A monolithic agent might load the entire sales dataset (huge) into context, analyze it, then compose an email – likely impossible due to token limits. A plan-and-execute agent, however, will plan steps: 1) summarize sales data (tool: run a data analysis script), 2) identify key insights from summary, 3) draft email with those insights. Each step is manageable in context: Step 1 might involve a tool outside the LLM (no prompt needed beyond telling the tool to run). Step 2 might involve an LLM reading only the summary (which is short) and outputting bullet points. Step 3 LLM sees just the bullet points and maybe a template, and produces an email. At no point did we put the raw full sales data into an LLM context, only the derived summary – solving the context limit issue by design.

State Management: When using this pattern, the system (the orchestration code) takes on the responsibility of tracking state between steps, rather than relying on the LLM’s hidden state or long prompt memory. The agent’s state (plan, intermediate results) can be stored in variables or a blackboard that the code manages. This means that if the conversation or task continues, the orchestrator can inject just the necessary state into future prompts. For instance, if the user asks a follow-up based on that email, the system knows the plan and outcomes and can feed the relevant pieces to the model, rather than the model needing to “remember” it all from a long conversation. This code-steered state machine approach aligns with having a “logic controller at the top level to help it stay on track”. The model is not fully autonomous in deciding to change course; if it wants to deviate from the plan, the controlling code (or a supervising model) can intercept and require a formal re-plan or confirmation. This prevents random tangents from dragging irrelevant context into the prompt, thereby keeping the interaction efficient and goal-focused.

It’s worth noting that plan-and-execute is not a silver bullet for all cases – it introduces complexity in orchestrating multiple calls and tools – but it’s a powerful method to manage context for complex, long-horizon tasks. The success of frameworks like BabyAGI and the ReAct+Plan hybrids, as well as academic proposals like ReWOO (Reasoning Without Observing Observations)[50][51], demonstrate that interleaving planning with execution can outperform naive single-context agents. In ReWOO, for example, the planner LLM can output placeholders for results (like #E2 to refer to the result of step E2) that the executor fills in later[44][52]. This allows the final solution to be composed with minimal reiteration of context – each subtask had exactly the info it needed and no more[53].

To implement hierarchical planning in available frameworks: - LangChain (LangGraph) provides a Plan-and-Execute agent template where you supply a Planner LLM and an Executor (which could be another chain or agent)[43]. - OpenAI’s function calling can be used similarly by having a planning function – e.g., the model can output a plan in a structured format which the application then reads and executes step by step, calling the model only as needed for each step. - Google’s ADK implicitly encourages structured approaches by separating session state and tools; one could design the root agent to primarily output a plan (as a special tool or as part of the response) then use ADK’s callbacks to carry out those steps.

The takeaway is that structured orchestration reduces the need for huge prompts. Each agent (or sub-agent) deals with a slice of the problem, keeping context windows well under control. Moreover, by having a top-level controller (which can be classic code), you can enforce rules (guardrails) and avoid infinite loops. For example, if an agent’s plan seems to be thrashing (repeating similar steps), the orchestrator can detect this and adjust prompts or break the loop – something much harder to do if all reasoning is inside one LLM prompt invisibly.

Adaptive Context Techniques and Other Tips

Beyond the major strategies above, there are a few additional techniques worth mentioning:

  • Dynamic Instruction Emphasis: If you have important instructions or key context that must not be forgotten (like user requirements, or a safety guideline), it’s wise to place them at the beginningand end of the prompt when the context is long. OpenAI’s cookbook suggests repeating critical instructions at both the start and the tail of a long prompt to counteract the model’s primacy/recency bias[54]. This ensures that even if some middle details fade, the crucial points are reinforced. It does consume extra tokens, but for vital info it’s worth it.
  • Context Window Budgeting: Treat your prompt like a limited budget to be allocated. For example, in an 8k-tokenmodel, decide that at most 1k is for instructions/system prompt, 1k for recent conversation, 5k for retrieved knowledge or working content, and leave ~1k margin for the model’s output. By budgeting, you can proactively trim or compress content sections before hitting hard limits. Tools can be built to count tokens of planned context items and refuse to add less-important items if it would overflow the budget. Some developers even automate a “token optimizer” that drops low-priority info first and only keeps high-priority, echoing the guideline “drop irrelevant/redundant data, summarize long chunks, prioritize information”[55] (as illustrated in Fig. 2).

Figure 2: An example context injection pipeline (Akira AI) optimizing token usage. The system collects various sources (user query, retrieved knowledge chunks, system instructions, memory/history) and feeds them into a context optimizer. This optimizer drops irrelevant or redundant text, summarizes long inputs, and prioritizes key info to ensure the final assembled prompt fits within the model’s token limit. Only the essential instructions, query, compressed top-K knowledge chunks, and an optional brief history summary are included in the LLM’s final prompt.[9][24]

  • Middleware and Protocols for Context: As the field matures, we see proposals like Model Context Protocol (MCP)[56], which aim to standardize how applications provide context to LLMs. These protocols could allow developers to tag bits of context by type (e.g., “This is memory”, “This is user input”, “These are relevant docs”), and let the system decide how to window or truncate them. While still emerging, it’s a sign that context management is becoming a first-class concern – frameworks will likely offer more built-in support for common patterns (like automatic summarization of older turns, etc.). For now, engineers building agentic systems should explicitly design their context-handling logic rather than relying on raw LLM memory.
  • Testing and Tuning: It is important to test your agent’s performance with various context lengths. Try conversations that push the limits – does the agent start to forget things or loop when the history is long? If so, implement summarization earlier or increase retrieval relevance. Use metrics like response accuracy or coherence drop-off as history grows to inform your strategy[57][58]. Sometimes the solution might be to use a model with a larger context window for the planning parts and a smaller model for execution parts (a trade-off of cost vs memory). Always validate that the summarizer isn’t omitting something crucial by reviewing a sample of summaries.
  • Fallbacks for Exceeded Context: Despite best efforts, there may be cases where the agent has more information than can fit. In product design, it’s wise to have a fallback behavior.For instance, if a user’s query references an extremely large dataset that even retrieval can’t prune (say “Summarize this 1000-page document”), the system might respond: “That’s a lot to process at once; let me handle it in parts.” and then proceed in iterations. Or the agent can politely ask the user to narrow the scope. This is better than the agent failing silently or hallucinating by trying to summarize something it didn’t fully read. Product managers should consider exposing some limits (e.g., “I can only look at the last 100 messages”) or handling such cases with a graceful message, so the user understands the limitation or is guided to an alternative flow (like uploading the document to a data store first).

Applying These Strategies in Different Frameworks

We will now briefly relate how these best practices map to specific agent development frameworks and what tool support exists, particularly focusing on OpenAI’s Agents SDK and Google’s Agent Development Kit (ADK), as well as popular open-source frameworks like LangChain.

OpenAI Function-Calling Agents (OpenAI SDK)

OpenAI’s agents (as enabled through function calling and the OpenAI Agents Python SDK) incorporate context management ideas in their design. The OpenAI Agents SDK provides a clear separation between local context and LLM-visible context[59][33]. Developers can attach arbitrary data to a RunContext that persists across function calls and agent steps – this could include cached results, user profile info, or a running summary. Because this is not automatically fed to the model, it’s up to the developer to inject what’s needed when needed. OpenAI encourages patterns like dynamic system messages: you can define the agent’s system prompt as a function of the context (for instance, system_prompt(context) that inserts the user’s name or other relevant bits)[34]. This way, crucial context is added to the prompt explicitly rather than implicitly carrying everything in conversation turns.

For tool outputs, the OpenAI function approach naturally limits what goes into the prompt – the model must explicitly call a function to get some data, and the function’s return value is what gets appended to the conversation. So if you design your function to return a concise result (as discussed earlier, e.g. only the needed info), you’ve inherently controlled the prompt size. The model can’t see anything more.

Additionally, OpenAI’s ecosystem has the concept of a “contextual cache” (not yet standardized, but the developer community and unofficial tools use it) where you can cache recent instructions or pieces of data so that you don’t have to resend them every time. There’s also emerging tooling around conversation summarization within the API (OpenAI’s gpt-3.5-turbo-16k, for instance, can be used to summarize content that might be used to summarize older messages for GPT-4).

To illustrate, imagine using OpenAI’s API for an agent that interacts with a user and also uses a knowledge base: - You might maintain a summary of the conversation in a variable. Every time you send a new ChatCompletion request, you include something like:

messages = [ 
  {
    "role": "system", 
    "content": summary + "\nImportant information to remember."
  }, 
  … , 
  {"role": "user", "content": new_user_query} ]

This way the model always has the summary but not the full log.

Or you might use function calling: define a function retrieve_docs(query) that the model can call. The model might ask, retrieve_docs(‘topic X’), and your code executes that (searching your DB) and returns a short snippet as the function result. That snippet (plus maybe a citation) is then available for the model to use in composing the final answer. The context window only saw that snippet, not the entire database.

The key recommendation for OpenAI-based agents is: don’t rely on the raw conversation history alone. Use tools and structured prompts to supply information as needed, use summarization for older content, and keep prompts trim to reduce token usage – this has direct cost implications since OpenAI billing is per token.

Google ADK and Vertex AI Agents

Google’s Agent Development Kit (ADK) is similarly built with context and memory in mind. In ADK, an agent runs within a session which can have an associated Memory service[32][60]. By default, ADK will store all interactions in a Memory Bank (especially if using Vertex AI Agents with the memory feature enabled). This means the full history is persisted, but as discussed, it’s not shoved into the model each turn. Instead, the developer can call search_memory() within a tool or agent step to retrieve relevant bits[19][20]. For example, ADK’s documentation shows pseudo-code where a tool does: search_results = tool_context.search_memory(f"info related to {query}")[61]. The agent could use this before answering a user, ensuring it brings in any prior knowledge about the user or related topics from memory.

The ADK also supports context caching and state management. Each session has a state (which can hold key-value pairs) and you can configure how much of that state to feed into the prompt. In fact, Google’s approach encourages you to minimize prompt size by using their “Vertex AI Context Cache” to store static prompts (so you don’t send the same system message every time)[62] – although this is more about saving prompt tokens than context logic, it’s in line with efficiency best practices.

With the introduction of Vertex AI Memory Bank (in preview as of mid-2025), Google provides an automated way to handle long-term memory. As described earlier, Memory Bank will extract memories asynchronously from the conversation logs and allow retrieval by semantic similarity[28][30]. This strongly aligns with our recommendations: using a “memory-as-a-tool” paradigm (the agent calls the memory when needed, rather than dragging the whole history along). The Google Cloud blog explicitly states this is to “solve [memory scaling] by not populating a large context window repeatedly”[3]. We can thus leverage Memory Bank to keep the prompt focused: for each new query to the agent, do a memory lookup for relevant facts and only inject those facts into the prompt (likely as part of the system context or a prefix in the user prompt).

One thing to note for ADK: it provides a framework-level control over sessions and context. You can configure how sessions expire, how much history to carry by default, etc. If building an agentic product on GCP, you’d typically enable sessions + memory such that the heavy lifting of storing/retrieving past info is handled by Vertex AI, and your agent code just makes sure to call the memory at appropriate times. This is quite analogous to what we’d implement manually with LangChain or OpenAI, but it’s nice to have a managed service do it (including the embeddings, summarization, etc., with Google’s own models).

LangChain, LlamaIndex, and Other Frameworks

Outside the big cloud providers, many open-source frameworks offer abstractions for context management: - LangChain: It provides Memory classes that implement different strategies (buffer memory, summary memory, vector store memory, etc.). For example, ConversationBufferMemory keeps all messages (bad for long chats), whereas ConversationSummaryMemory uses an LLM to summarize old messages[10]. There’s also VectorStoreRetrieverMemory which automatically stores each message in a vector store and on each new query, retrieves similar past messages. The recommendation from LangChain is to use the summary or vector memory for long-running agents so they don’t exceed token limits. LangChain’s recent updates (LangChain 0.3+/LangGraph) also introduce the Plan-and-Execute agents as described, which inherently reduce context per call[41][42]. - LlamaIndex (GPT Index): This focuses on connecting LLMs with external data. It enables building a context index of documents or chat history, and can feed the LLM only the parts that are relevant via query. Many developers use LlamaIndex to manage large context: you can treat your conversation logs as a document, index it, and then at query time retrieve a summary or the most relevant exchange from earlier in the conversation to remind the LLM. It’s similar to LangChain’s retriever memory but with more flexibility in how data is structured (nodes, indices, etc.). - Haystack: Primarily for QA, it also has concepts of long-term memory and caching previous answers, etc. It’s less about agents, but if one were building an agent with Haystack, the retrieval component ensures only relevant context paragraphs are given to the model. - Custom Implementations: One can always build custom logic – e.g., using Redis or Pinecone as a memory store (Redis even published a guide on using it for agent memory[63][64]). The best practice there is to choose a robust embedding model, design good metadata filters (so you retrieve e.g. memories for the same user and same topic), and periodically clean the memory to drop outdated info.

Regardless of framework, the principles remain: summarize, retrieve selectively, partition context, and keep an eye on token usage. Frameworks differ in how much they automate; for instance, LangChain can automatically insert the memory into the prompt for you each time, whereas with a lower-level SDK you do it manually. But too much automation can be risky if it’s not tuned – e.g., a memory component that retrieves irrelevant stuff can actually harm performance by introducing confusion. So whatever the toolkit, it’s advisable to monitor what is being fed into the prompt and ensure it aligns with expectations.

Conclusion

Context window management is a critical aspect of building reliable and efficient agentic systems. By thoughtfully controlling what information an AI agent “sees” at each step, we can overcome the token limit barriers while enhancing the agent’s performance and user experience. The current best practices include compressing and summarizing past interactions[68], retrieving only relevant knowledge rather than dumping large documents[3], trimming unnecessary verbosity from tool outputs, and leveraging external memory stores to hold long-term information[27][28]. Moreover, adopting a structured approach with planning and sub-agents ensures that each AI step deals with a bounded context, preventing prompt bloat and enabling greater focus[69][43].

As we implement these techniques, it’s evident that they not only solve technical problems but also align with creating more human-like, context-aware AI assistants. Users benefit from agents that remember pertinent details, don’t ask the same questions over and over, and respond quickly without unnecessary fluff – all of which stem from good context management. On the flip side, users are also protected from the pitfalls of overload: less risk of the AI going off on tangents because it read some irrelevant paragraph in the prompt, and less chance of errors due to lost context in the middle of a long conversation.

Looking forward, we can expect tools and frameworks to further simplify context management. Larger context windows are emerging in new models, but as research shows, simply having more tokens isn’t a panacea if not used wisely[70][71]. The principles of relevance, summarization, and dynamic memory will remain important. Newer techniques like long context architectures (e.g., transformer variants with better long-text handling) and latent space planning might expand how we handle context, but those are still nascent. In the meantime, the strategies discussed here provide a robust toolkit to build agentic systems today.

In implementing these, tailor the approach to your domain and constraints: a cloud-based SaaS agent might lean heavily on a vector database and managed memory service, whereas an on-premises agent with a smaller model might rely more on aggressive summarization and strict truncation policies. Test and iterate – ensure the agent’s behavior remains consistent as conversation grows. With careful engineering, we can have agents that appear to have endless memory and attention, while under the hood we diligently swap things in and out of the limited context window. This illusion of unlimited context is what will make AI agents truly useful collaborators in complex tasks, without running into the walls of their inherent limitations.

Sources:

1.        Liu et al., “Lost in the Middle: How Language Models Use Long Contexts,” arXiv preprint 2023 – Evidence of LLM performance degrading for information in the middle of long prompts[72][73].

2.        Google Cloud, “Announcing Vertex AI Memory Bank (Preview),” 2025 – Discussion of inefficiencies of using raw context window for memory and introduction of Memory Bank for long-term agent memory[3][28].

3.        AWS Blog, “Amazon Bedrock AgentCore Memory: Building context-aware agents,” 2025 – Highlights need for manual context window management (pruning/summarizing) due to token limits[68] and describes AWS’s managed memory solution.

4.        OpenAI, “Context management – OpenAI Agents SDK Documentation,” 2023 – Explains separating local context vs LLM-visible context and methods to inject data into prompts (system messages, tools, etc.)[33][34].

5.        LangChain Blog, “Plan-and-Execute Agents,” 2024 – Describes the plan/execute architecture and its benefits for efficiency and focus[47][43], and notes each sub-task can have only required context[53].

6.        Akira AI Blog, “Context Engineering: The Complete Guide,” 2025 – Provides principles for context optimization (summarization, dropping low-relevance info)[9] and warns against context overload, with a diagram of context window management pipeline[55].

7.        Moveworks Documentation, “Context Window Management,” 2023 – Discusses how long conversation history can confuse LLMs and their policy of clearing context after a day to maintain relevance[5].


[1] [9] [13] [14] [15] [16] [21] [22] [23] [24] [25] [57] [58] Context Engineering: The Complete Guide

https://www.akira.ai/blog/context-engineering

[2] Context Engineering in Practice for AI Agents | by Hung Vo | Jul, 2025 | Medium

https://hungvtm.medium.com/context-engineering-in-practice-for-ai-agents-c15ee8b207d9

[3] [4] [27] [28] [29] [30] [31] [37] [38] [67] Vertex AI Memory Bank in public preview | Google Cloud Blog

https://cloud.google.com/blog/products/ai-machine-learning/vertex-ai-memory-bank-in-public-preview

[5] [65] [66] Context Window Management

https://help.moveworks.com/docs/context-window-management

[6] [7] [70] [71] [72] [73] [2307.03172] Lost in the Middle: How Language Models Use Long Contexts

https://ar5iv.labs.arxiv.org/html/2307.03172

[8] AutoGPT - Wikipedia

https://en.wikipedia.org/wiki/AutoGPT

[10] ConversationSummaryMemory — LangChain documentation

https://python.langchain.com/api_reference/langchain/memory/langchain.memory.summary.ConversationSummaryMemory.html

[11] [12] [26] [35] [36] [39] [40] [68] Amazon Bedrock AgentCore Memory: Building context-aware agents | Artificial Intelligence

https://aws.amazon.com/blogs/machine-learning/amazon-bedrock-agentcore-memory-building-context-aware-agents/

[17] [18] [33] [34] [59] Context management - OpenAI Agents SDK

https://openai.github.io/openai-agents-python/context/

[19] [20] [61] Context - Agent Development Kit

https://google.github.io/adk-docs/context/

[32] [60] How to build AI agents with long-term memory using Vertex AI ...

https://discuss.google.dev/t/how-to-build-ai-agents-with-long-term-memory-using-vertex-ai-memory-bank-adk/193013

[41] [42] [43] [44] [45] [46] [47] [48] [49] [50] [51] [52] [53] [69] Plan-and-Execute Agents

https://blog.langchain.com/planning-agents/

[54] GPT-4.1 Prompting Guide - OpenAI Cookbook

https://cookbook.openai.com/examples/gpt4-1_prompting_guide

[55] akira.ai

https://www.akira.ai/hs-fs/hubfs/undefined%20(6).png?width=898&height=506&name=undefined%20(6).png

[56] Model context protocol (MCP) - OpenAI Agents SDK

https://openai.github.io/openai-agents-python/mcp/

[62] Why tf would Google ADK not let us cache system instructions and ...

https://www.reddit.com/r/agentdevelopmentkit/comments/1lzhrek/why_tf_would_google_adk_not_let_us_cache_system/

[63] [64] Build smarter AI agents: Manage short-term and long-term memory ...

https://redis.io/blog/build-smarter-ai-agents-manage-short-term-and-long-term-memory-with-redis/

Aided by GPT-5 Deep Research