Skip to main content

Context Handoff: Technical Implementation

This guide explores the technical mechanisms behind SuperModel’s context handoff system, showing how context flows seamlessly between different specialized UI apps while maintaining zero server inference.

Overview

Context handoff enables SuperModel apps to build on previous user interactions, creating personalized experiences that span multiple specialized interfaces. The key innovation is that context flows through the client, not the server, maintaining our zero-inference guarantee.

Context Flow Architecture

Context Data Structure

SuperModel uses a standardized context object that grows throughout the user journey:
interface UserContext {
  // Session information
  sessionId: string;
  userId?: string;
  timestamp: number;
  
  // Journey tracking
  journey: {
    currentApp: string;
    previousApps: string[];
    startTime: number;
    interactions: InteractionEvent[];
  };
  
  // User preferences and behavior
  preferences: {
    priorities: string[];
    values: Record<string, boolean>;
    interaction_patterns: string[];
  };
  
  // Domain-specific data
  data: {
    selections: Record<string, any>;
    filters: Record<string, any>;
    budget?: number;
    use_case?: string;
  };
  
  // Next step predictions
  predictions: {
    likely_next_app?: string;
    suggested_actions?: string[];
    confidence_score?: number;
  };
}

Implementation Examples

1. Context Capture in UI Components

Apps capture context through AG-UI events:
function ProductSearchUI({ products, context, onEvent }) {
  const [selectedProducts, setSelectedProducts] = useState([]);
  const [appliedFilters, setAppliedFilters] = useState({});

  const handleProductSelect = (product) => {
    const newSelection = [...selectedProducts, product];
    setSelectedProducts(newSelection);
    
    // Capture context through AG-UI event
    onEvent({
      type: 'CONTEXT_UPDATE',
      payload: {
        context: {
          ...context,
          data: {
            ...context.data,
            selected_products: newSelection,
            selection_criteria: appliedFilters
          },
          preferences: {
            ...context.preferences,
            // Infer preferences from selections
            values_quality: product.rating > 4.5,
            budget_conscious: product.price < context.data.budget * 0.8
          },
          journey: {
            ...context.journey,
            interactions: [
              ...context.journey.interactions,
              {
                type: 'product_selected',
                product_id: product.id,
                timestamp: Date.now(),
                selection_reason: 'user_choice'
              }
            ]
          }
        }
      }
    });
  };

  const handleTransition = (targetApp) => {
    onEvent({
      type: 'INTENT',
      payload: {
        intent: 'transition_to_app',
        target_app: targetApp,
        context: {
          ...context,
          predictions: {
            likely_next_app: targetApp,
            suggested_actions: ['compare_products', 'build_bundle'],
            confidence_score: 0.9
          }
        }
      }
    });
  };

  return (
    <div className="product-search">
      {/* Product grid with context-aware interactions */}
      {products.map(product => (
        <ProductCard 
          key={product.id}
          product={product}
          onSelect={() => handleProductSelect(product)}
          // Highlight based on context
          highlighted={
            context.preferences?.values_quality && product.rating > 4.5
          }
        />
      ))}
      
      {selectedProducts.length > 0 && (
        <div className="transition-actions">
          <button onClick={() => handleTransition('bundle-builder-ui')}>
            Build Complete Setup ({selectedProducts.length} items)
          </button>
        </div>
      )}
    </div>
  );
}

2. Context-Aware UI Generation

Apps use accumulated context to personalize generated interfaces:
Context-Aware Generation Prompt
{
  "method": "sampling/createMessage",
  "params": {
    "messages": [{
      "role": "user",
      "content": {
        "type": "text",
        "text": "Generate a bundle builder UI with the following context:\n\nUser Journey:\n- Started with product search for home office headphones\n- Prioritized comfort and noise canceling\n- Selected premium products (Sony WH-1000XM5)\n- Demonstrated willingness to pay for quality\n- Values thorough research (compared multiple options)\n\nUser Preferences:\n- values_quality: true\n- comfort_focused: true\n- budget_conscious: false\n- thorough_researcher: true\n\nSelected Products:\n- Sony WH-1000XM5 ($299) - chosen for comfort rating\n\nBudget Context:\n- Original budget: $300\n- Spent: $299\n- Willing to exceed for right accessories\n\nGenerate a bundle builder that:\n1. Acknowledges their quality focus ('Perfect for your comfort priority')\n2. Suggests premium accessories that match their demonstrated values\n3. Shows confidence in recommending higher-end options\n4. Provides detailed justifications (appeals to their research style)\n\nUse AG-UI for all interactions."
      }
    }],
    "systemPrompt": "Generate AG-UI component that leverages user context for hyper-personalized experience. Reference their demonstrated preferences and journey."
  }
}

3. Context Enrichment Between Apps

Each app can enrich context for future apps:
// Bundle Builder App enriches context based on user selections
class BundleBuilderTool {
  async execute(request: any, context: UserContext): Promise<UIResource> {
    // Generate personalized UI
    const uiResponse = await this.generateContextualUI(request, context);
    
    // Enrich context based on app-specific insights
    const enrichedContext = {
      ...context,
      preferences: {
        ...context.preferences,
        // Infer new preferences from bundle building behavior
        values_bundles: true,
        ecosystem_thinker: context.data.selected_accessories?.length > 2,
        convenience_focused: context.data.selected_accessories?.includes('wireless-charger')
      },
      data: {
        ...context.data,
        bundle_theme: this.inferBundleTheme(context),
        price_sensitivity: this.analyzePriceSensitivity(context)
      },
      predictions: {
        likely_next_app: 'checkout-ui',
        suggested_actions: ['review_bundle', 'add_warranty', 'apply_discounts'],
        confidence_score: 0.95
      }
    };

    return {
      type: 'resource',
      resource: {
        uri: `ui://bundle-builder/${Date.now()}`,
        mimeType: 'application/vnd.mcp-ui.ag-ui',
        text: uiResponse.content.text
      },
      context: enrichedContext // Pass enriched context back to client
    };
  }

  private inferBundleTheme(context: UserContext): string {
    const { use_case, selected_products, priorities } = context.data;
    
    if (use_case === 'home_office' && priorities?.includes('comfort')) {
      return 'productivity_comfort';
    }
    // ... other theme logic
    return 'general';
  }
}

Context Persistence Strategies

// Store context in browser session
class SessionContextStore {
  save(context: UserContext): void {
    sessionStorage.setItem('supermodel-context', JSON.stringify(context));
  }
  
  load(): UserContext | null {
    const stored = sessionStorage.getItem('supermodel-context');
    return stored ? JSON.parse(stored) : null;
  }
}
// Compress context for efficiency
class ContextCompressor {
  compress(context: UserContext): CompressedContext {
    return {
      essential: {
        preferences: context.preferences,
        key_selections: this.extractKeySelections(context.data),
        journey_stage: this.inferJourneyStage(context.journey)
      },
      metadata: {
        session_id: context.sessionId,
        compression_timestamp: Date.now()
      }
    };
  }
}
// Optional: Persist context across sessions
class PersistentContextStore {
  async saveUserProfile(userId: string, context: UserContext): Promise<void> {
    const profile = {
      preferences: context.preferences,
      interaction_patterns: this.extractPatterns(context.journey),
      value_indicators: this.extractValues(context.data)
    };
    
    // Save to user profile service
    await this.userService.updateProfile(userId, profile);
  }
}

Benefits of Context Handoff

Personalized Experiences

Each app builds on previous interactions, creating increasingly personalized and relevant experiences.

Reduced Cognitive Load

Users don’t need to re-explain preferences or re-select options. Context carries forward automatically.

Intelligent Routing

Routing decisions consider user journey and context, leading to more appropriate app selections.

Zero Server Inference

All context processing happens on the client. Server never interprets or analyzes context data.

Best Practices

1

Design for Context Growth

Structure your context schema to accommodate new data as the user journey progresses.
2

Capture User Intent

Don’t just track what users do - capture why they do it through interaction patterns.
3

Graceful Degradation

Ensure apps work even with minimal or missing context. Context should enhance, not break experiences.
4

Privacy by Design

Keep sensitive data in client-side context only. Server should never store personal preferences.

Next Steps