Skip to main content
The Guides System provides a composable hook architecture that integrates directly into the SammyAgentProvider for seamless walkthrough experiences.
Performance Update: Guides now use lazy loading to reduce API calls. User guides are only fetched when components call refreshUserGuides(), not automatically on initialization. This prevents unnecessary API load from users who never interact with guides. Always call refreshUserGuides() in components that display guides.

Architecture Overview

Clean Architecture

The guides system uses a hook-based composition pattern that integrates directly into the main provider:
  • No nested contexts - Integrated directly into main provider
  • Hook composition - Clean separation of concerns
  • Zero overhead - Returns null when disabled
  • Type-safe - Full TypeScript support

Data Flow

Quick Start

Basic Setup

import { SammyAgentProvider } from '@sammy-labs/sammy-three';

function App() {
  return (
    <SammyAgentProvider
      config={{
        auth: authConfig,
        captureMethod: 'render',
        debugLogs: true,
        model: 'models/gemini-2.5-flash-preview-native-audio-dialog',
      }}
      guides={true} // Enable guides functionality
      autoStartFromURL={true} // Auto-start from ?walkthrough= URLs
      onError={(error) => console.error('Agent error:', error)}
      onTokenExpired={handleTokenExpired}
      onWalkthroughStart={(guideId) => {
        console.log('Starting walkthrough:', guideId);
      }}
    >
      <YourApp />
    </SammyAgentProvider>
  );
}

URL-Based Activation

Guides can be automatically triggered via URL parameters, perfect for sharing specific walkthroughs or onboarding flows:
# Trigger a guide directly from URL
https://yourapp.com?walkthrough=onboarding-guide-v1

# Custom parameter name
https://yourapp.com?guide=quick-tour
When autoStartFromURL is enabled, the guide will automatically start when the page loads with the appropriate query parameter.

Guide Lifecycle

Manage the complete lifecycle of guides from initialization to completion:

Initialization

// Guides automatically initialize when provider mounts
// Fetches user guides and checks for URL parameters

Manual Start

// Start a guide programmatically
const success = await guides.startWalkthrough('guide-id');
if (success) {
  console.log('Guide started successfully');
}

URL Detection

// Check for guide in URL
const hasGuide = await guides.checkForGuideInUrl();
if (hasGuide) {
  console.log('Guide found in URL and started');
}

Progress Tracking

// Guides are automatically marked as completed when conversation starts
// Manual completion is also possible
guides.markGuideAsCompleted('guide-id');

Data Refresh

// Refresh guide data at any time
guides.refreshGuide();        // Current guide
guides.refreshUserGuides();   // All user guides

Cleanup

// Clean up URL params after use
guides.cleanupUrlParams();

Core Components

GuidesService

The service layer handles all API communication and transforms snake_case responses to camelCase.
  • Interface
  • Implementation
export interface GuidesService {
  fetchGuide: (guideId: string) => Promise<SammyGuide | null>;
  getUserGuides: () => Promise<SammyGuide[]>;
}

export interface SammyGuide {
  guideId: string;
  title: string;
  prompt: string;
  organisationId: string;
  isCompleted: boolean;
}

useGuides Hook

Provides always-on guide data with automatic fetching:
interface UseGuidesReturn {
  // Data
  currentGuide: SammyGuide | null;
  userGuides: SammyGuide[];
  
  // Loading states
  isLoadingGuide: boolean;
  isLoadingUserGuides: boolean;
  
  // Error states
  guideError: Error | null;
  userGuidesError: Error | null;
  
  // Actions
  refreshGuide: () => void;
  refreshUserGuides: () => void;
  markGuideAsCompleted: (guideId: string) => void;
}

Features

URL-Based Walkthrough Activation

1

User Visits URL

User visits: https://app.com?walkthrough=guide-123
2

Parameter Detection

GuidesProvider detects the parameter
3

Guide Fetching

Guide is fetched automatically
4

Auto-Start

If autoStartFromURL=true, agent starts with guide context
5

URL Cleanup

URL parameter is cleaned up
6

Completion Tracking

Guide marked as completed on conversation start

Guide Discovery & Listing

const { guides } = useSammyAgentContext();

// List all guides with completion status
guides?.userGuides.map(guide => ({
  id: guide.guideId,
  title: guide.title,
  completed: guide.isCompleted
}));

Manual Walkthrough Triggering

guides?.startWalkthrough('guide-123');
// This will:
// 1. Call onWalkthroughStart callback
// 2. Start agent with guide context
// 3. Mark guide as completed

Progress Tracking

Automatic Completion

Guides automatically track completion:
  • Marked complete when conversation starts with guide
  • Optimistic UI updates (immediate visual feedback)
  • Persistent across sessions (backend storage)

Query Parameter Detection

Configuration Options

  • Basic Setup
  • Configuration Table
<SammyAgentProvider
  config={authConfig}
  guides={true}                    // Enable guides
  autoStartFromURL={true}          // Auto-start from URL
  guidesQueryParam="walkthrough"   // Query param name (default)
  guidesDebug={true}               // Enable debug logging
>
  <YourApp />
</SammyAgentProvider>

Usage Examples

Share Walkthrough

function ShareWalkthroughButton({ guideId }) {
  const shareUrl = 
    `${window.location.origin}?walkthrough=${guideId}`;
  
  return (
    <button onClick={() => 
      navigator.clipboard.writeText(shareUrl)
    }>
      Copy Walkthrough Link
    </button>
  );
}

Email Campaign

<a href="https://app.com?walkthrough=new-user-onboarding">
  Start Your Guided Tour
</a>

Programmatic Navigation

function navigateWithWalkthrough(guideId: string) {
  window.location.href = 
    `/dashboard?walkthrough=${guideId}`;
}

Manual URL Check

const { guides } = useSammyAgentContext();

const handleCheckUrl = async () => {
  if (guides) {
    const found = await guides.checkForGuideInUrl();
    if (found) {
      console.log('Guide found and started!');
    }
  }
};

Advanced Features

  • Custom Query Parameter Names
  • Conditional Auto-Start
  • Debug Mode
<SammyAgentProvider
  guides={true}
  guidesQueryParam="tutorial"  // Now use ?tutorial=guide-id
>

Implementation Details

Conditional Provider Wrapping

The system uses a clever pattern to conditionally wrap providers without nesting:
// When guides={true}, wrap with GuidesProvider
if (guides) {
  return (
    <GuidesProvider>
      <InternalProvider>
        {children}
      </InternalProvider>
    </GuidesProvider>
  );
}

// When guides={false}, skip the wrapper
return <InternalProvider>{children}</InternalProvider>;

Dependency Injection for Agent Start

// Extract startAgent function from inner context
const StartAgentExtractor = ({ onStartAgentReady }) => {
  const context = useContext(SammyAgentContext);
  
  useEffect(() => {
    if (context?.startAgent) {
      onStartAgentReady(context.startAgent);
    }
  }, [context?.startAgent, onStartAgentReady]);
  
  return null;
};

Optimistic Updates

Immediate UI Feedback

Guide completion is updated optimistically for better UX:
const markGuideAsCompleted = useCallback((guideId: string) => {
  // Update current guide immediately
  if (currentGuide?.guideId === guideId) {
    setCurrentGuide(prev => 
      prev ? { ...prev, isCompleted: true } : null
    );
  }
  
  // Update user guides list immediately
  setUserGuides(prev => 
    prev.map(guide => 
      guide.guideId === guideId 
        ? { ...guide, isCompleted: true }
        : guide
    )
  );
}, [currentGuide]);

API Reference

Provider Props

interface SammyAgentProviderProps {
  guides?: boolean;           // Enable guides functionality
  autoStartFromURL?: boolean; // Auto-start from URL params
  onWalkthroughStart?: (guideId: string) => void;
  // ... other props
}

Context API

const { guides } = useSammyAgentContext();

if (guides) {
  // All guides functionality available
  guides.currentGuide;        // Current active guide
  guides.userGuides;          // All user's guides
  guides.isLoadingGuide;      // Loading state
  guides.guideError;          // Error state
  guides.refreshGuide();      // Refresh current
  guides.refreshUserGuides(); // Refresh list
  guides.markGuideAsCompleted(id); // Mark complete
  guides.startWalkthrough(id); // Start walkthrough
}

Service Endpoints

GET /api/v1/sammy-three/guides/{id}

Complete Example

  • Provider Setup
  • Dashboard Component
import { SammyAgentProvider, useSammyAgentContext } from '@sammy-three/react';

function App() {
  return (
    <SammyAgentProvider
      config={{
        auth: { token: 'xxx', baseUrl: 'https://api.sammy.ai' },
        model: 'gemini-2.0-flash-exp',
      }}
      guides={true}
      autoStartFromURL={true}
      guidesQueryParam="walkthrough"
      guidesDebug={process.env.NODE_ENV === 'development'}
      onWalkthroughStart={(guideId) => {
        console.log(`Walkthrough started: ${guideId}`);
        // Track analytics event
        analytics.track('walkthrough_started', { guideId });
      }}
    >
      <Dashboard />
    </SammyAgentProvider>
  );
}

Performance & Best Practices

Zero-Cost When Disabled

When guides={false}:
  • No GuidesProvider rendered
  • No API calls made
  • No state management overhead
  • No event listeners attached

Memoization

All expensive operations are memoized:
const sammyApiClient = useMemo(() => 
  authConfig ? new SammyApiClient(authConfig) : null, 
  [authConfig]
);

Automatic Cleanup

Resources are properly cleaned up:
// URL parameter cleaned after detection
window.history.replaceState({}, '', newUrl.toString());

TypeScript Best Practices

Use null checks for type safety:
// Good - null safe
if (guides) {
  guides.userGuides.map(...);
}

// Bad - assumes guides exists
guides!.userGuides.map(...);

Security Considerations

Always validate guide IDs on the backend:
  • Check if guide exists
  • Verify user permissions
  • Validate organization access

URL Parameter Sanitization

The system automatically:
  • Sanitizes guide IDs before use
  • Prevents XSS through parameter injection
  • Cleans up parameters after processing

Troubleshooting

Common Issues

  • Guide Not Starting
  • URL Not Cleaning Up
  • Multiple Triggers
Troubleshooting Steps:
  1. Check if guides={true} is set
  2. Verify autoStartFromURL={true} for automatic start
  3. Ensure guide ID exists and user has access
  4. Enable debug mode to see detailed logs

Summary

The Sammy-Three Guides System provides a robust, performant, and developer-friendly solution for implementing guided experiences. Its clean architecture, type safety, and zero-overhead design make it an excellent choice for applications requiring tutorial or walkthrough functionality.
Key takeaways:
  • Clean Architecture: Separated concerns with proper layering
  • Performance First: Zero cost when disabled
  • Developer Experience: Full TypeScript support and simple API
  • User Experience: Seamless URL-based activation and progress tracking
  • Extensible: Easy to add new features without breaking existing functionality
I