> ## Documentation Index
> Fetch the complete documentation index at: https://docs.poly.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Tutorial: Variants

> PolyAcademy Level 2 – Use variants to manage site-specific, brand-specific, or channel-specific content.

export const LessonMeta = ({level, difficulty, time}) => {
  const levelConfig = {
    1: {
      badge: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200',
      label: 'Level 1'
    },
    2: {
      badge: 'bg-amber-100 text-amber-800 dark:bg-amber-900 dark:text-amber-200',
      label: 'Level 2'
    },
    3: {
      badge: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200',
      label: 'Level 3'
    }
  };
  const difficultyConfig = {
    Beginner: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200',
    Intermediate: 'bg-amber-100 text-amber-800 dark:bg-amber-900 dark:text-amber-200',
    Advanced: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200'
  };
  const lvl = levelConfig[level] || levelConfig[1];
  const diffColor = difficultyConfig[difficulty] || difficultyConfig['Beginner'];
  return <div className="flex flex-wrap items-center gap-2 my-4 not-prose">
      <span className={`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold ${lvl.badge}`}>
        {lvl.label}
      </span>
      <span className={`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold ${diffColor}`}>
        {difficulty}
      </span>
      {time && <span className="inline-flex items-center gap-1 text-xs text-gray-500 dark:text-gray-400">
          <svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
            <path strokeLinecap="round" strokeLinejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z" />
          </svg>
          {time}
        </span>}
    </div>;
};

export const Quiz = ({questions = []}) => {
  const [selected, setSelected] = useState({});
  const [resetCount, setResetCount] = useState(0);
  const letters = ['A', 'B', 'C', 'D'];
  const handleSelect = (qIdx, optIdx) => {
    if (selected[qIdx] !== undefined) return;
    setSelected(prev => ({
      ...prev,
      [qIdx]: optIdx
    }));
  };
  const handleReset = () => {
    setSelected({});
    setResetCount(c => c + 1);
  };
  if (!questions?.length) return null;
  const getOptionClasses = ({hasAnswered, isThisCorrect, isThisSelected}) => {
    if (!hasAnswered) {
      return {
        btn: 'flex w-full items-center gap-3 py-2.5 px-4 rounded-xl text-sm leading-normal transition-all duration-150 text-left border cursor-pointer border-gray-200 bg-white text-gray-700 hover:border-gray-300 hover:bg-gray-50 hover:shadow-sm dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:border-gray-500 dark:hover:bg-gray-700',
        badge: 'w-6 h-6 rounded-full text-xs font-bold flex items-center justify-center shrink-0 leading-none transition-all duration-150 bg-gray-100 text-gray-500 dark:bg-gray-700 dark:text-gray-300',
        icon: null
      };
    }
    if (isThisCorrect) {
      return {
        btn: 'flex w-full items-center gap-3 py-2.5 px-4 rounded-xl text-sm leading-normal transition-all duration-150 text-left border cursor-default border-green-400 bg-green-50 text-green-900 font-medium dark:border-green-500 dark:bg-green-950 dark:text-green-100',
        badge: 'w-6 h-6 rounded-full text-xs font-bold flex items-center justify-center shrink-0 leading-none transition-all duration-150 bg-green-500 text-white dark:bg-green-500',
        icon: <svg className="shrink-0 w-4 h-4 text-green-500 dark:text-green-400 ml-auto" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2.5}>
            <path strokeLinecap="round" strokeLinejoin="round" d="M4.5 12.75l6 6 9-13.5" />
          </svg>
      };
    }
    if (isThisSelected) {
      return {
        btn: 'flex w-full items-center gap-3 py-2.5 px-4 rounded-xl text-sm leading-normal transition-all duration-150 text-left border cursor-default border-red-400 bg-red-50 text-red-900 dark:border-red-500 dark:bg-red-950 dark:text-red-100',
        badge: 'w-6 h-6 rounded-full text-xs font-bold flex items-center justify-center shrink-0 leading-none transition-all duration-150 bg-red-500 text-white dark:bg-red-500',
        icon: <svg className="shrink-0 w-4 h-4 text-red-400 dark:text-red-400 ml-auto" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2.5}>
            <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
          </svg>
      };
    }
    return {
      btn: 'flex w-full items-center gap-3 py-2.5 px-4 rounded-xl text-sm leading-normal transition-all duration-150 text-left border cursor-default border-gray-100 bg-white text-gray-400 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-500',
      badge: 'w-6 h-6 rounded-full text-xs font-bold flex items-center justify-center shrink-0 leading-none transition-all duration-150 bg-gray-100 text-gray-500 dark:bg-gray-700 dark:text-gray-500',
      icon: null
    };
  };
  return <div key={resetCount} className="my-6">
      {questions.map((q, qIdx) => {
    const answer = selected[qIdx];
    const hasAnswered = answer !== undefined;
    const isCorrect = answer === q.correct;
    return <div key={String(qIdx)} className="mb-8">
            <p className="flex items-start gap-2.5 font-semibold text-sm mb-3 mt-0 leading-relaxed text-gray-900 dark:text-gray-100">
              <span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-gray-800 dark:bg-gray-200 text-white dark:text-gray-900 text-xs font-bold shrink-0 mt-px leading-none">
                {qIdx + 1}
              </span>
              {q.q}
            </p>

            <div className="flex flex-col gap-2">
              {q.options.map((opt, i) => {
      const isThisCorrect = i === q.correct;
      const isThisSelected = i === answer;
      const {btn, badge, icon} = getOptionClasses({
        hasAnswered,
        isThisCorrect,
        isThisSelected
      });
      return <button key={String(i)} type="button" onClick={() => handleSelect(qIdx, i)} className={btn}>
                    <span className={badge}>{letters[i]}</span>
                    <span className="flex-1">{opt}</span>
                    {icon}
                  </button>;
    })}
            </div>

            {hasAnswered ? <div className={`mt-3 py-3 pl-4 pr-3.5 rounded-r-xl text-sm leading-relaxed border-l-4 ${isCorrect ? 'border-green-500 bg-green-50 dark:bg-green-950 dark:border-green-500' : 'border-red-500 bg-red-50 dark:bg-red-950 dark:border-red-500'}`}>
                <span className={`font-semibold ${isCorrect ? '!text-green-800 dark:!text-green-200' : '!text-red-800 dark:!text-red-200'}`}>
                  {isCorrect ? 'Correct.' : 'Not quite.'}
                </span>{' '}
                <span className="!text-gray-700 dark:!text-gray-300">{q.explanation}</span>
              </div> : null}
          </div>;
  })}

      <button type="button" onClick={handleReset} className="mt-1 text-xs text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 underline underline-offset-2 cursor-pointer transition-colors duration-150">
        Reset quiz
      </button>
    </div>;
};

export const ProgressTracker = ({lessonNum, totalLessons, level}) => {
  const [checked, setChecked] = useState(false);
  return <div onClick={() => setChecked(prev => !prev)} className={checked ? 'flex items-center gap-3 p-4 rounded-lg border-2 border-green-600 bg-green-50 dark:bg-green-950 cursor-pointer select-none transition-all' : 'flex items-center gap-3 p-4 rounded-lg border-2 border-gray-200 dark:border-gray-600 bg-gray-50 dark:bg-gray-800 cursor-pointer select-none transition-all'}>
      <div className={checked ? 'w-5 h-5 rounded border-2 border-green-600 bg-green-600 flex items-center justify-center shrink-0 transition-all' : 'w-5 h-5 rounded border-2 border-gray-400 dark:border-gray-500 bg-white dark:bg-gray-800 flex items-center justify-center shrink-0 transition-all'}>
        {checked ? <svg width="10" height="8" viewBox="0 0 10 8" fill="none">
            <path d="M1 4L3.5 6.5L9 1" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
          </svg> : null}
      </div>
      <div>
        <div className={checked ? 'font-semibold text-sm text-green-700 dark:text-green-300' : 'font-semibold text-sm text-gray-700 dark:text-gray-200'}>
          {checked ? 'Lesson complete' : 'Mark lesson complete'}
        </div>
        {lessonNum && totalLessons ? <div className="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
            {level ? level + ' - ' : ''}Lesson {lessonNum} of {totalLessons}
          </div> : null}
      </div>
    </div>;
};

**Level 2 – Lesson 7 of 8** – Tailor agent responses for different contexts without creating separate projects.

<LessonMeta level={2} difficulty="Intermediate" time="15 min" />

[Variants](/knowledge/variants/introduction) let you maintain **one agent** while tailoring responses for different contexts – no separate projects needed. A variant is a **named configuration profile** that changes selected content or settings depending on where or how the agent is used.

## Common use cases

<CardGroup cols={2}>
  <Card title="Site/location" icon="location-dot">
    Different branches, properties, campuses, stores
  </Card>

  <Card title="Brand" icon="trademark">
    Same company, different sub-brands with different tone or policies
  </Card>

  <Card title="Region" icon="globe">
    Differences in hours, terminology, supported services, legal language
  </Card>

  <Card title="Channel" icon="comments">
    Chat vs Call wording; short vs spoken-friendly phrasing
  </Card>

  <Card title="Audience segment" icon="users">
    B2B vs B2C, member vs non-member
  </Card>
</CardGroup>

## What variants are (and aren't)

<Tabs>
  <Tab title="What variants ARE">
    <AccordionGroup>
      <Accordion title="Configuration profiles" icon="sliders">
        A **set of values** attached to a variant name (for example: `site_name = "Example site"`), used to customize how the agent responds in that context.
      </Accordion>

      <Accordion title="Consistency tool" icon="link">
        A way to keep **shared logic and behavior consistent**, while allowing specific fields to differ.
      </Accordion>

      <Accordion title="Analysis dimension" icon="chart-line">
        Visible during analysis: variants appear in Conversation review/diagnosis, showing which context handled each turn.
      </Accordion>
    </AccordionGroup>
  </Tab>

  <Tab title="What variants are NOT">
    <Warning>
      * **Not separate agents** - They share the same core configuration
      * **Not environments** - Sandbox/Pre-release/Live are about safe promotion; variants are about contextual behavior
      * **Not a retrieval fix** - Variants should refine, not rescue, retrieval
    </Warning>
  </Tab>
</Tabs>

## How the Variant UI works

<AccordionGroup>
  <Accordion title="Empty state" icon="square-dashed">
    When no variants exist, you'll see a primary **Add Variant** button.
  </Accordion>

  <Accordion title="Table/grid view" icon="table">
    When variants exist:

    * Each row is a variant (for example, `Site 1 (default)`)
    * Columns represent variant fields/attributes (for example, `site_name`, plus other fields your org has defined)
    * A search bar for finding variants quickly
  </Accordion>

  <Accordion title="Edit variant panel" icon="pen-to-square">
    Often a right-side drawer containing:

    * **Variant name (required)**: the label you will recognize in testing and reporting
    * **Default variant** toggle: marks which variant is used when no other variant is selected
    * Editable fields such as `site_name`, and any other attributes your configuration supports
  </Accordion>

  <Accordion title="Import / Export controls" icon="file-import">
    Useful for bulk setup (many sites/locations) and sharing configurations across environments or projects.
  </Accordion>
</AccordionGroup>

## When to use variants

<CardGroup cols={2}>
  <Card title="Use variants when" icon="circle-check">
    * You have **repeatable structure** but different values
    * You want to avoid copying the same Managed Topic content across multiple projects
    * You need to test and report on performance by context
  </Card>

  <Card title="Avoid variants when" icon="circle-xmark">
    * The differences are **so large** that you effectively have a different agent
    * You are trying to solve a retrieval problem that should be fixed by better topic names
  </Card>
</CardGroup>

## Check your understanding

<Quiz
  questions={[
{
q: "You have 20 hotel properties and each has different check-in times, addresses, and front desk numbers. You're considering creating 20 separate agent projects. What's a better approach?",
options: [
  "Create 20 projects – one per property",
  "Use variants to store property-specific values in a single agent",
  "Use Response Controls to switch between properties",
  "Create environment-specific configurations for each property",
],
correct: 1,
explanation: "Variants let you maintain one agent while tailoring responses for different contexts. Creating 20 separate projects would mean duplicating all shared logic and making maintenance much harder.",
}
]}
/>

## Planning your variant strategy

Before creating anything, define one sentence your team agrees on:

**"A variant represents \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_."**

**Examples:**

* "A variant represents a single hotel property."
* "A variant represents a specific store location."
* "A variant represents a brand under a multi-brand umbrella."

This prevents "variant sprawl," where variants become an unstructured dumping ground.

## Create your first variant

<Steps>
  <Step title="Open Variants">
    Navigate to **Knowledge > Variants** in the platform.
  </Step>

  <Step title="Click Add Variant">
    Start the variant creation process.
  </Step>

  <Step title="Configure variant settings">
    Set:

    * **Variant name**: use a naming convention that scales
    * **Default variant**: set one default so testing and Live always have a predictable fallback
    * **Key fields**: start with 1–3 fields that clearly affect behavior
  </Step>
</Steps>

### Naming conventions that scale

<Tabs>
  <Tab title="Stable and sortable">
    `site_001_downtown`

    Good for large deployments with many locations
  </Tab>

  <Tab title="Human-friendly">
    `kansas_city`

    Consistent with your existing naming conventions
  </Tab>

  <Tab title="Multi-dimensional">
    `brand_a_us`

    If your dimension is brand + region
  </Tab>
</Tabs>

## What to put into variants

Variants are most useful for content that is:

* Frequently repeated in calls/chats
* Specific to context
* Risky if wrong

<Tabs>
  <Tab title="Good variant fields">
    <AccordionGroup>
      <Accordion title="Location identifiers" icon="location-dot">
        `site_name`, `city`, `region`
      </Accordion>

      <Accordion title="Customer-facing facts" icon="info-circle">
        `hours`, `address`, `parking_info`, `accessibility_info`
      </Accordion>

      <Accordion title="Escalation language" icon="phone-arrow-up-right">
        "connect you to the front desk" vs "connect you to an agent"
      </Accordion>

      <Accordion title="Channel-specific phrasing" icon="comments">
        Short, spoken-friendly alternatives for Call
      </Accordion>
    </AccordionGroup>
  </Tab>

  <Tab title="Avoid varying">
    <Warning>
      **Content you usually should NOT vary:**

      * Broad agent role and overall scope (keep consistent across variants unless you truly operate different agents)
      * Safety policies
      * Core tone guidelines (small adjustments are fine; wholesale tone shifts are not)
    </Warning>
  </Tab>
</Tabs>

## Testing variants

<Steps>
  <Step title="Switch to a non-default variant">
    Select a variant other than your default
  </Step>

  <Step title="Run your tests">
    Execute the same tests you used earlier:

    * Simple FAQ (Chat and Call)
    * Multiturn FAQ
    * SMS/handoff topic phrasing (where relevant)
    * Any brand-sensitive language (greeting, disclaimers, closings)
  </Step>

  <Step title="Verify behavior">
    Confirm:

    * Switching variants changes **only what you intended**
    * Core behavior remains consistent (no missing topics, no broken escalation language)
    * In Conversation review/diagnosis, you can clearly see which variant handled the interaction
  </Step>
</Steps>

## Operational tips

<CardGroup cols={2}>
  <Card title="Start small" icon="seedling">
    Keep the number of variant fields small at first. Add fields only when you have a clear use case.
  </Card>

  <Card title="Store facts" icon="database">
    Prefer storing factual, high-impact values (hours, addresses, names) rather than duplicating full KB answers.
  </Card>

  <Card title="Use Import/Export" icon="file-import">
    When onboarding many variants at once; it reduces manual errors and makes review easier.
  </Card>

  <Card title="Maintain a default" icon="star">
    Always maintain a **Default variant** so there is a safe fallback when context is missing or misconfigured.
  </Card>
</CardGroup>

## Check your understanding

<Quiz
  questions={[
{
q: "What are variants for?",
options: [
  "Creating separate agent projects for each location",
  "Testing different LLM models in production",
  "Tailoring agent responses for different contexts without creating separate projects",
  "Rolling back to a previous published version",
],
correct: 2,
explanation: "A variant is a named configuration profile – same core agent, different values for specific fields. This avoids project sprawl when you need context-specific behavior.",
}
]}
/>

## Try it yourself

<Steps>
  <Step title="Challenge: Design a variant strategy for a hotel chain">
    You are deploying one agent for three hotel properties: The Linden (London), The Linden (New York), and The Linden (Tokyo).

    Answer:

    1. Write your one-sentence variant strategy statement.
    2. List **3 fields** that belong in variants.
    3. List **1 field** that should NOT be in variants – and explain why.

    <Accordion title="Hint">
      Think about what changes per property (hours, address, local phone number) vs what should stay the same (core agent role, safety rules, overall tone).
    </Accordion>

    <Accordion title="Example solution">
      1. **Strategy:** "A variant represents a single Linden Hotel property."

      2. **Fields in variants:**
         * `hotel_name` (e.g., "The Linden London")
         * `check_in_time` / `check_out_time`
         * `front_desk_phone`

      3. **Should NOT be in variants:** Safety policies (e.g., "Never share guest information"). These are non-negotiable constraints that should apply identically across all properties.
    </Accordion>
  </Step>
</Steps>

## Check your understanding

<Quiz
  questions={[
{
q: "Which type of content is best suited for variants?",
options: [
  "Core safety policies and compliance language",
  "The agent's overall tone and personality",
  "Location-specific facts like hours, addresses, and escalation language",
  "LLM model selection per session",
],
correct: 2,
explanation: "Safety policies and core tone should NOT vary. Location-specific facts – hours, addresses, escalation language – are frequently repeated, context-specific, and risky if wrong, making them ideal candidates for variants.",
}
]}
/>

<CardGroup cols={2}>
  <Card title="← Previous: Global ASR" icon="arrow-left" href="/learn/guides/advanced/global-asr">
    Lesson 6 of 8
  </Card>

  <Card title="Next: Advanced diagnostics →" icon="arrow-right" href="/learn/guides/advanced/conv-review">
    Lesson 8 of 8
  </Card>
</CardGroup>

<ProgressTracker lessonKey="l2-7-variants" lessonNum={7} totalLessons={8} level="Level 2" />
