TypeScript SDK Advanced Patterns
Multi-Agent Orchestration
Coordinated Agent System
import { query, type SDKMessage } from "@anthropic-ai/claude-code";
interface Agent {
name: string;
role: string;
systemPrompt: string;
expertise: string[];
}
interface AgentMessage {
agent: string;
content: string;
timestamp: Date;
}
class MultiAgentOrchestrator {
private agents: Map<string, Agent> = new Map();
private conversation: AgentMessage[] = [];
constructor() {
this.initializeAgents();
}
private initializeAgents() {
// Code Architect
this.agents.set('architect', {
name: 'System Architect',
role: 'architect',
systemPrompt: `You are a senior system architect. Focus on:
- High-level design patterns
- System architecture decisions
- Technology stack recommendations
- Scalability and performance considerations`,
expertise: ['architecture', 'design patterns', 'scalability']
});
// Security Expert
this.agents.set('security', {
name: 'Security Expert',
role: 'security',
systemPrompt: `You are a security expert. Focus on:
- Security vulnerabilities
- Authentication and authorization
- Data protection
- Security best practices`,
expertise: ['security', 'authentication', 'encryption']
});
// Code Reviewer
this.agents.set('reviewer', {
name: 'Code Reviewer',
role: 'reviewer',
systemPrompt: `You are a meticulous code reviewer. Focus on:
- Code quality and maintainability
- Performance optimizations
- Best practices adherence
- Potential bugs and edge cases`,
expertise: ['code quality', 'performance', 'best practices']
});
}
async consultAgents(
task: string,
relevantAgents?: string[]
): Promise<Map<string, string>> {
const responses = new Map<string, string>();
const agentsToConsult = relevantAgents || Array.from(this.agents.keys());
// Parallel consultation
const consultations = agentsToConsult.map(async (agentId) => {
const agent = this.agents.get(agentId)!;
const response = await this.consultAgent(agent, task);
return { agentId, response };
});
const results = await Promise.all(consultations);
for (const { agentId, response } of results) {
responses.set(agentId, response);
this.conversation.push({
agent: agentId,
content: response,
timestamp: new Date()
});
}
return responses;
}
private async consultAgent(agent: Agent, task: string): Promise<string> {
const contextPrompt = this.buildContextPrompt(agent, task);
let response = '';
for await (const message of query({
prompt: contextPrompt,
abortController: new AbortController(),
options: {
systemPrompt: agent.systemPrompt,
maxTurns: 1
}
})) {
if (message.type === 'assistant') {
response = message.data.message.content as string;
}
}
return response;
}
private buildContextPrompt(agent: Agent, task: string): string {
// Include relevant previous responses
const relevantContext = this.conversation
.filter(msg => msg.agent !== agent.role)
.slice(-3)
.map(msg => `${this.agents.get(msg.agent)?.name}: ${msg.content}`)
.join('\n\n');
return `
Task: ${task}
${relevantContext ? `Previous team input:\n${relevantContext}\n\n` : ''}
Please provide your expert opinion as the ${agent.name}.
`;
}
async synthesizeResponses(
responses: Map<string, string>
): Promise<string> {
const synthesisPrompt = `
Synthesize these expert opinions into a cohesive recommendation:
${Array.from(responses.entries())
.map(([agentId, response]) => {
const agent = this.agents.get(agentId)!;
return `${agent.name}:\n${response}`;
})
.join('\n\n---\n\n')}
Provide a unified recommendation that incorporates all perspectives.
`;
let synthesis = '';
for await (const message of query({
prompt: synthesisPrompt,
abortController: new AbortController(),
options: {
systemPrompt: 'You are a technical lead synthesizing expert opinions.',
maxTurns: 1
}
})) {
if (message.type === 'assistant') {
synthesis = message.data.message.content as string;
}
}
return synthesis;
}
}
// Usage example
async function architectureReview(codebase: string) {
const orchestrator = new MultiAgentOrchestrator();
// Get all agents' opinions
const responses = await orchestrator.consultAgents(
`Review this proposed architecture: ${codebase}`
);
// Synthesize into final recommendation
const recommendation = await orchestrator.synthesizeResponses(responses);
return {
individualOpinions: Object.fromEntries(responses),
synthesis: recommendation
};
}Adaptive Prompt Engineering
Dynamic Prompt Optimization
interface PromptMetrics {
promptId: string;
successRate: number;
avgResponseQuality: number;
avgTokenCount: number;
avgResponseTime: number;
}
class AdaptivePromptEngine {
private promptVariants = new Map<string, string[]>();
private metrics = new Map<string, PromptMetrics>();
private abTestResults = new Map<string, Map<string, number>>();
registerPromptVariants(baseId: string, variants: string[]) {
this.promptVariants.set(baseId, variants);
// Initialize metrics for each variant
variants.forEach((_, index) => {
const variantId = `${baseId}_v${index}`;
this.metrics.set(variantId, {
promptId: variantId,
successRate: 0,
avgResponseQuality: 0,
avgTokenCount: 0,
avgResponseTime: 0
});
});
}
async selectOptimalPrompt(
baseId: string,
context?: Record<string, any>
): Promise<string> {
const variants = this.promptVariants.get(baseId);
if (!variants || variants.length === 0) {
throw new Error(`No variants registered for ${baseId}`);
}
// Use Thompson Sampling for selection
const scores = await this.calculateVariantScores(baseId);
const selectedIndex = this.thompsonSampling(scores);
return this.personalizePrompt(variants[selectedIndex], context);
}
private async calculateVariantScores(
baseId: string
): Promise<number[]> {
const variants = this.promptVariants.get(baseId)!;
return variants.map((_, index) => {
const variantId = `${baseId}_v${index}`;
const metrics = this.metrics.get(variantId)!;
// Composite score based on multiple factors
const qualityWeight = 0.4;
const successWeight = 0.3;
const efficiencyWeight = 0.3;
const qualityScore = metrics.avgResponseQuality;
const successScore = metrics.successRate;
const efficiencyScore = 1 - (metrics.avgTokenCount / 1000); // Normalize
return (
qualityScore * qualityWeight +
successScore * successWeight +
efficiencyScore * efficiencyWeight
);
});
}
private thompsonSampling(scores: number[]): number {
// Add randomness for exploration
const samples = scores.map(score => {
const alpha = score * 10 + 1; // Success count
const beta = (1 - score) * 10 + 1; // Failure count
return this.betaRandom(alpha, beta);
});
// Select highest sampled value
return samples.indexOf(Math.max(...samples));
}
private betaRandom(alpha: number, beta: number): number {
// Simplified Beta distribution sampling
const x = this.gammaRandom(alpha);
const y = this.gammaRandom(beta);
return x / (x + y);
}
private gammaRandom(shape: number): number {
// Simplified Gamma distribution (Marsaglia & Tsang method)
if (shape < 1) {
return this.gammaRandom(shape + 1) * Math.pow(Math.random(), 1 / shape);
}
const d = shape - 1/3;
const c = 1 / Math.sqrt(9 * d);
while (true) {
const x = this.normalRandom();
const v = Math.pow(1 + c * x, 3);
if (v > 0 && Math.log(Math.random()) < 0.5 * x * x + d - d * v + d * Math.log(v)) {
return d * v;
}
}
}
private normalRandom(): number {
// Box-Muller transform
const u = 1 - Math.random();
const v = Math.random();
return Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v);
}
private personalizePrompt(
template: string,
context?: Record<string, any>
): string {
if (!context) return template;
// Dynamic variable replacement
let personalized = template;
for (const [key, value] of Object.entries(context)) {
personalized = personalized.replace(
new RegExp(`{{${key}}}`, 'g'),
String(value)
);
}
// Conditional sections
personalized = this.processConditionals(personalized, context);
return personalized;
}
private processConditionals(
template: string,
context: Record<string, any>
): string {
// Handle {{#if condition}} ... {{/if}} blocks
const conditionalRegex = /{{#if\s+(\w+)}}([\s\S]*?){{\/if}}/g;
return template.replace(conditionalRegex, (match, condition, content) => {
return context[condition] ? content : '';
});
}
async recordResult(
promptId: string,
result: {
success: boolean;
quality: number; // 0-1
tokenCount: number;
responseTime: number;
}
) {
const metrics = this.metrics.get(promptId);
if (!metrics) return;
// Update metrics with exponential moving average
const alpha = 0.2; // Learning rate
metrics.successRate = alpha * (result.success ? 1 : 0) +
(1 - alpha) * metrics.successRate;
metrics.avgResponseQuality = alpha * result.quality +
(1 - alpha) * metrics.avgResponseQuality;
metrics.avgTokenCount = alpha * result.tokenCount +
(1 - alpha) * metrics.avgTokenCount;
metrics.avgResponseTime = alpha * result.responseTime +
(1 - alpha) * metrics.avgResponseTime;
}
}
// Usage
const promptEngine = new AdaptivePromptEngine();
// Register variants for code review prompts
promptEngine.registerPromptVariants('code-review', [
'Review this {{language}} code for bugs and improvements:\n{{code}}',
'Analyze the following {{language}} code. Identify issues and suggest enhancements:\n{{code}}',
'As an expert {{language}} developer, review this code:\n{{code}}\nFocus on correctness and performance.'
]);
// Use the optimal prompt
const optimalPrompt = await promptEngine.selectOptimalPrompt('code-review', {
language: 'TypeScript',
code: 'function example() { ... }'
});Streaming Pipeline Architecture
Advanced Stream Processing
interface PipelineStage<T, R> {
name: string;
process(input: T): Promise<R> | R;
onError?: (error: Error) => void;
}
class StreamPipeline {
private stages: PipelineStage<any, any>[] = [];
addStage<T, R>(stage: PipelineStage<T, R>): this {
this.stages.push(stage);
return this;
}
async *execute<T>(
source: AsyncIterable<T>
): AsyncGenerator<any> {
for await (const item of source) {
let current: any = item;
for (const stage of this.stages) {
try {
current = await stage.process(current);
// Allow stages to yield multiple values
if (current && typeof current[Symbol.asyncIterator] === 'function') {
yield* current;
} else {
yield {
stage: stage.name,
data: current
};
}
} catch (error) {
if (stage.onError) {
stage.onError(error as Error);
} else {
throw error;
}
}
}
}
}
}
// Specialized pipeline stages
class CodeAnalysisPipeline {
static createPipeline() {
return new StreamPipeline()
.addStage({
name: 'parse',
process: async (message: SDKMessage) => {
if (message.type !== 'assistant') return null;
const content = message.data.message.content as string;
// Extract code blocks
const codeBlocks = content.match(/```[\s\S]*?```/g) || [];
return {
content,
codeBlocks: codeBlocks.map(block => ({
language: block.match(/```(\w+)/)?.[1] || 'unknown',
code: block.replace(/```\w*\n?|\n?```/g, '')
}))
};
}
})
.addStage({
name: 'analyze',
process: async (parsed: any) => {
if (!parsed || !parsed.codeBlocks) return null;
const analyses = await Promise.all(
parsed.codeBlocks.map(async (block: any) => ({
...block,
complexity: calculateComplexity(block.code),
lineCount: block.code.split('\n').length,
hasTests: block.code.includes('test(') || block.code.includes('describe('),
hasTypes: block.language === 'typescript' || block.code.includes(': ')
}))
);
return {
...parsed,
analyses
};
}
})
.addStage({
name: 'enhance',
process: async (analyzed: any) => {
if (!analyzed) return null;
// Generate suggestions based on analysis
const suggestions = analyzed.analyses.map((analysis: any) => {
const items = [];
if (analysis.complexity > 10) {
items.push('Consider breaking down complex functions');
}
if (!analysis.hasTests && analysis.lineCount > 20) {
items.push('Add unit tests for this code');
}
if (!analysis.hasTypes && analysis.language === 'javascript') {
items.push('Consider adding TypeScript types');
}
return {
code: analysis.code,
suggestions: items
};
});
return {
...analyzed,
suggestions
};
}
});
}
}
function calculateComplexity(code: string): number {
// Simplified cyclomatic complexity
const conditionals = (code.match(/if|else|switch|case|while|for|\?|&&|\|\|/g) || []).length;
const functions = (code.match(/function|=>|async/g) || []).length;
return conditionals + functions;
}
// Usage
async function analyzeCodeStream(prompt: string) {
const pipeline = CodeAnalysisPipeline.createPipeline();
const messageStream = query({
prompt,
abortController: new AbortController()
});
for await (const result of pipeline.execute(messageStream)) {
console.log(`[${result.stage}]`, result.data);
}
}Context Window Management
Intelligent Context Optimization
interface ContextItem {
id: string;
content: string;
priority: number;
tokens: number;
lastUsed: Date;
useCount: number;
}
class ContextWindowManager {
private maxTokens = 100000; // Claude's context limit
private reservedTokens = 4000; // Reserve for response
private contextItems = new Map<string, ContextItem>();
async optimizeContext(
newPrompt: string,
requiredContext: string[] = []
): Promise<string> {
const promptTokens = await this.estimateTokens(newPrompt);
const availableTokens = this.maxTokens - this.reservedTokens - promptTokens;
// Score all context items
const scoredItems = this.scoreContextItems(requiredContext);
// Select items that fit within token budget
const selectedItems = this.selectOptimalItems(scoredItems, availableTokens);
// Build optimized context
return this.buildContext(newPrompt, selectedItems);
}
private scoreContextItems(required: string[]): ContextItem[] {
const now = new Date();
const items = Array.from(this.contextItems.values());
return items
.map(item => ({
...item,
score: this.calculateScore(item, required.includes(item.id), now)
}))
.sort((a, b) => b.score - a.score);
}
private calculateScore(
item: ContextItem,
isRequired: boolean,
now: Date
): number {
if (isRequired) return Infinity;
// Recency factor (exponential decay)
const hoursSinceUse = (now.getTime() - item.lastUsed.getTime()) / 3600000;
const recencyScore = Math.exp(-hoursSinceUse / 24); // 24-hour half-life
// Frequency factor
const frequencyScore = Math.log(item.useCount + 1) / 10;
// Priority factor
const priorityScore = item.priority / 10;
// Combined score
return (
recencyScore * 0.4 +
frequencyScore * 0.3 +
priorityScore * 0.3
);
}
private selectOptimalItems(
items: (ContextItem & { score: number })[],
tokenBudget: number
): ContextItem[] {
const selected: ContextItem[] = [];
let usedTokens = 0;
for (const item of items) {
if (item.score === Infinity || usedTokens + item.tokens <= tokenBudget) {
selected.push(item);
usedTokens += item.tokens;
// Update usage stats
item.lastUsed = new Date();
item.useCount++;
}
}
return selected;
}
private buildContext(prompt: string, items: ContextItem[]): string {
const sections = items
.map(item => `### ${item.id}\n${item.content}`)
.join('\n\n');
return `
## Context
${sections}
## Task
${prompt}
`;
}
async addContext(
id: string,
content: string,
priority: number = 5
): Promise<void> {
const tokens = await this.estimateTokens(content);
this.contextItems.set(id, {
id,
content,
priority,
tokens,
lastUsed: new Date(),
useCount: 0
});
}
private async estimateTokens(text: string): Promise<number> {
// Rough estimation: ~4 characters per token
return Math.ceil(text.length / 4);
}
pruneOldContext(maxAge: number = 7 * 24 * 3600000) {
const now = new Date();
for (const [id, item] of this.contextItems) {
const age = now.getTime() - item.lastUsed.getTime();
if (age > maxAge && item.priority < 8) {
this.contextItems.delete(id);
}
}
}
}
// Usage
const contextManager = new ContextWindowManager();
// Add various context items
await contextManager.addContext(
'project-structure',
'Project uses React 18, TypeScript 5, and MobX for state management...',
8
);
await contextManager.addContext(
'api-schema',
'REST API endpoints: GET /users, POST /users, ...',
7
);
// Optimize context for new query
const optimizedPrompt = await contextManager.optimizeContext(
'Implement user authentication',
['project-structure'] // Required context
);Intelligent Retry Strategies
Adaptive Retry System
interface RetryStrategy {
shouldRetry(error: Error, attempt: number): boolean;
getDelay(error: Error, attempt: number): number;
modifyRequest?(request: any, error: Error): any;
}
class AdaptiveRetrySystem {
private strategies = new Map<string, RetryStrategy>();
private errorHistory: Array<{
error: Error;
timestamp: Date;
attempt: number;
resolved: boolean;
}> = [];
constructor() {
this.registerDefaultStrategies();
}
private registerDefaultStrategies() {
// Rate limit strategy
this.strategies.set('RateLimitError', {
shouldRetry: (error, attempt) => attempt < 3,
getDelay: (error: any) => {
const retryAfter = error.headers?.['retry-after'];
return retryAfter ? parseInt(retryAfter) * 1000 : 60000;
}
});
// Timeout strategy
this.strategies.set('TimeoutError', {
shouldRetry: (error, attempt) => attempt < 2,
getDelay: (error, attempt) => Math.pow(2, attempt) * 1000,
modifyRequest: (request) => ({
...request,
options: {
...request.options,
maxTurns: Math.max(1, (request.options?.maxTurns || 3) - 1)
}
})
});
// Network error strategy
this.strategies.set('NetworkError', {
shouldRetry: (error, attempt) => {
// Check error patterns
const pattern = this.analyzeErrorPattern();
// Don't retry if seeing consistent network errors
if (pattern.consistentFailures > 5) return false;
return attempt < 4;
},
getDelay: (error, attempt) => {
// Exponential backoff with jitter
const baseDelay = Math.pow(2, attempt) * 1000;
const jitter = Math.random() * 1000;
return baseDelay + jitter;
}
});
}
private analyzeErrorPattern(): {
consistentFailures: number;
errorRate: number;
} {
const recentErrors = this.errorHistory
.filter(e => e.timestamp > new Date(Date.now() - 300000)); // Last 5 minutes
const failures = recentErrors.filter(e => !e.resolved).length;
const errorRate = recentErrors.length > 0 ? failures / recentErrors.length : 0;
return {
consistentFailures: failures,
errorRate
};
}
async executeWithRetry<T>(
operation: () => Promise<T>,
context?: any
): Promise<T> {
let attempt = 0;
let lastError: Error | null = null;
while (attempt < 5) {
try {
const result = await operation();
// Mark success in history
if (lastError) {
const errorEntry = this.errorHistory.find(
e => e.error === lastError && !e.resolved
);
if (errorEntry) {
errorEntry.resolved = true;
}
}
return result;
} catch (error) {
attempt++;
lastError = error as Error;
// Record error
this.errorHistory.push({
error: lastError,
timestamp: new Date(),
attempt,
resolved: false
});
// Get strategy
const strategy = this.getStrategy(lastError);
if (!strategy || !strategy.shouldRetry(lastError, attempt)) {
throw lastError;
}
// Wait before retry
const delay = strategy.getDelay(lastError, attempt);
console.log(`Retrying after ${delay}ms (attempt ${attempt})`);
await this.sleep(delay);
// Modify request if needed
if (strategy.modifyRequest && context) {
context = strategy.modifyRequest(context, lastError);
}
}
}
throw lastError || new Error('Max retry attempts exceeded');
}
private getStrategy(error: Error): RetryStrategy | undefined {
// Try exact match first
const strategy = this.strategies.get(error.constructor.name);
if (strategy) return strategy;
// Try pattern matching
if (error.message.includes('timeout')) {
return this.strategies.get('TimeoutError');
}
if (error.message.includes('network')) {
return this.strategies.get('NetworkError');
}
return undefined;
}
private sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
getRetryStats() {
const total = this.errorHistory.length;
const resolved = this.errorHistory.filter(e => e.resolved).length;
const byType = this.errorHistory.reduce((acc, e) => {
const type = e.error.constructor.name;
acc[type] = (acc[type] || 0) + 1;
return acc;
}, {} as Record<string, number>);
return {
totalErrors: total,
resolvedErrors: resolved,
resolutionRate: total > 0 ? resolved / total : 0,
errorsByType: byType
};
}
}Real-time Collaboration System
Collaborative Coding Session
interface CollaborationSession {
id: string;
participants: string[];
sharedContext: Map<string, any>;
messageHistory: Array<{
participant: string;
message: SDKMessage;
timestamp: Date;
}>;
}
class CollaborativeCodingSystem {
private sessions = new Map<string, CollaborationSession>();
private userQueues = new Map<string, SDKMessage[]>();
createSession(participants: string[]): string {
const sessionId = crypto.randomUUID();
this.sessions.set(sessionId, {
id: sessionId,
participants,
sharedContext: new Map(),
messageHistory: []
});
return sessionId;
}
async addParticipantQuery(
sessionId: string,
participantId: string,
prompt: string
): Promise<void> {
const session = this.sessions.get(sessionId);
if (!session) throw new Error('Session not found');
// Build context-aware prompt
const contextPrompt = this.buildContextualPrompt(session, participantId, prompt);
// Execute query
const messages: SDKMessage[] = [];
for await (const message of query({
prompt: contextPrompt,
abortController: new AbortController(),
options: {
systemPrompt: this.getCollaborativeSystemPrompt(session)
}
})) {
messages.push(message);
// Broadcast to other participants
this.broadcastUpdate(sessionId, participantId, message);
}
// Update session history
messages.forEach(msg => {
session.messageHistory.push({
participant: participantId,
message: msg,
timestamp: new Date()
});
});
}
private buildContextualPrompt(
session: CollaborationSession,
participantId: string,
prompt: string
): string {
// Get recent relevant history
const recentHistory = session.messageHistory
.filter(h => h.message.type === 'assistant')
.slice(-5)
.map(h => `${h.participant}: ${h.message.data.message.content}`)
.join('\n\n');
// Get shared context
const sharedContext = Array.from(session.sharedContext.entries())
.map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
.join('\n');
return `
## Collaboration Context
Participants: ${session.participants.join(', ')}
Current participant: ${participantId}
## Shared Context
${sharedContext}
## Recent Discussion
${recentHistory}
## Current Request
${prompt}
Please provide a response that builds upon the collaborative discussion.
`;
}
private getCollaborativeSystemPrompt(session: CollaborationSession): string {
return `You are assisting a collaborative coding session with ${session.participants.length} participants.
Maintain consistency with previous discussions and help the team work together effectively.
Reference previous participants' contributions when relevant.`;
}
private broadcastUpdate(
sessionId: string,
senderId: string,
message: SDKMessage
) {
const session = this.sessions.get(sessionId);
if (!session) return;
// Queue message for other participants
session.participants
.filter(p => p !== senderId)
.forEach(participant => {
const queue = this.userQueues.get(participant) || [];
queue.push(message);
this.userQueues.set(participant, queue);
});
}
async *subscribeToSession(
sessionId: string,
participantId: string
): AsyncGenerator<SDKMessage> {
const session = this.sessions.get(sessionId);
if (!session || !session.participants.includes(participantId)) {
throw new Error('Invalid session or participant');
}
// Yield existing history first
for (const { message } of session.messageHistory) {
yield message;
}
// Then yield new messages as they arrive
while (true) {
const queue = this.userQueues.get(participantId) || [];
if (queue.length > 0) {
const message = queue.shift()!;
yield message;
} else {
// Wait for new messages
await new Promise(resolve => setTimeout(resolve, 100));
}
}
}
updateSharedContext(
sessionId: string,
key: string,
value: any
) {
const session = this.sessions.get(sessionId);
if (session) {
session.sharedContext.set(key, value);
}
}
}
// Usage
const collabSystem = new CollaborativeCodingSystem();
// Create a session
const sessionId = collabSystem.createSession(['alice', 'bob', 'charlie']);
// Alice starts the discussion
await collabSystem.addParticipantQuery(
sessionId,
'alice',
'Let\'s design a user authentication system'
);
// Bob subscribes and responds
const bobSubscription = collabSystem.subscribeToSession(sessionId, 'bob');
for await (const message of bobSubscription) {
if (message.type === 'assistant') {
// Bob sees Alice's query results and can respond
await collabSystem.addParticipantQuery(
sessionId,
'bob',
'I suggest we use JWT tokens for stateless auth'
);
break;
}
}Next Steps
- Practice these patterns with Workshop Exercises
- Review Best Practices for production implementation
- Explore Practical Examples for real-world usage
Related Pattern Libraries
Discover more advanced patterns in our pattern library:
- TypeScript Streaming Patterns - Real-time data handling
- Multi-Agent Collaboration - Advanced orchestration
- Context Management - Large codebase patterns
- Performance Patterns - Optimization techniques
- Browse All Patterns - Complete pattern collection
Tags: claude-code typescript advanced patterns multi-agent collaboration