> ## 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.

# Tutorial: Writing natural agent speech

> PolyAcademy Level 3 – Write brief, conversational copy that sounds human.

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

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

<Info>
  **Level 3 – Lesson 4 of 5** – Write agent copy that sounds human, not generated.
</Info>

<LessonMeta level={3} difficulty="Advanced" time="15 min" />

LLMs default to verbose, overly formal phrasing. Copywriting separates an agent that works from one that feels right – this lesson teaches you to identify and fix the patterns that make agent speech sound generated, not human.

## Keep it brief

In general, concise responses are clearer, more respectful of the user's time, and avoid sounding like an advert.

<Tabs>
  <Tab title="Good">
    > "If you want, I can also sign you up for our rewards program so you can get a free appetizer with your next meal – would you like me to do that?"

    Brief, clear, one question.
  </Tab>

  <Tab title="Bad">
    > "Our Prime Rib Rewards Program lets you earn 10 cents in rewards for every dollar spent at any of our twelve locations! Plus, if you sign up today, you'll get a free delicious appetizer like our mouth-watering buffalo wings or crispy onion rings with your next meal. Would you like me to enroll you?"

    Too long, reads like an advertisement, and users disengage when they feel they are being sold to.
  </Tab>
</Tabs>

### When longer is better

The exception: when the user asks for an explanation. Being more thorough gives them time to process the information. If a user says "Can you explain what the CARE program is?", be detailed:

<Tabs>
  <Tab title="Good (thorough)">
    > "California Alternate Rates for Energy, also known as CARE, is a discount program for lower-income California residents to help with monthly energy costs. You can get a discount of 20% or more on your electric bill if you meet the income requirements or are enrolled in certain public assistance programs. Do you want me to send you a text with more info about CARE and how to apply?"
  </Tab>

  <Tab title="Too brief">
    > "CARE is an income-based discount program for energy bills in California. There are a few ways to qualify; do you want me to send you a text about that?"
  </Tab>
</Tabs>

## Tone and formality

LLMs default to verbose, overly formal phrasing. Correct this consistently:

| Avoid                                                     | Prefer                                     |
| --------------------------------------------------------- | ------------------------------------------ |
| "Could you please *provide me with* your account number?" | "Could you *tell me* your account number?" |
| "How may I assist you today?"                             | "How can I help?"                          |
| "I apologize for the inconvenience."                      | "Sorry about that."                        |
| "Should I proceed with making that booking?"              | "Should I go ahead with that?"             |

Also use:

* **Contractions** – "I'll", "we're", "that's"
* **Informal word forms** – "alrighty", "gotcha"
* **Fragments** – "Sound good?" instead of "Does that sound good to you?"

<Quiz
  questions={[
{
q: "Which phrasing is more appropriate for a voice agent?",
options: [
  "I apologize for the inconvenience. How may I assist you further?",
  "Sorry about that. How can I help?",
  "I regret the difficulty you are experiencing. Please allow me to assist.",
  "My apologies. What would you like assistance with?",
],
correct: 1,
explanation: "Voice agents should sound conversational and informal-professional. Contractions, shorter phrases, and natural word choices avoid the robotic formality that LLMs default to.",
}
]}
/>

## Avoiding repetitive structure

LLMs overuse this pattern:

**`[explanatory statement] [request that references the explanation]`**

> "In order to check for outages, I'll need to look up your account. Could you tell me your account number?"

Then on the next turn:

> "Okay, I've found your account. To verify your identity, I'll need your birth date. Could you please provide me with that?"

The explanatory statement is usually unnecessary – the user can infer *why* from context. Combine into a single natural question:

| Verbose pattern                                                                                            | Better                                                                                      |
| ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| "In order to check for outages, I'll need to look up your account. Could you tell me your account number?" | "No problem, what's your account number?"                                                   |
| "To verify your identity, I'll need your birth date. Could you please provide me with that?"               | "Great, and just to verify I have the right account, could you tell me your date of birth?" |

Notice that both alternatives also **vary from each other** – different openings, different structures.

## Making speech sound human

These techniques make agent speech feel like a real conversation rather than a script. Use them in pre-scripted copy and as examples in style guides.

<Note>
  Some of these techniques are dialect-specific and may not work in all contexts. They are examples and inspiration, not universal rules.
</Note>

### Use "I'm looking" instead of "I don't see"

Saying "I'm not seeing any accounts..." (present progressive) sounds like you're actively helping. Saying "I don't see any accounts..." (simple present) sounds final and definitive – it shuts the door.

| Less natural                                        | More natural                                             |
| --------------------------------------------------- | -------------------------------------------------------- |
| "I don't see any accounts under that phone number." | "I'm not seeing any accounts under that phone number..." |

### Reference shared context without restating it

In conversation, people reference what they've already discussed implicitly. LLMs tend to repeat the context explicitly:

| Over-explicit                                                          | Natural                                          |
| ---------------------------------------------------------------------- | ------------------------------------------------ |
| "Since you said you prefer weekends, how does Saturday at 2:30 sound?" | "In that case, how does Saturday at 2:30 sound?" |
| "How about Wednesday instead of Tuesday?"                              | "How about Wednesday instead?"                   |

### Vary your acknowledgements

Acknowledgements like "Great", "Okay", "Perfect" create a sense of flow. But LLMs tend to repeat the same one:

| Repetitive                              | Varied                                  |
| --------------------------------------- | --------------------------------------- |
| "Great, ... " "Great, ..." "Great, ..." | "Great, ..." "Okay, ..." "Perfect, ..." |

### Use "for me" to sound invested

Adding "for me" to a request makes it feel like the agent is personally involved, not just following a script:

| Standard                                    | More personal                            |
| ------------------------------------------- | ---------------------------------------- |
| "Could you read your account number aloud?" | "Could you read me your account number?" |
| "Can you log into your account?"            | "Can you log into your account for me?"  |

### Soften references to what the user wants

When referencing the user's request, past tense sounds more polite than present tense:

| Direct                            | Softer                                                               |
| --------------------------------- | -------------------------------------------------------------------- |
| "When are you trying to come in?" | "When were you trying to come in?" / "When did you want to come in?" |

<Quiz
  questions={[
{
q: "The agent says: 'I don't see any accounts under that phone number.' How could this be improved?",
options: [
  "Add an apology: 'I'm sorry, I don't see any accounts under that phone number.'",
  "Use present progressive: 'I'm not seeing any accounts under that phone number...'",
  "Add an explanation: 'Our system does not have any accounts registered under that phone number.'",
  "Add a follow-up question: 'I don't see any accounts. Are you sure that's the right number?'",
],
correct: 1,
explanation: "'I'm not seeing' sounds like you're actively looking and might have missed something – it's less definitive and more collaborative than 'I don't see'.",
}
]}
/>

## Don't push the conversation forward on every turn

LLMs are biased toward ending every turn with a question. This gets repetitive and unnatural.

### Step-by-step walkthroughs

Don't ask for confirmation after every step. In real conversations, the guide gives an instruction and waits – the user will naturally confirm or ask a follow-up.

<Tabs>
  <Tab title="Bad (over-prompting)">
    > Agent: "First, scroll down and click 'Account settings'. *Let me know when you've done that.*"
    > User: "I've done that."
    > Agent: "Then click 'Contact Details'. *Let me know when you're ready for the next step.*"
    > User: "Okay."
    > Agent: "Great. Then select the address you want to edit. *Let me know when you've done that.*"
  </Tab>

  <Tab title="Good (natural pacing)">
    > Agent: "First, scroll down and click 'Account settings'."
    > User: "Okay."
    > Agent: "Then hit 'Contact Details'."
    > User: "Okay, yep."
    > Agent: "Then just select the address you want to edit and input your new details!"
  </Tab>
</Tabs>

### Don't immediately ask "anything else?"

After answering a question, don't immediately ask if there's anything else. Give the user space to acknowledge or follow up:

<Tabs>
  <Tab title="Too pushy">
    > Agent: "Yes, we have large vehicle parking on Meridian Street during weekdays. Is there anything else I can help you with?"
  </Tab>

  <Tab title="Better">
    > Agent: "Yes, we have large vehicle parking on Meridian Street during weekdays."
    > User: "Okay, thanks."
    > Agent: "No problem. Is there anything else I can help you with?"
  </Tab>
</Tabs>

## Try it yourself

<Steps>
  <Step title="Challenge: Rewrite these agent responses">
    Rewrite each response to be more natural:

    1. "Could you please provide me with the phone number associated with your account so that I can look up your information?"
    2. "I apologize for the inconvenience. Let me check on that for you. Could you please hold for a moment?"
    3. "Thank you for providing that information. To verify your identity, I will need your date of birth. Could you please provide me with that?"

    <Accordion title="Example rewrites">
      1) "What's the phone number on your account?"
      2) "Sorry about that – let me take a quick look."
      3) "Great, and just to check I've got the right account, what's your date of birth?"
    </Accordion>
  </Step>
</Steps>

<Quiz
  questions={[
{
q: "After answering a user's question about parking, the agent immediately says 'Is there anything else I can help you with?' What's wrong with this?",
options: [
  "Nothing – it's good practice to always offer more help",
  "It doesn't give the user a chance to acknowledge the answer or ask a follow-up",
  "The agent should transfer to a live agent instead",
  "The agent should repeat the parking information first",
],
correct: 1,
explanation: "Immediately asking 'anything else' is too pushy. Let the user acknowledge the answer or ask a follow-up. The 'anything else' should come after the user signals they're satisfied.",
}
]}
/>

<CardGroup cols={2}>
  <Card title="← Previous: Flow patterns" icon="arrow-left" href="/learn/guides/expert/flow-patterns">
    Lesson 3 of 5
  </Card>

  <Card title="Next: Voice polish →" icon="arrow-right" href="/learn/guides/expert/voice-polish">
    Lesson 5 of 5
  </Card>
</CardGroup>

<ProgressTracker lessonKey="l3-4-utterance-design" lessonNum={4} totalLessons={5} level="Level 3" />
