> ## Documentation Index
> Fetch the complete documentation index at: https://polyai-mintlify-665e356f.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Level 3 complete

> PolyAcademy – You can structure complex projects, design reliable flows, and polish agent speech for production.

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>;
};

<Check>
  **Level 3 complete!** You've reached the highest level of PolyAcademy. You can structure complex projects, design reliable flows, and polish agent speech to production quality.
</Check>

You covered:

* [Code organization](/learn/guides/expert/code-organization): utility files, imports, and the `conv.functions` pattern
* [Flow fundamentals](/learn/guides/expert/flow-fundamentals): steps, persistent prompts, transitions, and exit behavior
* [Flow patterns](/learn/guides/expert/flow-patterns): collection, validation, verification, and deterministic vs LLM-led control
* [Writing natural agent speech](/learn/guides/expert/utterance-design): brevity, tone, avoiding repetitive structure
* [Voice polish](/learn/guides/expert/voice-polish): filler, turn-taking, personalization, and voice quality

You can now answer without guessing:

* How should I structure code so it stays maintainable?
* When should I use a flow vs a function vs a managed topic?
* How do I enforce strict retry limits while keeping speech natural?
* What makes agent speech sound human rather than generated?

## Level 3 recap quiz

<Quiz
  questions={[
{
q: "You need the same phone number validation in 5 different flow functions. What's the best approach?",
options: [
  "Copy the validation regex into each function",
  "Define it once in a utility file and import it everywhere",
  "Use conv.functions to share the validation",
  "Add the validation to the Behavior field",
],
correct: 1,
explanation: "Define the validation in a utility file and import it with standard Python syntax. Update it in one place, fix it everywhere – this is the core benefit of modular code.",
},
{
q: "A flow collects a phone number in step 1, but users sometimes give their name first. What should happen?",
options: [
  "Reject the name and repeat the phone number question",
  "Accept the name, save it, and still ask for the phone number – handle information in any order",
  "Skip the phone number step since the user volunteered different info",
  "Exit the flow and start over",
],
correct: 1,
explanation: "Design principle 2 (listen robustly): handle information in any order. If the user gives their name unprompted, save it and continue collecting the phone number. Don't discard useful information.",
},
{
q: "A user fails identity verification three times. The flow should transfer to a live agent. How do you implement the transfer message?",
options: [
  "Hard-code a fixed phrase like 'Transferring you now'",
  "Let the LLM generate the message freely",
  "Pass the utterance as a function argument so the LLM generates context-appropriate phrasing with deterministic execution",
  "Use a Response Control to replace the agent's message",
],
correct: 2,
explanation: "Passing the utterance as a function argument gives you LLM-generated phrasing (context-aware) with deterministic execution (the handoff always happens). Best of both worlds.",
},
{
q: "The agent says 'In order to look up your account, I'll need your phone number. Could you please provide me with that?' – on every single turn. What are two things wrong?",
options: [
  "The response is too short and needs more detail",
  "The explanatory preamble is unnecessary, and the phrasing is too formal – simplify to 'What's your phone number?'",
  "The agent should ask for email instead",
  "The agent should use DTMF input for phone numbers",
],
correct: 1,
explanation: "Two issues: the explanatory statement ('In order to...') is filler the user can infer from context, and 'Could you please provide me with' is overly formal. Combine into a single natural question.",
}
]}
/>

## What's next?

You've completed all three levels. From here, the reference docs and maintain guides are your ongoing companions:

<CardGroup cols={3}>
  <Card title="Maintain your agent" icon="wrench" href="/learn/maintain/introduction">
    Best practices for keeping a live agent healthy and up to date
  </Card>

  <Card title="Help Center" icon="book-open" href="/home">
    Full reference documentation for every Agent Studio feature
  </Card>

  <Card title="Back to PolyAcademy" icon="house" href="/learn/guides/introduction">
    Return to the main learning hub
  </Card>
</CardGroup>

<ProgressTracker lessonKey="l3-finished" />
