Context Engineering

Context engineering provides AI agents with rich, structured external reference materials to improve reasoning and decision-making.

1. Overview

Context engineering is the practice of providing AI agents with "the right information, at the right time, in the right format." For autonomous development agents, this means gathering external documentation, API specifications, examples, and best practices before agent execution.

The VendirContextAdvisor implements the "Select Context" strategy using vendir to declaratively fetch external content into the agent’s workspace.

2. Why Context Engineering?

Most agent failures are context failures, not model failures. Agents make better decisions when they have access to:

  • Framework documentation - Understanding APIs and patterns

  • API specifications - Correct usage of external services

  • Best practices - Industry-standard approaches

  • Examples - Real-world usage patterns

Without proper context, agents may:

  • Hallucinate non-existent APIs

  • Use deprecated patterns

  • Miss important conventions

  • Make suboptimal architectural decisions

3. Context Engineering vs RAG

A fundamental shift is happening in AI systems: direct context engineering is replacing traditional RAG (Retrieval-Augmented Generation) with vector stores for many agent workflows.

3.1. The Shift from Vector Search to File Access

Traditional LLM applications use vector stores and embedding-based similarity search. Agent systems are shifting to direct file access and navigation.

3.1.1. Sources Supporting This Shift

1. Anthropic Engineering Blog

Rather than relying on vector similarity search, agents can directly access codebases, search files with grep, and navigate directory structures—providing more precise and reliable context than approximate embeddings.

— Anthropic Engineering

2. Latent Space Podcast with LangChain

Harrison Chase (founder of LangChain) discusses how file-based context is replacing traditional semantic search for agent workflows in this podcast: Latent Space: Context Engineering

The observation from LangChain—a framework that pioneered vector-based RAG—validates this architectural shift toward direct file access for agents.

3.2. Why Context > RAG for Agents

Aspect Traditional RAG Context Engineering

Retrieval

Vector similarity search

Direct file access + grep

Accuracy

Approximate (embeddings)

Exact (string matching)

Recall

Top-k results (~80-90%)

Perfect (grep finds all matches)

Complexity

Vector DB + embeddings + chunking

File system operations

Agent Fit

Static retrieval

Dynamic navigation

Latency

Embedding + vector search

Native OS operations (faster)

Infrastructure

Vector database, embedding API

File system only

3.3. Example: Testing Spring Data JPA

Traditional RAG Approach:

// ❌ Complex: Vector store + embeddings + chunking
VectorStore vectorStore = new PgVectorStore(...);

// Embed all documentation
List<Document> docs = loadSpringDocs();
vectorStore.add(docs);

// Query with similarity search
List<Document> results = vectorStore.similaritySearch(
    SearchRequest.query("How to test Spring Data JPA repositories?")
        .withTopK(5)
        .withSimilarityThreshold(0.8)
);

// Hope the right docs are in top-5...
// Might get generic testing docs, might miss @DataJpaTest specifics

Context Engineering Approach:

// ✅ Simple: Agent explores directly
AgentClientResponse response = agentClientBuilder
    .goal("Write tests for UserRepository using Spring Data JPA best practices")
    .workingDirectory(projectRoot)
    .advisors(
        VendirContextAdvisor.builder()
            .vendirConfigPath("vendir-spring-boot.yml")
            .build()
    )
    .call();

// Agent dynamically:
// 1. grep -r "@DataJpaTest" docs/
// 2. Find test examples in fetched Spring Boot repo
// 3. Read UserRepository.java to understand entity
// 4. Navigate to Spring Data JPA testing docs
// 5. Write tests following discovered patterns

3.4. Benefits of Context Engineering

3.4.1. Perfect Recall

grep finds all matches, not approximate top-k:

# Agent can do this:
$ grep -r "OAuth2" docs/
# Finds EVERY occurrence

# vs Vector search top-5 (might miss important results)

3.4.2. Dynamic Navigation

Agents can follow references:

1. Find "@Configuration" classes
2. Notice import for OAuth2ClientConfig
3. Navigate to OAuth2ClientConfig.java
4. Read implementation details
5. Follow to examples

Vector search: Static top-k results
Agent: Dynamic navigation following code references

3.4.3. No Embedding Overhead

Traditional RAG:
1. Chunk documents
2. Generate embeddings (API calls + cost)
3. Store in vector DB
4. Query with embeddings (more API calls)
5. Post-process results

Context Engineering:
1. Give agent file access
2. Agent uses grep/find (instant, free)

3.4.4. Simpler Architecture

Traditional RAG Stack:
┌─────────────────┐
│   Application   │
└────────┬────────┘
         │
┌────────▼────────┐
│  Vector Store   │
│  (Postgres +    │
│   pgvector)     │
└────────┬────────┘
         │
┌────────▼────────┐
│ Embedding API   │
│  (OpenAI/etc)   │
└─────────────────┘

Context Engineering Stack:
┌─────────────────┐
│   Application   │
└────────┬────────┘
         │
┌────────▼────────┐
│  File System    │
└─────────────────┘

(That's it!)

3.5. When RAG Still Makes Sense

Context engineering doesn’t replace RAG everywhere:

Use Context Engineering When:

  • ✅ Working with codebases (files have structure)

  • ✅ Need exact file/directory navigation

  • ✅ Agent can explore dynamically

  • ✅ Documents have references (imports, links)

  • ✅ Precision is critical (no false positives)

Use RAG When:

  • ✅ Searching across massive unstructured corpora

  • ✅ Need semantic similarity (not exact match)

  • ✅ Content doesn’t have file/code structure

  • ✅ One-shot retrieval (no navigation needed)

  • ✅ User queries are semantic ("find documents about…​")

3.6. Context Engineering in Practice

VendirContextAdvisor implements context engineering by fetching relevant documentation into the agent’s workspace:

// Fetch Spring Security documentation
VendirContextAdvisor advisor = VendirContextAdvisor.builder()
    .vendirConfigPath("vendir.yml")
    .build();

AgentClientResponse response = agentClientBuilder
    .goal("Implement OAuth2 login following Spring Security best practices")
    .advisors(advisor)
    .call();

// Agent has direct file access to:
// - Spring Security reference docs
// - Code examples
// - Configuration templates
// - Migration guides

// Agent can grep, navigate, read—no vector store needed

4. VendirContextAdvisor

The VendirContextAdvisor automatically gathers external context before agent execution using vendir configuration files.

4.1. Basic Usage

// Create vendir configuration
Path vendirConfig = createVendirConfig(); // vendir.yml

// Create advisor
VendirContextAdvisor advisor = VendirContextAdvisor.builder()
    .vendirConfigPath(vendirConfig)
    .contextDirectory(".agent-context/vendir")
    .build();

// Register with AgentClient
AgentClient client = AgentClient.builder(agentModel)
    .defaultAdvisor(advisor)
    .build();

// Execute - context is gathered automatically before agent runs
AgentClientResponse response = client.run(
    "Implement Spring Boot actuator health endpoint following best practices"
);

4.2. Vendir Configuration

Create a vendir.yml file specifying what external content to fetch:

apiVersion: vendir.k14s.io/v1alpha1
kind: Config
directories:
- path: vendor
  contents:
  # Clone entire repository
  - path: spring-guide
    git:
      url: https://github.com/spring-guides/gs-rest-service
      ref: main
      depth: 1    # Shallow clone for efficiency

  # Fetch specific paths
  - path: spring-boot-docs
    git:
      url: https://github.com/spring-projects/spring-boot
      ref: v3.3.0
      depth: 1
    includePaths:
    - README.adoc

  # HTTP source
  - path: api-specs
    http:
      url: https://example.com/api-spec.yaml

For complete vendir configuration options, see the official vendir documentation.

5. Configuration Options

5.1. Context Directory

Specify where context files are placed:

VendirContextAdvisor advisor = VendirContextAdvisor.builder()
    .vendirConfigPath("vendir.yml")
    .contextDirectory(".agent-context/vendir") // Default
    .build();

Context files are placed in {workingDirectory}/.agent-context/vendir/vendor/.

5.2. Timeout

Configure how long vendir has to fetch content:

VendirContextAdvisor advisor = VendirContextAdvisor.builder()
    .vendirConfigPath("vendir.yml")
    .timeout(300) // 5 minutes (default)
    .build();

5.3. Auto-cleanup

Optionally remove context files after agent execution:

VendirContextAdvisor advisor = VendirContextAdvisor.builder()
    .vendirConfigPath("vendir.yml")
    .autoCleanup(true) // Default: false (keep for inspection)
    .build();

5.4. Execution Order

Control when context is gathered relative to other advisors:

import org.springframework.core.Ordered;

VendirContextAdvisor advisor = VendirContextAdvisor.builder()
    .vendirConfigPath("vendir.yml")
    .order(Ordered.HIGHEST_PRECEDENCE + 100) // Default: early execution
    .build();

6. Context Metadata

The advisor adds metadata to request/response contexts for observability:

AgentClientResponse response = client.run("Some goal");

// Check if context was gathered successfully
Boolean success = (Boolean) response.context().get("vendir.context.success");
String contextPath = (String) response.context().get("vendir.context.path");
String output = (String) response.context().get("vendir.context.output");

if (!success) {
    String error = (String) response.context().get("vendir.context.error");
    logger.warn("Context gathering failed: {}", error);
}

7. Examples

7.1. Clone Entire Repository

apiVersion: vendir.k14s.io/v1alpha1
kind: Config
directories:
- path: vendor
  contents:
  - path: spring-guide
    git:
      url: https://github.com/spring-guides/gs-rest-service
      ref: main
      depth: 1
VendirContextAdvisor advisor = VendirContextAdvisor.builder()
    .vendirConfigPath("vendir.yml")
    .build();

AgentClient client = AgentClient.builder(agentModel)
    .defaultAdvisor(advisor)
    .build();

client.run("Based on the Spring guide, create a similar REST service for products");

7.2. Fetch Specific Files

apiVersion: vendir.k14s.io/v1alpha1
kind: Config
directories:
- path: vendor
  contents:
  - path: spring-boot
    git:
      url: https://github.com/spring-projects/spring-boot
      ref: v3.3.0
      depth: 1
    includePaths:
    - README.adoc

7.3. HTTP Sources

apiVersion: vendir.k14s.io/v1alpha1
kind: Config
directories:
- path: vendor
  contents:
  - path: api-spec
    http:
      url: https://api.example.com/openapi.yaml

8. Spring Boot Integration

Register as a Spring bean for automatic configuration:

@Configuration
public class ContextEngineeringConfig {

    @Bean
    public VendirContextAdvisor vendirContextAdvisor() {
        return VendirContextAdvisor.builder()
            .vendirConfigPath("context/vendir.yml")
            .contextDirectory(".agent-context")
            .timeout(300)
            .autoCleanup(false)
            .build();
    }

    @Bean
    public AgentClient agentClient(
            AgentModel agentModel,
            VendirContextAdvisor contextAdvisor) {
        return AgentClient.builder(agentModel)
            .defaultAdvisor(contextAdvisor)
            .build();
    }
}

9. Error Handling

The advisor handles failures gracefully:

  • Vendir not installed - Logs error, agent continues without context

  • Network failures - Logs error, agent continues without context

  • Invalid configuration - Logs error, agent continues without context

  • Timeout - Logs error, agent continues without context

Failures are recorded in the context for observability:

AgentClientResponse response = client.run("Some goal");

if (!(Boolean) response.context().get("vendir.context.success")) {
    String error = (String) response.context().get("vendir.context.error");
    // Handle degraded execution
}

10. Tips

  • Use depth: 1 for faster shallow clones

  • Use includePaths to fetch only relevant files

  • Keep autoCleanup: false during development to inspect gathered context

  • Adjust timeout based on repository size


Context engineering transforms autonomous agents from isolated tools into context-aware developers that understand and respect external APIs, frameworks, and best practices.