Agent System Architecture

How Bootspring's AI expert agents work.

Overview#

The agent system provides specialized AI personas for different development tasks. Each agent has expertise in a specific domain and collaborates with others.

Agent Architecture#

┌─────────────────────────────────────────────────────────────────────┐ │ AGENT SYSTEM │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ Agent │ │ Context │ │ LLM │ │ │ │ Registry │───▶│ Builder │───▶│ Provider │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ Profile │ │ Project │ │ Response │ │ │ │ Loader │ │ Context │ │ Processor │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────┘

Agent Profile#

Profile Structure#

1interface AgentProfile { 2 // Identity 3 name: string; 4 displayName: string; 5 description: string; 6 avatar?: string; 7 8 // Classification 9 category: AgentCategory; 10 tier: Tier; 11 tags: string[]; 12 13 // Behavior 14 systemPrompt: string; 15 capabilities: string[]; 16 limitations: string[]; 17 18 // Collaboration 19 collaborates: string[]; 20 delegates: DelegationRule[]; 21 22 // Configuration 23 model?: string; 24 temperature?: number; 25 maxTokens?: number; 26 27 // Extensions 28 tools?: Tool[]; 29 examples?: Example[]; 30} 31 32type AgentCategory = 33 | 'development' 34 | 'quality' 35 | 'architecture' 36 | 'business' 37 | 'design'; 38 39type Tier = 'free' | 'pro' | 'team' | 'enterprise';

Example Profile#

1# agents/frontend-expert.yaml 2 3name: frontend-expert 4displayName: Frontend Expert 5description: Expert in React, Next.js, and modern frontend development 6 7category: development 8tier: free 9tags: [react, nextjs, typescript, css, tailwind] 10 11systemPrompt: | 12 You are a senior frontend developer with deep expertise in: 13 - React 18+ with Server Components 14 - Next.js 14+ App Router 15 - TypeScript best practices 16 - Tailwind CSS and modern styling 17 - Performance optimization 18 - Accessibility (WCAG 2.1) 19 20 When helping users: 21 1. Prefer Server Components when possible 22 2. Use TypeScript with strict mode 23 3. Follow React best practices (hooks, composition) 24 4. Consider performance and accessibility 25 5. Provide complete, working code examples 26 27capabilities: 28 - React component development 29 - Next.js App Router patterns 30 - Tailwind CSS styling 31 - Form handling and validation 32 - State management 33 - API integration 34 - Performance optimization 35 - Accessibility implementation 36 37limitations: 38 - Backend/database design (delegate to backend-expert) 39 - Infrastructure/DevOps (delegate to devops-expert) 40 - Security audits (delegate to security-expert) 41 42collaborates: 43 - ui-ux-expert 44 - testing-expert 45 - performance-expert 46 - backend-expert 47 48delegates: 49 - pattern: "database|schema|prisma" 50 to: database-expert 51 - pattern: "api|endpoint|route" 52 to: api-expert 53 - pattern: "security|auth|permission" 54 to: security-expert 55 56examples: 57 - prompt: "Create a data table component" 58 response: | 59 Here's a reusable data table component...

Agent Registry#

Registry Implementation#

1// core/agents/registry.ts 2 3export class AgentRegistry { 4 private agents: Map<string, AgentProfile> = new Map(); 5 private categories: Map<AgentCategory, string[]> = new Map(); 6 7 async loadAll(agentsPath: string): Promise<void> { 8 const files = await glob('*.yaml', { cwd: agentsPath }); 9 10 for (const file of files) { 11 const content = await readFile(join(agentsPath, file), 'utf-8'); 12 const profile = parseYaml<AgentProfile>(content); 13 14 this.register(profile); 15 } 16 } 17 18 register(profile: AgentProfile): void { 19 // Validate profile 20 this.validate(profile); 21 22 // Store in registry 23 this.agents.set(profile.name, profile); 24 25 // Index by category 26 const categoryAgents = this.categories.get(profile.category) || []; 27 categoryAgents.push(profile.name); 28 this.categories.set(profile.category, categoryAgents); 29 } 30 31 get(name: string): AgentProfile | undefined { 32 return this.agents.get(name); 33 } 34 35 list(filter?: AgentFilter): AgentProfile[] { 36 let results = Array.from(this.agents.values()); 37 38 if (filter?.category) { 39 results = results.filter(a => a.category === filter.category); 40 } 41 if (filter?.tier) { 42 results = results.filter(a => TIER_ORDER[a.tier] <= TIER_ORDER[filter.tier!]); 43 } 44 if (filter?.tags) { 45 results = results.filter(a => 46 filter.tags!.some(t => a.tags.includes(t)) 47 ); 48 } 49 50 return results; 51 } 52}

Agent Invocation#

Invoker Implementation#

1// core/agents/invoker.ts 2 3export class AgentInvoker { 4 private registry: AgentRegistry; 5 private contextBuilder: ContextBuilder; 6 private llmProvider: LLMProvider; 7 private entitlements: EntitlementChecker; 8 9 async invoke( 10 agentName: string, 11 prompt: string, 12 options: InvokeOptions = {} 13 ): Promise<AgentResponse> { 14 // 1. Load agent profile 15 const agent = this.registry.get(agentName); 16 if (!agent) { 17 throw new AgentNotFoundError(agentName); 18 } 19 20 // 2. Check entitlements 21 await this.checkEntitlements(agent, options.userId); 22 23 // 3. Build context 24 const context = await this.buildContext(agent, options); 25 26 // 4. Prepare messages 27 const messages = this.prepareMessages(agent, prompt, context); 28 29 // 5. Invoke LLM 30 const startTime = Date.now(); 31 const response = await this.llmProvider.complete(messages, { 32 model: agent.model || 'claude-3-5-sonnet', 33 temperature: agent.temperature ?? 0.7, 34 maxTokens: options.maxTokens || agent.maxTokens || 4096, 35 }); 36 37 // 6. Process response 38 const processed = await this.processResponse(response, agent); 39 40 // 7. Track usage 41 await this.trackUsage({ 42 agent: agentName, 43 duration: Date.now() - startTime, 44 tokens: response.usage, 45 userId: options.userId, 46 }); 47 48 return processed; 49 } 50 51 private async buildContext( 52 agent: AgentProfile, 53 options: InvokeOptions 54 ): Promise<InvocationContext> { 55 const context: InvocationContext = { 56 agent: { 57 name: agent.name, 58 capabilities: agent.capabilities, 59 }, 60 }; 61 62 // Add project context 63 if (options.projectId) { 64 context.project = await this.contextBuilder.getProjectContext( 65 options.projectId 66 ); 67 } 68 69 // Add file context 70 if (options.files?.length) { 71 context.files = await this.contextBuilder.getFileContents( 72 options.files 73 ); 74 } 75 76 // Add conversation history 77 if (options.history?.length) { 78 context.history = options.history; 79 } 80 81 return context; 82 } 83 84 private prepareMessages( 85 agent: AgentProfile, 86 prompt: string, 87 context: InvocationContext 88 ): Message[] { 89 const messages: Message[] = []; 90 91 // System message with agent persona 92 messages.push({ 93 role: 'system', 94 content: this.buildSystemPrompt(agent, context), 95 }); 96 97 // Add history if present 98 if (context.history) { 99 messages.push(...context.history); 100 } 101 102 // User prompt 103 messages.push({ 104 role: 'user', 105 content: this.buildUserPrompt(prompt, context), 106 }); 107 108 return messages; 109 } 110}

Context Building#

Context Builder#

1// core/agents/context-builder.ts 2 3export class ContextBuilder { 4 async build(options: ContextOptions): Promise<string> { 5 const sections: string[] = []; 6 7 // Agent context 8 sections.push(this.formatAgentContext(options.agent)); 9 10 // Project context 11 if (options.project) { 12 sections.push(await this.formatProjectContext(options.project)); 13 } 14 15 // File contents 16 if (options.files?.length) { 17 sections.push(await this.formatFileContents(options.files)); 18 } 19 20 // Custom context 21 if (options.custom) { 22 sections.push(options.custom); 23 } 24 25 return sections.join('\n\n---\n\n'); 26 } 27 28 private formatAgentContext(agent: AgentProfile): string { 29 return ` 30## Agent: ${agent.displayName} 31 32**Capabilities:** 33${agent.capabilities.map(c => `- ${c}`).join('\n')} 34 35**Collaboration:** 36When appropriate, suggest involving: 37${agent.collaborates.map(c => `- ${c}`).join('\n')} 38 `.trim(); 39 } 40 41 private async formatProjectContext(projectId: string): Promise<string> { 42 const context = await this.loadProjectContext(projectId); 43 44 return ` 45## Project Context 46 47${context.summary} 48 49**Tech Stack:** ${context.stack.join(', ')} 50**Key Files:** 51${context.keyFiles.map(f => `- ${f.path}: ${f.description}`).join('\n')} 52 `.trim(); 53 } 54}

Agent Collaboration#

Delegation System#

1// core/agents/delegation.ts 2 3export class DelegationManager { 4 private registry: AgentRegistry; 5 6 shouldDelegate( 7 agent: AgentProfile, 8 prompt: string 9 ): DelegationSuggestion | null { 10 for (const rule of agent.delegates || []) { 11 const regex = new RegExp(rule.pattern, 'i'); 12 13 if (regex.test(prompt)) { 14 const targetAgent = this.registry.get(rule.to); 15 16 if (targetAgent) { 17 return { 18 from: agent.name, 19 to: rule.to, 20 reason: `This task involves ${rule.pattern}, which is better handled by ${targetAgent.displayName}`, 21 confidence: this.calculateConfidence(prompt, rule), 22 }; 23 } 24 } 25 } 26 27 return null; 28 } 29 30 suggestCollaborators( 31 agent: AgentProfile, 32 prompt: string 33 ): CollaborationSuggestion[] { 34 const suggestions: CollaborationSuggestion[] = []; 35 36 for (const collaborator of agent.collaborates) { 37 const collaboratorProfile = this.registry.get(collaborator); 38 39 if (collaboratorProfile && this.isRelevant(prompt, collaboratorProfile)) { 40 suggestions.push({ 41 agent: collaborator, 42 reason: `${collaboratorProfile.displayName} could help with ${this.getRelevantCapability(prompt, collaboratorProfile)}`, 43 }); 44 } 45 } 46 47 return suggestions; 48 } 49}

Multi-Agent Workflows#

1// core/agents/orchestration.ts 2 3export class MultiAgentOrchestrator { 4 async orchestrate( 5 task: Task, 6 agents: string[] 7 ): Promise<OrchestrationResult> { 8 const results: AgentResult[] = []; 9 10 for (const agentName of agents) { 11 // Get previous results as context 12 const previousContext = this.formatPreviousResults(results); 13 14 // Invoke agent with context 15 const result = await this.invoker.invoke(agentName, task.prompt, { 16 context: previousContext, 17 task: task.id, 18 }); 19 20 results.push({ 21 agent: agentName, 22 response: result, 23 }); 24 25 // Check if task is complete 26 if (this.isTaskComplete(task, results)) { 27 break; 28 } 29 } 30 31 return { 32 task: task.id, 33 agents: results.map(r => r.agent), 34 finalResponse: this.synthesizeResults(results), 35 }; 36 } 37}

Response Processing#

Processor Implementation#

1// core/agents/processor.ts 2 3export class ResponseProcessor { 4 process(response: LLMResponse, agent: AgentProfile): AgentResponse { 5 const content = response.content; 6 7 return { 8 id: generateId(), 9 agent: agent.name, 10 content: content, 11 type: this.detectResponseType(content), 12 codeBlocks: this.extractCodeBlocks(content), 13 suggestions: this.extractSuggestions(content, agent), 14 usage: response.usage, 15 timestamp: new Date(), 16 }; 17 } 18 19 private detectResponseType(content: string): ResponseType { 20 if (content.includes('```')) return 'code'; 21 if (content.includes('##')) return 'documentation'; 22 if (content.includes('- [ ]')) return 'checklist'; 23 return 'text'; 24 } 25 26 private extractCodeBlocks(content: string): CodeBlock[] { 27 const regex = /```(\w+)?\n([\s\S]*?)```/g; 28 const blocks: CodeBlock[] = []; 29 let match; 30 31 while ((match = regex.exec(content)) !== null) { 32 blocks.push({ 33 language: match[1] || 'text', 34 code: match[2].trim(), 35 }); 36 } 37 38 return blocks; 39 } 40}

Agent Categories#

Development Agents#

AgentExpertise
frontend-expertReact, Next.js, CSS
backend-expertAPIs, servers, logic
database-expertSchemas, queries, optimization
api-expertREST, GraphQL, design
mobile-expertReact Native, iOS, Android

Quality Agents#

AgentExpertise
testing-expertUnit, integration, E2E
security-expertAuth, vulnerabilities, compliance
performance-expertOptimization, profiling
code-review-expertBest practices, patterns

Architecture Agents#

AgentExpertise
architecture-expertSystem design, patterns
devops-expertCI/CD, infrastructure
cloud-expertAWS, GCP, Azure

Business Agents#

AgentExpertise
business-strategy-expertStrategy, planning
fundraising-expertInvestors, pitching
growth-expertMetrics, acquisition