Skip to main content

Architecture Overview

The agent uses a multi-step tool pipeline:
  1. classify_intent → Determines if this is a new question or follow-up
  2. text_to_sql → Generates SQL from natural language + schema
  3. run_sql → Executes SQL against your database
  4. analyse_data → Analyzes the data slice and extracts insights
  5. create_chart → Generates chart configurations
  6. summarizer → Creates final user-facing response

Key Technical Details

  • Data handling: Only analyse_data receives actual data rows. text_to_sql and create_chart work with schema and context only.
  • Golden Assets: Retrieved via RAG at runtime to provide few-shot examples for each tool
  • Session memory: Maintains conversation context using thread IDs
  • Streaming: All operations stream events in real-time

Integration Options

Option 1: Full Upsolve Application

Complete UI for data catalog, chat, Golden Assets, and evaluations.

Option 2: Embedded React Widget

Drop-in components for your application with full customization support.

Basic Usage

import { UpsolveChat } from "@upsolve/components";

<UpsolveChat
  tenantJWT={tenantJWT}
  agentId={agentId} // Optional: defaults to first available agent
/>;

Component Props

Required Props
  • tenantJWT (string): Authentication token for API requests. Generate this token using your tenant credentials.
Optional Props
  • agentId (string): Specify which agent configuration to use. If omitted, the component automatically uses the first agent available in your organization.
  • prompt (string): Initial message to send when the chat loads. Use this to start a conversation automatically.
    <UpsolveChat tenantJWT={token} prompt="Show me revenue trends for Q4" />
    
  • apiHostOverride (string): Override the API endpoint. Default: https://api.upsolve.ai
    <UpsolveChat
      tenantJWT={token}
      apiHostOverride="https://custom-api.yourcompany.com"
    />
    
  • useLocalApi (boolean): Enable local development mode. Default: false

Customization Options

Theme Customization Control the visual appearance to match your application:
<UpsolveChat
  tenantJWT={token}
  resolvedTheme="dark" // "light" or "dark"
/>
Welcome Screen Customize the initial welcome screen shown before messages:
// Default welcome screen
<UpsolveChat tenantJWT={token} />
#1 Example of welcome screen component
// Custom text
<UpsolveChat
  tenantJWT={token}
  welcomeScreenContent="How can I help you today?"
/>
#2 Example of welcome screen component
// Custom JSX component
<UpsolveChat
  tenantJWT={token}
  welcomeScreenContent={
    <div>
      <h2 className="text-purple">How can I help you today?</h2>
      <p>
        Ask me anything about your data. I can generate SQL queries, analyze
        results, and create visualizations.
      </p>
    </div>
  }
/>
#3 Example of welcome screen component
// Hide welcome screen entirely
<UpsolveChat tenantJWT={token} welcomeScreenContent={null} />
#4 Example of welcome screen component

Placeholder Text Override default placeholder text throughout the interface:
<UpsolveChat
  tenantJWT={token}
  placeholderOverrides={{
    inputPlaceholder: "Ask about your data...",
    thinkingPlaceholder: "Analyzing your request...",
    sqlGenerationPlaceholder: "Writing SQL query...",
    chartGenerationPlaceholder: "Creating visualization...",
  }}
/>
#1 Example of placeholder override
#2 Example of placeholder override
#3 Example of placeholder override

Option 3: Headless API Integration

Server-Sent Events (SSE) stream for real-time tool execution:
const eventSource = new EventSource("/api/chat", {
  headers: { Authorization: `Bearer ${token}` },
});

eventSource.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log(`Event: ${data.type}`, data);
};
Event Types:
{
  "type": "sql_generated",
  "data": {
    "sql": "SELECT revenue FROM sales WHERE date > '2024-01-01' LIMIT 100"
  }
}
{
  "type": "sql_executed",
  "data": { "message": "Query executed successfully", "rows": 42 }
}
{
  "type": "analysis_complete",
  "data": {
    "key_takeaways": ["Revenue increased 15% YoY"],
    "insights": "Strong growth in Q4"
  }
}
{
  "type": "chart_generated",
  "data": {
    "config": { "type": "line", "x": "date", "y": "revenue" },
    "sql": "SELECT..."
  }
}
{
  "type": "response",
  "data": {
    "content": "Revenue trends show strong Q4 performance with 15% year-over-year growth."
  }
}

Option 4: Embedded iframe

Embed the chat interface in any web application using an iframe. This approach provides complete isolation and is ideal for embedding in third-party applications or when you need strict security boundaries.

Basic Usage

<iframe
  src="https://hub.upsolve.ai/share/chat/YOUR_AGENT_ID?jwt=YOUR_JWT_TOKEN"
  width="100%"
  height="600px"
  frameborder="0"
/>

URL Parameters

Required Parameters
  • jwt (string): Authentication token for API requests. Generate this token using your tenant credentials. The token must be valid and not expired.
  • agentId (path parameter): The ID of the agent configuration to use. This is specified in the URL path: /share/chat/[agentId]
Optional Parameters
  • prompt (string): Initial message to send when the chat loads. Use this to start a conversation automatically.
    const agentId = "YOUR_AGENT_ID";
    const jwt = "YOUR_JWT_TOKEN";
    const prompt = "Show me revenue trends for Q4";
    
    const url = `https://hub.upsolve.ai/share/chat/${agentId}?jwt=${jwt}&prompt=${encodeURIComponent(
      prompt
    )}`;
    
    <iframe src={url} width="100%" height="600px" />;
    
  • theme (string): Control the visual appearance. Valid values: "light" or "dark". Default: follows system preference.
    const agentId = "YOUR_AGENT_ID";
    const jwt = "YOUR_JWT_TOKEN";
    const theme = "dark";
    
    const url = `https://hub.upsolve.ai/share/chat/${agentId}?jwt=${jwt}&theme=${theme}`;
    
    <iframe src={url} width="100%" height="600px" />;
    
  • isAdmin (string): Enable admin mode to show all tool details. Set to "true" to enable, "false" or omit to disable. Default: "false"
    const agentId = "YOUR_AGENT_ID";
    const jwt = "YOUR_JWT_TOKEN";
    const isAdmin = "true";
    
    const url = `https://hub.upsolve.ai/share/chat/${agentId}?jwt=${jwt}&isAdmin=${isAdmin}`;
    
    <iframe src={url} width="100%" height="600px" />;
    
  • placeholderOverrides (string): JSON-encoded object to override default placeholder text throughout the interface. Must be URL-encoded.
    const agentId = "YOUR_AGENT_ID";
    const jwt = "YOUR_JWT_TOKEN";
    const placeholderOverrides = {
      inputPlaceholder: "Ask about your data...",
      thinkingPlaceholder: "Analyzing...",
    };
    
    const url = `https://hub.upsolve.ai/share/chat/${agentId}?jwt=${jwt}&placeholderOverrides=${encodeURIComponent(
      JSON.stringify(placeholderOverrides)
    )}`;
    
    <iframe src={url} width="100%" height="600px" />;
    
    The placeholderOverrides object supports the following properties:
    • userName (string, optional): Override the user name displayed in messages
    • assistantName (string, optional): Override the assistant name displayed in messages
    • inputPlaceholder (string, optional): Override the input field placeholder text
    • thinkingPlaceholder (string, optional): Override the thinking/loading placeholder text
  • organizationId (string): Organization ID for conditional host logic. Used for multi-tenant deployments.

Complete Example

<!DOCTYPE html>
<html>
  <head>
    <title>Upsolve Chat Integration</title>
  </head>
  <body>
    <h1>Data Analytics Chat</h1>

    <iframe
      id="upsolve-chat"
      width="100%"
      height="800px"
      frameborder="0"
      style="border: 1px solid #e0e0e0; border-radius: 8px;"
    />

    <script>
      const agentId = "YOUR_AGENT_ID";
      const jwt = "YOUR_JWT_TOKEN";
      const prompt = "Show me revenue trends";
      const theme = "dark";
      const isAdmin = "false";

      const params = new URLSearchParams({
        jwt,
        prompt,
        theme,
        isAdmin,
      });

      const iframeUrl = `https://hub.upsolve.ai/share/chat/${agentId}?${params.toString()}`;
      document.getElementById("upsolve-chat").src = iframeUrl;
    </script>
  </body>
</html>

React/Next.js Example

import { useMemo } from "react";

function ChatEmbed({ agentId, jwt, prompt, theme = "light" }) {
  const iframeUrl = useMemo(() => {
    const params = new URLSearchParams({
      jwt,
      ...(prompt && { prompt }),
      ...(theme && { theme }),
    });
    return `https://hub.upsolve.ai/share/chat/${agentId}?${params.toString()}`;
  }, [agentId, jwt, prompt, theme]);

  return (
    <iframe
      src={iframeUrl}
      width="100%"
      height="800px"
      frameBorder="0"
      style={{ border: "1px solid #e0e0e0", borderRadius: "8px" }}
    />
  );
}

Security Considerations

  • JWT Expiration: The iframe automatically validates JWT tokens and displays an error message if the token is expired or malformed.
  • Token Security: Never expose JWT tokens in client-side code that could be accessed by unauthorized users. Consider generating short-lived tokens for iframe embeds.
  • CSP Headers: If your application uses Content Security Policy (CSP), ensure the iframe source domain is allowed:
    Content-Security-Policy: frame-src https://hub.upsolve.ai;
    

Error Handling

The iframe component automatically handles the following error scenarios:
  • Invalid or expired JWT: Displays a user-friendly error message
  • Missing agent connection: Shows a loading state while fetching connection details
  • Invalid parameters: Silently ignores invalid query parameters and uses defaults

Data Catalog Configuration

Table Selection

Define which tables the agent can access:
{
  "tables": ["users", "orders", "products"],
  "restricted_tables": ["internal_logs", "sensitive_data"]
}

Selectable Columns

Mark columns for precise filtering. The system pre-scans these for distinct values:
{
  "selectable_columns": {
    "users.region": true,
    "products.category": true,
    "users.user_id": false // Skip high-variance columns
  }
}
Performance guidance: Avoid selecting:
  • High-cardinality columns (IDs, timestamps)
  • Numeric columns with many unique values
  • Free-text fields

Golden Assets Management

Golden Assets provide few-shot examples that improve consistency. They map questions to expected outputs:

Creating Golden Assets

Save directly from chat interactions or use the API:
POST /api/golden-assets
{
  "question": "What are our top products by revenue?",
  "sql": "SELECT product_name, SUM(revenue) FROM sales GROUP BY product_name ORDER BY 2 DESC LIMIT 10",
  "analysis": "iPhone leads with $2.1M, followed by MacBook at $1.8M",
  "chart_config": {"type": "bar", "x": "product_name", "y": "revenue"}
}
Golden Assets management interface

How Golden Assets Work

At runtime, the agent:
  1. Retrieves similar Golden Assets using vector search
  2. Includes them as few-shot examples in tool prompts
  3. Generates more consistent outputs for similar questions

Evaluations

Test the agent against ground truth before deployment:

Creating Test Sets

POST /api/test-sets
{
  "name": "Q4 Sales Analysis",
  "test_cases": [
    {
      "question": "What were total sales in Q4?",
      "expected_sql": "SELECT SUM(amount) FROM sales WHERE quarter = 4",
      "expected_insight": "Q4 sales totaled $5.2M"
    }
  ]
}

Running Evaluations

The system automatically:
  1. Runs each test case through the full agent pipeline
  2. Compares outputs against expected results
  3. Generates similarity scores and detailed reports
Evaluation results dashboard with pass/fail indicators

Security & Privacy

Data Access Controls

  • Table-level: Restrict which tables the agent can query
  • Column-level: Exclude sensitive columns from schema and analysis
  • Row-level: Apply WHERE clause filters to limit data access

Data Handling

  • At rest: Golden Assets stored with logical tenant separation
  • In transit: All API calls require authenticated JWT tokens
  • In processing: Only analyse_data tool receives actual data rows
// Example: Exclude sensitive columns
{
  "excluded_columns": ["ssn", "credit_card", "password_hash"],
  "restricted_queries": ["DROP", "DELETE", "UPDATE"]
}

Performance Optimization

Query Limits

All generated SQL automatically includes LIMIT clauses to prevent large data transfers:
-- Generated SQL includes automatic limits
SELECT * FROM large_table
WHERE created_date > '2024-01-01'
LIMIT 100  -- Added automatically

Caching Strategy

  • Query results: Cached per session to avoid re-running identical SQL
  • Golden Assets: Retrieved and cached for the conversation duration
  • Schema metadata: Cached and refreshed periodically

Monitoring

Track key metrics:
  • SQL execution time
  • Token usage per conversation
  • Golden Asset retrieval latency
  • User satisfaction scores

Troubleshooting

Common Issues

SQL Generation Fails
  • Check table/column names in schema
  • Verify Golden Assets have correct SQL examples
  • Review any custom prompts for the text_to_sql tool
Charts Don’t Render
  • Ensure data has appropriate columns for visualization
  • Check chart configuration format
  • Verify previous chart context if this is a follow-up
Poor Accuracy
  • Add more Golden Assets for common question patterns
  • Run evaluations to identify specific failure modes
  • Refine selectable columns to include relevant filter options

API Reference Summary

Core Endpoints:
  • POST /api/chat - Start conversational session (SSE)
  • GET /api/agents - List available agents
  • POST /api/golden-assets - Create/manage Golden Assets
  • POST /api/evaluations/run - Execute evaluation suite
Authentication: All endpoints require Bearer token in Authorization header.