AI agents · Context engineering · Architecture

Context Engineering for AI Agents: Build a Context Assembler

Design a context pipeline that selects trusted instructions, relevant evidence, tool definitions, and recent state within an explicit token budget.

Published
Updated
Code examples
Illustrative
Reading time
6 minutes

Context engineering is the process of deciding what an agent sees on every model call, where each item came from, how much space it may consume, and whether it is allowed to influence behavior. A good implementation is a deterministic context assembler around the model—not one enormous prompt and not an unfiltered conversation transcript.

This guide designs that assembler. It is framework-neutral and intended for agents that use tools, retrieval, memory, or multiple turns. The outcome is a context packet whose contents can be inspected, tested, and reproduced.

Context is more than the system prompt

For an agent, context commonly contains six different classes of information:

ClassExampleAuthority
PolicySafety and authorization rulesApplication owner
TaskThe user's current goalUser, within policy
StateCurrent plan, completed steps, remaining budgetOrchestrator
EvidenceDocuments, search results, tool responsesUntrusted until verified
MemorySaved preferences and prior factsMixed; requires provenance
CapabilitiesTool names, schemas, and constraintsApplication/tool owner

Anthropic's September 2025 context-engineering note defines the problem as curating the tokens used for inference across instructions, tools, external data, and history—not merely wording a prompt. It also emphasizes that an agent loop continually creates more candidate context than should necessarily be carried forward. Anthropic's context-engineering guidance

Do not collapse those classes into a single text blob. If retrieved text can visually imitate a system instruction, the model may not preserve the authority boundary your application intended. Keep role, source, trust, and lifetime as structured metadata until final serialization.

Specify a context-item contract

The assembler should accept typed candidates and return both the model messages and an audit manifest.

type ContextKind =
  | "policy"
  | "task"
  | "state"
  | "evidence"
  | "memory"
  | "capability";

type Trust = "application" | "user" | "external";

interface ContextItem {
  readonly id: string;
  readonly kind: ContextKind;
  readonly trust: Trust;
  readonly source: string;
  readonly content: string;
  readonly estimatedTokens: number;
  readonly relevance: number; // Normalized by your retriever, 0..1.
  readonly createdAt: string;
  readonly expiresAt?: string;
  readonly supersedes?: readonly string[];
}

interface ContextPacket {
  readonly messages: readonly {
    role: "system" | "user";
    content: string;
  }[];
  readonly includedIds: readonly string[];
  readonly excluded: readonly {
    id: string;
    reason: string;
  }[];
  readonly estimatedTokens: number;
}

source must identify an origin that an operator can inspect, such as a document revision, tool-call ID, or user-message ID. A URL alone is insufficient when its content can change. Store a content digest or immutable revision alongside version-sensitive evidence.

Do not store credentials, session cookies, or approval tokens as context items. Pass authority to tools through an out-of-band execution layer with narrow scopes. OWASP's AI Agent Security Cheat Sheet recommends least-privilege tools, input and output validation, provenance-aware memory, and explicit human control for high-impact actions. OWASP AI Agent Security Cheat Sheet

Assemble in a fixed order

A useful assembler follows deterministic stages:

  1. Authorize: discard data the tenant or user may not read.
  2. Expire: remove stale items and items superseded by newer state.
  3. Classify: preserve instructions, state, evidence, and memory as distinct sections.
  4. Reserve: allocate space for the model's response and required policies first.
  5. Select: choose evidence by relevance, diversity, recency, and source quality.
  6. Compress: replace old interaction detail with an attributed state summary.
  7. Serialize: label untrusted content as data and keep it below authoritative instructions.
  8. Record: save the manifest, estimator version, and content digests.

Here is deliberately simple selection pseudocode. Production code needs a tokenizer appropriate to the selected model; character counts are not a reliable substitute.

function selectWithinBudget(
  required: readonly ContextItem[],
  optional: readonly ContextItem[],
  inputBudget: number,
): readonly ContextItem[] {
  const requiredTokens = required.reduce(
    (sum, item) => sum + item.estimatedTokens,
    0,
  );

  if (requiredTokens > inputBudget) {
    throw new Error("Required context exceeds the input budget");
  }

  const ranked = [...optional].sort((a, b) => {
    const utilityA = a.relevance / Math.max(a.estimatedTokens, 1);
    const utilityB = b.relevance / Math.max(b.estimatedTokens, 1);
    return utilityB - utilityA;
  });

  const selected = [...required];
  let used = requiredTokens;

  for (const item of ranked) {
    if (used + item.estimatedTokens > inputBudget) continue;
    selected.push(item);
    used += item.estimatedTokens;
  }

  return selected;
}

Utility-per-token is only a baseline. It can select five near-duplicate passages because each scores well independently. Add a diversity penalty, per-source caps, and mandatory opposing evidence where the task calls for comparison.

Do not equate context capacity with context quality

The published Lost in the Middle experiments found that the tested long-context models' performance changed with the position of relevant information, often declining when it appeared between the beginning and end. The paper is evidence about the evaluated models and tasks, not a universal law for every current model. It is still a strong reason to test placement rather than assuming that information is used equally wherever it fits. Liu et al., Lost in the Middle

Prefer a small, sufficient packet over filling the advertised window. Put immutable policy and the immediate task near the beginning. Put a concise action request near the end. Between them, group evidence with stable identifiers and explicit delimiters. Never rely on placement as a security control; authorization and tool policy must remain in code.

For long-running work, keep an external working state instead of repeatedly summarizing summaries. A state object might hold goals, completed steps, unresolved questions, artifact references, and budgets. The model can propose a state update; deterministic code validates and persists it.

Memory requires provenance and a deletion path

Persistent memory is candidate context, not truth. Store who or what wrote it, its tenant, evidence, confidence semantics, creation time, and expiry. Separate an observation such as “the user selected weekly reports” from an instruction such as “send all reports externally.”

OWASP's 2026 discussion of memory poisoning explains why carrying untrusted content across sessions turns a transient injection into a persistent attack surface. Treat memory writes as security-sensitive and make correction, quarantine, and deletion first-class operations. OWASP, “Memory Is a Feature. It Is Also an Attack Surface”

The Postgres and pgvector memory guide provides a schema for tenant isolation, provenance, retrieval, and forgetting. Context assembly should consume that store through an authorized query rather than bypassing its access boundary.

Test the assembler independently of the model

Most context behavior is deterministic enough for ordinary tests. Given fixed candidates and a budget, assert:

  • required policy is always present;
  • expired and cross-tenant items never appear;
  • a superseded state is excluded;
  • the response reserve is not consumed;
  • duplicate evidence is capped;
  • each included claim retains its source identifier;
  • untrusted text cannot change message roles; and
  • manifests reproduce the same packet under the same assembler version.

Then add model evaluations for the remaining questions: can the agent find evidence at different positions, distinguish instructions from quoted hostile text, report insufficient evidence, and carry task state across compaction? Version the model, tools, retriever, assembler, and evaluation set together.

Operational and cost tradeoffs

More context increases input processing and can expose more sensitive data. Aggressive compression costs another model call and can erase exceptions. Retrieval reduces input size but introduces indexing, authorization, and ranking failure modes. There is no universal allocation; measure task success, unsupported claims, input tokens, latency, cache behavior, and incidents on your own workload.

Use a simpler prompt plus a few examples when the task is one-shot, the input is already bounded, and no persistent or retrieved state is needed. A context pipeline earns its complexity when selection changes per turn or when provenance and authorization matter.

Context-assembler checklist

  • Classify every item as policy, task, state, evidence, memory, or capability.
  • Authorize before ranking or serialization.
  • Reserve output capacity and enforce a hard input budget.
  • Preserve origin, revision, trust, and expiry metadata.
  • Deduplicate evidence and cap any single source.
  • Keep secrets and execution authority outside model context.
  • Record inclusion and exclusion decisions.
  • Test information placement, hostile content, and compaction.
  • Provide memory correction and deletion.
  • Re-evaluate when the model, tokenizer, retriever, or tools change.