Back to Blog
multi-agent systemscontext drifttoken fragmentationLLM context windowagentic AICrewAI memoryLahorePakistan

The Hidden Overhead of Autonomy: Mitigating Context Drift and Token Fragmentation in Multi-Agent AI Systems

Anber Aziz•Lahore, Pakistan•
Multi-agent conversation history compressed while system rules stay at the top of context

Long-running multi-agent systems fail when history becomes the prompt. Context drift is attention sliding off system rules as tool dumps pile up; token fragmentation is the same budget wasted on duplicates, retries, and overlapping specialist chatter. Fix it with an explicit memory controller: isolate instructions, summarize the middle, keep a short live tail, and sync durable state outside the chat log.

When engineering basic AI applications, developers focus on prompt optimization and embeddings. As those apps become production-scale multi-agent systems, a new class of bottleneck appears. When independent agents pass JSON tools, execution feedback, and telemetry back and forth, the state variables start to degrade.

That degradation is context window drift and memory fragmentation. Isolated runs look fine. Long-running conversations hit memory limits, forget original instructions, or loop. Autonomy looks cheap in a demo because the demo is short.

Who this is for

This is for product teams putting more than one agent in front of customers, for startups whose token bill became a line item, and for engineering teams in Lahore, across Pakistan, and working remote-from-Pakistan who cannot hide unbounded context behind a lab budget.

If you are a product manager, drift looks like "the agent ignored the policy we wrote yesterday." If you are a founder, fragmentation looks like a GPU or API invoice that grows with conversation length, not with value. If you are an engineer, this is prompt compilation, not more persona text.

What actually causes context decay?

Agents usually communicate by appending task output onto a shared chat history. As Agent A passes a vulnerability scan to Agent B, the global context expands.

Large language models evaluate sequences with attention weights. As history grows, attention on earlier system safety instructions thins out:

[Initial run]  System rules (high attention) -> task -> output
[Extended run] System rules (low attention)  -> history bloat -> hallucination risk

Agents then lose operational constraints: messy formatting, duplicated pipelines, or misread API variables. Linear text accumulation has to be replaced with a structured, sliding-window memory controller.

I also see a second failure that looks like drift but is really fragmentation. The same stack trace appears four times. Two agents summarize the same ticket in different words. A tool returns a 40 KB HTML page that nobody needed in the next prompt. The window is full, but the useful bits are sparse. Compression without a schema just turns that junk into a vague paragraph.

Symptoms I treat as memory bugs, not model bugs

  • Output schema that was perfect in turn one and decorative by turn twelve.
  • Agents re-doing a tool call whose result is already in the log.
  • Safety or tenancy rules that vanish after a long tool chain.
  • Loops that "almost" finish, then restart the plan from scratch.

If a single-shot prompt on a fresh context still succeeds, the weights are fine. The runtime is not.

How does a deterministic context truncation engine work?

Rather than dumping raw logs into the model, put an intermediary controller in front. It summarizes older loops while preserving system instructions.

export class AgentContextManager {
  constructor(maxTokenThreshold = 4000) {
    this.maxTokenThreshold = maxTokenThreshold;
    this.coreSystemInstructions = "";
    this.ephemeralConversationHistory = [];
  }

  initializeSystemRules(rulesText) {
    this.coreSystemInstructions = rulesText;
  }

  appendTransactionEvent(role, content) {
    this.ephemeralConversationHistory.push({
      role,
      content,
      timestamp: Date.now(),
    });
  }

  async compileOptimizedPayload(summarizerService) {
    let compiledPayload = `${this.coreSystemInstructions}\n\n`;

    if (this.ephemeralConversationHistory.length > 10) {
      const blocksToSummarize = this.ephemeralConversationHistory.slice(0, -4);
      const activePreservedContext = this.ephemeralConversationHistory.slice(-4);
      const compressedSummary =
        await summarizerService.generateSummaryString(blocksToSummarize);

      compiledPayload += `[Summary of historical context]: ${compressedSummary}\n\n`;
      activePreservedContext.forEach((event) => {
        compiledPayload += `${event.role.toUpperCase()}: ${event.content}\n`;
      });
    } else {
      this.ephemeralConversationHistory.forEach((event) => {
        compiledPayload += `${event.role.toUpperCase()}: ${event.content}\n`;
      });
    }

    return compiledPayload;
  }
}

Architectural notes

  • System rules isolation keeps safety constraints at the top of the attention field.
  • Asynchronous compression of older turns can cut token spend substantially.
  • Preserving the last four turns keeps short-term tactical context intact.

I compile on every LLM call, not once per session. The class above is a sketch: in production I count tokens (or a tight character budget if the tokenizer is unavailable), not message counts. Ten messages of stack traces can exceed four thousand tokens by themselves.

The summarizer should be a smaller, cheaper model with a rigid instruction: preserve identifiers, URLs, error codes, and decisions; drop greetings and repeated reasoning. I never let the specialist agents summarize their own history unsupervised. They are motivated to keep looking busy. The controller is motivated to stay under budget.

Pin the live tail to tool results and user-visible decisions, not to chain-of-thought. If you buffer internal scratchpads, you pay twice: once to generate them, again to re-feed them.

How should state stay synchronized across a multi-agent graph?

A single-agent chain is only the start. Concurrent specialists need a shared source of truth. Don't let agents message each other ad hoc. Push outputs to a coordinator (Redis or MongoDB), wrap the new state into a clean package, and hand it to the next agent. That keeps data synchronized and compute overhead down.

Think in three layers:

  1. Policy — system rules, tenancy, disallowed tools. Always in the prefix. Never summarized away.
  2. Artifacts — scan JSON, diffs, ticket ids. In a store. Referenced by id in the prompt.
  3. Narrative — what happened in this run. Eligible for summary.

When Agent B needs the CVE list, it should receive the list (or a pointer), not Agent A's entire monologue. Crew-style frameworks make it easy to concatenate everything. I treat that default as a footgun.

Memory styleToken curveDrift riskI use it for
Full transcriptLinear growthHighDemos and traces only
Last-k messagesFlat-ishMedium (rules still drown)Short tools
Prefix + summary + tailBoundedLow if artifacts are externalProduction crews
Per-agent views + coordinator storeBoundedLowestParallel specialists

What else belongs in a production memory policy?

  • Hard caps and kill switches. If a crew has not emitted a terminal artifact in N steps, stop. Drift loves infinite planners.
  • Tool result truncation. HTML, PDFs, and raw packet dumps enter the store, not the prompt. The prompt gets a hash, a path, and a 20-line extract.
  • Replay for debugging. Operators need the full log. The model does not. Keep them separate.
  • Evaluation. Score long runs the same way you score short ones: did the final artifact still honor the original constraints? If only turn one does, you have drift.

How do I measure token fragmentation before it becomes a bill?

Fragmentation is waste you can count. I log three numbers per compiled payload: tokens in the system prefix, tokens in the summary, and tokens in the live tail. If the tail grows faster than the summary shrinks, the controller is not actually bounding anything—it is just delaying overflow.

I also log duplication. A cheap check is hashing tool payloads. If the same hash appears twice in one run, the second copy should be a pointer (tool_result_ref: abc) rather than another 8,000 tokens of JSON. Multi-agent graphs are especially good at this: the analyst restates the scout's list, the reporter restates the analyst, and the coordinator echoes all three.

When I am diagnosing a looping crew, I dump the compiled prefix next to the original kickoff instructions and diff them. If the prefix has drifted—someone "helpfully" merged a summary into the system rules—I treat that as a bug in the controller, not as a smarter agent. Rules are append-only from a human, never from a summarizer.

A compiled packet I actually hand to the next specialist looks like this:

POLICY: (verbatim system rules)
GOAL: (one paragraph, from the coordinator)
ARTIFACTS: (ids + inline excerpts, not raw dumps)
RECENT: (last tool errors and the last user-visible decision)
SUMMARY: (narrative only)

That packet is smaller than a chat history and more honest than a vibe. Product teams in Pakistan paying frontier APIs in dollars feel this immediately; remote-from-Pakistan latency also punishes giant prompts that do not change the answer.

I build production AI and full-stack systems from Lahore, and the multi-agent work that survives contact with users is the work with a compiler in front of the window. Anber Aziz is the byline because I have watched crews look intelligent for eight turns and then forget the tenant they were not allowed to touch.

If you are wiring specialists together and the token curve or the instruction-following is already bending, services outlines how I approach production agent architecture, and contact is the place to start.

FAQ

What is context drift in a multi-agent system?

Context drift is the gradual loss of attention on original instructions as agents append tool output, retries, and chatter to a shared history. The model still generates fluent text, but constraints, schemas, and safety rules weaken. It shows up as format breakage, repeated work, and goals that no longer match the kickoff.

How do I stop agents from blowing the context window?

Do not append raw logs forever. Keep system rules in a dedicated prefix, summarize older turns, and preserve only a short live tail. Cap tool payloads before they enter history. A memory controller in front of the LLM is cheaper than a larger model with a longer window.

Should every agent share one chat history?

No. Shared transcripts turn into a junk drawer. Give each specialist a role-specific view and persist durable state in a store the coordinator owns. Pass a compiled packet—goal, constraints, artifacts—not the entire gossip log.

Is summarization safe for tool-using agents?

Summaries lose IDs, error codes, and numbers if you are careless. Keep structured artifacts (CVE ids, file paths, JSON results) in a side channel and summarize only narrative. Re-inject exact records when the next agent needs them.

How should startups in Pakistan budget multi-agent token use?

Treat tokens as a product cost, not a lab curiosity. A truncation-plus-summary loop on a modest model usually beats an unbounded crew on a frontier model. Engineering teams in Lahore and remote-from-Pakistan companies should meter tokens per run and kill loops that do not converge.

Ada
AdaOnline
Anber's AI Assistant

Before we begin

So Anber can follow up with you if needed.