03 - Agent Decision Trees: How Contextual Intelligence Actually Thinks
Part 2: Breaking down the decision logic that transforms retrieved context into intelligent actions
Agent Decision Trees: How Contextual Intelligence Actually Thinks
Part 3 of the Technical Deep Dive Series
In Part 2: Anatomy of a Retrieval, we saw how the Guardrailed Retriever Stack finds relevant context. But retrieval is only half the story. The real magic happens in what agents do with that context.
This is the decision engine that transforms generic AI into contextual intelligence.
The Core Problem: Context Without Intelligence is Just Data
Here's what happens when you give raw context to a generic AI:
// Generic AI approach
const context = await retrieve("How should I implement user auth?");
const response = await ai.complete({
prompt: `Context: ${context}\n\nQuestion: How should I implement user auth?`,
model: "gpt-4"
});
// Result: Generic OAuth2 tutorial, ignores your actual architecture
Here's what happens with contextual intelligence:
// Contextual intelligence approach
const context = await retrieveWithRouting("How should I implement user auth?", config);
const decision = await agentDecisionTree.process(context, query, projectState);
// Result: Specific implementation that matches your patterns, dependencies, and constraints
The Agent Decision Framework
Every enhanced agent in RouteKit Shell follows this decision tree:
Step 1: Context Gathering - The Intelligence Foundation
Every agent starts with systematic context gathering. Here's the actual implementation:
// .claude/agents/engineering/routekit-shell-frontend-developer.md
export class ContextualFrontendAgent {
async gatherContext(query: string): Promise<ContextBundle> {
// Step 1a: Search for existing solutions
const existingSolutions = await ragQuery({
query: `${query} implementation examples`,
k: 3
});
// Step 1b: Find architectural patterns
const patterns = await ragQuery({
query: `${extractDomain(query)} patterns architecture`,
k: 3
});
// Step 1c: Identify constraints
const constraints = await ragQuery({
query: `technical constraints ${extractDomain(query)}`,
k: 2
});
return {
existingSolutions,
patterns,
constraints,
confidence: calculateContextConfidence([existingSolutions, patterns, constraints])
};
}
}
Step 2: Pattern Analysis - Finding What Already Works
The agent analyzes retrieved context to identify reusable patterns:
async analyzePatterns(context: ContextBundle): Promise<PatternAnalysis> {
// Extract pattern signatures
const signatures = context.existingSolutions.map(solution => ({
dependencies: extractDependencies(solution.text),
architecture: identifyArchitecture(solution.text),
complexity: assessComplexity(solution.text)
}));
// Find consensus patterns
const consensus = findConsensus(signatures);
// Identify deviations and their reasons
const deviations = signatures.filter(sig =>
!matchesPattern(sig, consensus)
).map(sig => ({
pattern: sig,
reason: identifyDeviationReason(sig, context.constraints)
}));
return {
primaryPattern: consensus,
alternativePatterns: deviations,
confidence: consensus.support / signatures.length
};
}
Step 3: Constraint Evaluation - Respecting Project Reality
Generic AI ignores constraints. Contextual intelligence respects them:
async evaluateConstraints(
patterns: PatternAnalysis,
context: ContextBundle
): Promise<ConstraintEvaluation> {
const constraints = {
// Technical constraints
dependencies: extractAllowedDependencies(context),
architecture: extractArchitecturalConstraints(context),
performance: extractPerformanceConstraints(context),
// Business constraints
timeline: extractTimelineConstraints(context),
team: extractTeamConstraints(context),
maintenance: extractMaintenanceConstraints(context)
};
// Filter patterns by constraints
const viablePatterns = patterns.filter(pattern =>
satisfiesConstraints(pattern, constraints)
);
// Rank by constraint satisfaction
const rankedPatterns = viablePatterns.sort((a, b) =>
constraintScore(b, constraints) - constraintScore(a, constraints)
);
return {
constraints,
viablePatterns: rankedPatterns,
rejectedPatterns: patterns.filter(p => !viablePatterns.includes(p))
};
}
Real Decision Tree Walkthrough: Frontend Component Architecture
Let's trace a real query through the decision tree:
Query: "Create a user profile component with avatar upload"
Step 1: Context Gathering
// RAG queries executed in parallel
const context = await Promise.all([
ragQuery("user profile component implementation", 3),
ragQuery("avatar upload patterns React", 3),
ragQuery("file upload constraints security", 2)
]);
// Results found:
// - 3 existing profile components in different projects
// - 2 avatar upload implementations
// - 1 security constraint document about file uploads
Step 2: Pattern Analysis
// Pattern extraction
const patterns = analyzePatterns(context);
/*
Primary Pattern Found:
- React functional component with hooks
- Separate upload service for file handling
- Optimistic UI updates with fallback
- Integration with existing design system
Confidence: 0.85 (85% of examples follow this pattern)
*/
Step 3: Constraint Evaluation
// Constraint checking
const constraints = evaluateConstraints(patterns, context);
/*
Active Constraints:
- Must use existing RouteKit design system components
- File upload limited to 2MB (security constraint)
- No new dependencies without approval
- Must support mobile responsive design
Viable Patterns: 1 (primary pattern satisfies all constraints)
*/
Step 4: Solution Architecture
// Architecture decision
const architecture = designSolution(patterns[0], constraints);
/*
Recommended Architecture:
Component: ProfileComponent.tsx
Service: AvatarUploadService.ts
Design: Use existing Card, Button, Avatar from design system
Validation: Client-side size check + server-side validation
State: React hooks for upload state management
*/
Step 5: Implementation Planning
// Implementation breakdown
const plan = createImplementationPlan(architecture, context);
/*
Implementation Plan:
1. Create ProfileComponent using existing Card pattern
2. Implement AvatarUploadService following existing file service pattern
3. Add upload validation using existing validation utils
4. Integrate with existing error handling system
5. Add loading states using existing spinner component
6. Write tests following existing component test patterns
Files to create: 3
Files to modify: 1 (add service to index)
Estimated complexity: Medium
*/
Step 6: Validation & Safety
// Final validation
const validation = validateSolution(plan, context, constraints);
/*
Validation Results:
✅ Follows existing architectural patterns
✅ Uses approved dependencies only
✅ Meets security constraints
✅ Integrates with existing design system
✅ Has test coverage plan
✅ Handles error cases per existing patterns
Safety Score: 0.95
Ready for implementation: true
*/
The Decision Tree Outputs: Contextual vs Generic
Generic AI Output:
Create a React component with useState for the profile data and use
a file input for avatar upload. You'll need to handle the file upload
to your backend and update the UI accordingly.
Contextual Intelligence Output:
// Based on your existing Card and Avatar patterns, here's the recommended approach:
// ProfileComponent.tsx - follows your established component patterns
import { Card, Avatar, Button } from '@/components/design-system';
import { useAvatarUpload } from '@/hooks/useAvatarUpload'; // matches existing hook patterns
export const ProfileComponent = () => {
const { uploadAvatar, isUploading, error } = useAvatarUpload({
maxSize: 2 * 1024 * 1024, // respects your 2MB security constraint
onSuccess: (url) => updateUserProfile({ avatarUrl: url })
});
// Implementation follows your existing error handling patterns
// Uses your established loading state conventions
// Integrates with your existing validation system
};
// This approach:
// ✅ Uses your existing design system components
// ✅ Follows your established hook patterns
// ✅ Respects your file size security constraints
// ✅ Integrates with your existing error handling
// ✅ Matches your team's component structure conventions
Advanced Decision Patterns
Pattern 1: Cross-Domain Intelligence
When a query spans multiple domains, agents collaborate:
// Frontend agent recognizes backend implications
if (requiresBackendChanges(solution)) {
const backendContext = await ragQuery(
`backend API patterns ${extractBackendRequirements(solution)}`,
3
);
solution.backendRecommendations = await consultBackendAgent(
backendContext,
solution
);
}
Pattern 2: Progressive Complexity
Agents start simple and add complexity only when needed:
const complexityLevels = [
'minimal_viable_implementation',
'production_ready_implementation',
'enterprise_scale_implementation'
];
let selectedComplexity = complexityLevels[0];
// Upgrade complexity based on constraints
if (constraints.userLoad > 10000) selectedComplexity = complexityLevels[1];
if (constraints.compliance.required) selectedComplexity = complexityLevels[2];
Pattern 3: Failure Recovery
When primary patterns fail constraints, agents have fallback strategies:
// Primary pattern fails constraints
if (!satisfiesConstraints(primaryPattern, constraints)) {
// Try alternative patterns
for (const altPattern of alternativePatterns) {
if (satisfiesConstraints(altPattern, constraints)) {
return adaptPattern(altPattern, constraints);
}
}
// No existing pattern works - synthesize new approach
return synthesizeNewPattern(constraints, context);
}
The Self-Improving Loop
Here's the remarkable part: agents learn from their decisions.
// After implementation
async recordDecisionOutcome(
decision: AgentDecision,
outcome: ImplementationOutcome
) {
// Store successful patterns for future use
if (outcome.success) {
await storePattern({
query: decision.originalQuery,
solution: decision.recommendedSolution,
context: decision.context,
satisfaction: outcome.userSatisfaction
});
}
// Learn from failures
if (!outcome.success) {
await recordAntiPattern({
pattern: decision.recommendedSolution,
failureReason: outcome.failureReason,
context: decision.context
});
}
}
This creates a feedback loop where successful decisions become preferred patterns for future queries.
Performance Characteristics
The decision tree is surprisingly fast:
| Decision Tree Phase | Time Range | Process |
|---|---|---|
| Context Gathering | 200-500ms | 3-5 parallel RAG queries |
| Pattern Analysis | 50-100ms | JavaScript pattern matching |
| Constraint Evaluation | 20-50ms | Rule engine evaluation |
| Solution Architecture | 30-80ms | Template generation |
| Implementation Planning | 40-100ms | Complexity analysis |
| Validation & Safety | 10-30ms | Constraint checking |
| TOTAL DECISION TIME | 350-860ms | Complete contextual decision |
Performance Comparison:
| Approach | Time Required | Context Quality |
|---|---|---|
| Human architect research | 2-4 hours | High (with experience) |
| Generic AI with manual context | 15-30 minutes back-and-forth | Low (context switching) |
| Contextual intelligence | Under 1 second | High (maintained context) |
The Meta-Decision: When to Decide vs When to Ask
Agents make meta-decisions about their own decision-making:
const decisionConfidence = calculateConfidence(
contextQuality,
patternMatch,
constraintCertainty
);
if (decisionConfidence > 0.8) {
// High confidence - proceed with recommendation
return makeDecision(context, patterns, constraints);
} else if (decisionConfidence > 0.5) {
// Medium confidence - present options
return presentAlternatives(viablePatterns, reasoning);
} else {
// Low confidence - ask clarifying questions
return requestClarification(missingContext, uncertainConstraints);
}
What Makes This Different from Generic AI
Generic AI: "Here are some options for user authentication"
Contextual Intelligence: "Based on your existing JWT middleware, MongoDB user schema, and the security constraints documented in Decision 003, I recommend extending your existing auth service with OAuth2 support using the same error handling patterns you've established. This integrates with your existing user management flow and respects your no-new-dependencies constraint."
The difference: Context-aware reasoning that respects established patterns and constraints.
Continue the Series
Next: 04 - From Architecture to Product Intelligence - How contextual AI transforms product development
*This is Part 3 of our Technical Deep Dive series exploring AI-first development frameworks. Next:
