Context Bundles: Teaching AI Agents Your Codebase
The biggest bottleneck in AI coding is intelligence—it is context. Learn how context bundles teach AI agents your codebase systematically, keeping them focused and productive.
The biggest bottleneck in AI coding isn't intelligence—it's context.
Your AI assistant is capable of sophisticated reasoning, but it can't think about your codebase without knowing what's in it. Feed it incomplete or scattered information, and you get scattered solutions. Feed it a thousand lines of irrelevant boilerplate, and you waste tokens that could have been used for actual problem-solving.
This is the context problem: how do you give an AI agent exactly the right knowledge at exactly the right time?
At Trinity Agency, we've been solving this in our swarm architecture with something we call context bundles—a systematic way to package, score, and automatically attach curated domain knowledge to agent tasks.
The Context Bottleneck
Consider a typical scenario: An agent is tasked with adding a feature to your authentication system. To do this well, it needs to know:
- Where your auth code lives
- What patterns you use for JWT handling
- Which files it can modify and which are off-limits
- Your conventions for error handling
- What related features already exist
- Why previous decisions were made
Without this context, the agent either asks questions (slowing you down) or makes assumptions (creating bugs).
The traditional approach is to dump everything into the system prompt: copy the entire codebase directory structure, relevant code snippets, your conventions document, everything. This works for small projects, but it breaks at scale. You hit token limits. The signal-to-noise ratio collapses. The agent drowns in irrelevant details.
What you need is selective context—just the right knowledge for the job at hand.
What Are Context Bundles?
A context bundle is a self-contained package of curated knowledge about a single domain. Each bundle contains:
- Domain: The area it covers (e.g., "authentication", "database", "swarm-lifecycle")
- Keywords: Terms that trigger relevance matching (e.g., "JWT", "token", "auth flow")
- File References: Specific files to include, marked with purpose (read, modify, create, reference)
- Conventions: Compact markdown documenting patterns and best practices for that domain
- Knowledge Graph Queries: Automated queries to pull fresh context from your knowledge base
- Modification Targets: Which files the agent is expected to edit
- Affinities: Agent types this bundle is most useful for (e.g., "implementer", "backend")
Think of bundles as domain-specific context primers. Instead of drowning agents in all your knowledge, you give them exactly what they need for their task.
Here's what a real bundle looks like from Trinity's swarm SDK:
export interface ContextBundle {
id: string;
slug: string;
domain: string;
title: string;
description: string;
affinities: string[]; // e.g., ["implementer", "backend"]
keywords: string[]; // e.g., ["task", "field", "potential"]
file_refs: FileRef[]; // e.g., path, purpose, annotation
modification_targets: ModificationTarget[];
kg_queries: KgQueryPrompt[]; // Fresh knowledge from your graph
conventions: string; // Markdown best practices
priority: number;
is_active: boolean;
version: number;
}
How Scoring Works
The magic happens in the matching algorithm. When a new task arrives, the system scores every active bundle against that task. Only the highest-scoring bundles attach.
The scoring formula is elegantly simple:
score = (domainMatch × 3.0)
+ (min(keywordHits, 3) × 2.0)
+ (min(affinityOverlap, 2) × 1.5)
Max score: 12.0
Threshold: 1.0 (must score this high to attach)
Breaking it down:
Domain Match (3.0 points) If the task is about authentication and your "auth-patterns" bundle covers the authentication domain, it gets 3.0 points immediately. This is the strongest signal—domain detection from task analysis.
Keyword Hits (up to 6.0 points) If the task mentions keywords from the bundle (up to 3 matches, 2.0 points each), it scores higher. A bundle with keywords ["JWT", "token", "refresh"] will attach to a task mentioning "JWT token validation" because it hits 2 keywords.
Affinity Overlap (up to 3.0 points) If the task is assigned to an "implementer" agent and your bundle lists "implementer" in its affinities, both get points. This ensures backend bundles attach to backend agents.
The threshold of 1.0 means even a single keyword match guarantees attachment—no false negatives. The cap at 4 bundles maximum prevents context bloat.
Here's the actual implementation from our SDK:
export function scoreBundleMatch(
bundle: ContextBundle,
taskText: string,
taskAffinities: string[],
detectedDomains: string[],
): number {
const lowerText = taskText.toLowerCase();
// Domain match: 3.0 if bundle domain appears in detected domains
const domainScore = detectedDomains.includes(bundle.domain) ? 3.0 : 0;
// Keyword hits: count matches in task text, cap at 3, weight 2.0 each
let keywordHits = 0;
for (const kw of bundle.keywords) {
if (lowerText.includes(kw.toLowerCase())) {
keywordHits++;
if (keywordHits >= 3) break;
}
}
const keywordScore = keywordHits * 2.0;
// Affinity overlap: intersection of bundle affinities and task affinities
let affinityOverlap = 0;
const taskAffSet = new Set(taskAffinities.map((a) => a.toLowerCase()));
for (const aff of bundle.affinities) {
if (taskAffSet.has(aff.toLowerCase())) {
affinityOverlap++;
if (affinityOverlap >= 2) break;
}
}
const affinityScore = affinityOverlap * 1.5;
return domainScore + keywordScore + affinityScore;
}
This is deterministic, fast, and debuggable—you can always explain why a bundle attached.
Lazy Re-Matching: Fresh Context at Claim Time
Here's where it gets clever. Bundles don't attach once and stay attached. Instead, they're lazily re-matched when an agent claims a task.
This means:
- When a task is deposited, bundles attach based on initial scoring
- When an agent claims the task, the system refreshes all bundle matches against the latest active bundles
- New bundles created after the task was deposited are automatically discovered
- Stale bundles are removed
- Scores are recalculated
This is crucial for long-running swarms where new domains and patterns emerge over time. Your agents always get the latest context without manual curation.
export async function refreshBundlesForNode(
sql: Sql,
nodeId: string,
task: { title: string; content?: Record<string, unknown>; affinity?: string[] },
): Promise<void> {
const matches = await matchBundlesToNode(sql, task);
await sql.begin(async (tx) => {
// Clear existing attachments for this node
await tx`DELETE FROM field_node_bundles WHERE node_id = ${nodeId}::uuid`;
// Insert fresh matches
if (matches.length > 0) {
const values = matches.map((m) => ({
node_id: nodeId,
bundle_id: m.bundle_id,
match_score: m.match_score,
attached_by: 'system:lazy-rematch',
}));
await tx`
INSERT INTO field_node_bundles ${tx(values, 'node_id', 'bundle_id', 'match_score', 'attached_by')}
ON CONFLICT (node_id, bundle_id) DO UPDATE SET match_score = EXCLUDED.match_score
`;
}
});
}
The transaction ensures atomicity—either all old bundles are replaced, or none are. No race conditions, no partial attachments.
The Knowledge Graph Integration
Context bundles aren't static snapshots. They can include Knowledge Graph queries that fetch fresh context at render time.
Each bundle can declare:
kg_queries: [
{
query: "Agent lifecycle patterns",
project: "codebase",
limit: 3
},
{
query: "Field operations examples",
project: "codebase",
limit: 3
}
]
When an agent loads its context, the system executes these queries in parallel and appends the results. This means your bundles automatically pull the latest patterns, examples, and learnings from your knowledge base—no manual updates needed.
If the knowledge graph is unavailable (timeout, network error), the bundle still loads—it just skips the fresh queries. Graceful degradation.
Why This Matters
Context bundles solve three problems simultaneously:
1. Scaling Context Without Bloat As your codebase grows, you don't dump more files into the system prompt. You create more bundles, each focused on one domain.
2. Keeping Context Fresh Lazy re-matching + knowledge graph queries mean agent context evolves as your codebase evolves. No stale documentation.
3. Making Context Predictable Because scoring is deterministic, you can debug why certain context attached (or didn't). No mysterious "why did it ignore my authentication patterns?"
Building Your Own Bundles
If you're building an agentic system, context bundles are worth implementing:
- Identify your domains — authentication, database, API, frontend, infrastructure
- Create bundles for each — one bundle per domain, not one monolithic bundle
- Define keywords — think like a search engine. What would someone type to find this?
- Document conventions — make your implicit patterns explicit
- Wire up scoring — use the algorithm above. It works.
- Integrate knowledge graph — let your system learn from its own decisions
The implementation is straightforward. The payoff is massive: agents that understand your codebase as well as your team does.
The Future of Agentic Context
Context bundles are one answer to a bigger question: How do we scale AI agents from toy projects to production systems?
The answer isn't smarter models—it's better context. It's systematic knowledge management. It's treating context engineering as seriously as we treat software architecture.
At Trinity Agency, context bundles are part of our thermodynamic swarm—a self-organizing system where agents sense tasks, discover relevant context, and execute with precision. No prompts written by hand. No manual context engineering per task. Just bundles, scoring, and autonomous agents that always have what they need.
That's the future we're building.
Want to see context bundles in action? Build with Trinity Agency and watch your agents ship faster with fewer mistakes.