Index Ai Academy
Phase 1 · Building with LLMs · Prompting

Prompt fundamentals

Clear instructions, context and constraints: the 80% of prompting.

About 30 minutes · A free account opens the whole lesson

Create a free account Try part of it here

Already have an account? Sign in to open this lesson

Why it matters

The prompt is the main control you have over a model. The same model can send back a vague paragraph or exactly the output your code needs. The difference is almost always how clearly you described the task. Good prompting has little to do with secret phrases. It's much closer to leaving a clear note for a house-sitter or writing a brief for a freelancer. If you've done either, you already have the core skill.

What you'll be able to do

  • Rewrite a vague request as a prompt with a task, context, constraints and an output format
  • Separate instructions from the material the model works on, using XML-style tags
  • Build prompts from a Python template so every request is worded the same way
  • Test a prompt on several inputs, and handle replies that don't follow the format

What it covers

  1. Write the brief you'd give a new hire
  2. Specific beats clever
  3. Keep instructions and material apart
  4. Templates: the same wording every time
  5. Worked example: one template, several reviews

Write the brief you'd give a new hire

Picture a friend who will look after your dog for the weekend. A note that says "Feed the dog" isn't enough. They need to know how much food, when, where it's kept, and what to do if she won't eat. You know all of that already, so it's easy to forget to write it down.

A model is in the same spot as your friend. It knows a great deal about the world in general. It knows nothing about your situation: your business, your audience, why you're asking, or what happens to the answer next. You saw in "What an LLM actually does" that a model writes by picking likely next tokens. Generic text is usually the most likely text. So when a prompt leaves out the details, the model fills the gaps with the most generic guess.

A prompt is the text you send to the model. Here are two prompts for the same job, a sale email for an outdoor clothing store:

Write an email about our sale.
Write a promotional email for Trailhead Outfitters, an outdoor clothing brand.
The audience is past customers who bought rain gear in the last two years.
The offer: 30% off all rain jackets, ending Sunday at midnight.
Keep it under 120 words, in a friendly, plain tone, with one call to action.
Return the subject line on the first line, then a blank line, then the body.

The first gets you an email written for nobody in particular. The second gets you something close to ready to send.

Here's a useful test. Imagine a capable colleague who knows nothing about the task. Would they need to ask you questions before they could start? If so, the model needs those answers too. For a product description: who it's for, its key features, a word limit, where it will appear. Unlike the colleague, the model won't ask. It will guess.

Four parts of a clear prompt

The second prompt works because it covers four things:

PartWhat it answersExample
TaskWhat should it do? Start with a verb."Write a promotional email"
ContextWho is it for, why, and what facts does it need?"past customers who bought rain gear; 30% off, ends Sunday"
ConstraintsWhat limits apply?"under 120 words, friendly and plain, one call to action"
Output formatExactly what should come back?"subject line first, a blank line, then the body"

The task is the job itself. The context is the background the model can't know on its own. Constraints are the limits, such as length and tone. The output format is the exact shape of the reply.

Short prompts don't need every part spelled out. When a reply disappoints, though, one of the four is usually missing.

Quick check
"Write a birthday message for my coworker Dana. Keep it under 40 words, warm but not cheesy. Reply with the message only." Which of the four parts is thinnest here?
  1. Task: it never says what to write
  2. Output format: it doesn't say what should come back
  3. Context: it says nothing about Dana or how well you know her
  4. Constraints: there's no length limit
Show the answer

Context: it says nothing about Dana or how well you know her

The task (write a birthday message), the constraints (under 40 words, warm but not cheesy) and the output format (the message only) are all there. Apart from "coworker", the model knows nothing about Dana, so it will write a message that could be for anyone.

Try it now

Send the vague prompt first. Then replace it with the detailed version above and send again. It's the same model, but you'll get a very different email. If a reply comes back cut off, raise max_tokens.

Specific beats clever

Some prompting advice is about tricks: magic phrases, flattering job titles, even threats. Specific prompting means saying exactly what you want, and it works far better. A few habits make the biggest difference:

  • Use numbers instead of adjectives. "Three options, each under 50 characters" beats "a few short options".
  • Say what to do, not only what to avoid. "Write in plain sentences" works better than "Don't use bullet points" on its own.
  • Give the reason for a rule. Say "Keep subject lines under 50 characters, because longer ones get cut off on phones." The reason lets the model apply the idea to cases your rule didn't mention.
  • Give it a way out. Add "If the review doesn't mention shipping, reply none." This stops the model from inventing an answer to fit the question.
  • Ask for the exact output. "Reply with the subject line only" saves your code from digging the answer out of "Sure! Here's a subject line you could use: ...".

You don't need magic phrases, threats or ALL CAPS. Current models follow plain, specific instructions closely. Shouting a rule can even backfire, because the model may then apply it too broadly.

Quick check
You ask a model, "What does this review say about shipping?" The review never mentions shipping. What is the best fix?
  1. Nothing: a model never answers a question the text can't support
  2. Add "If the review doesn't mention shipping, reply none."
  3. Tell the model it is the world's best review analyst
  4. Write the question in ALL CAPS so the model reads it carefully
Show the answer

Add "If the review doesn't mention shipping, reply none."

Without a way out, the model tends to invent an answer that fits the question. A stated fallback like none gives it an honest reply to choose, and gives your code something easy to check.

Keep instructions and material apart

Most real prompts mix two things. There are your instructions, and there's material to work on: a review, an article, a list of products. Think of forwarding an email to a coworker with a note on top. A clear line between your note and the forwarded text stops them from mixing the two up.

In a prompt, you draw that line with XML-style tags. These are labels you make up, written in angle brackets. An opening tag like <review> marks where the material starts. A closing tag with a slash, </review>, marks where it ends. (XML is a data format that uses labels like these. You don't need to know anything else about it.)

Classify the sentiment of the customer review below.

<review>
The jacket kept me dry on a six-hour hike, but the hood is too small to fit over a cap.
</review>

Reply with one word: positive, negative or mixed.

"Sentiment" means the feeling behind the words: happy, unhappy, or a bit of both. The tag names are yours to choose. There's nothing special about review. Tags help in three ways:

  • The model can see exactly where the material starts and ends.
  • You can refer to the material by name: "the review in the <review> tags".
  • The model is less likely to treat text inside the material as instructions. That risk is called prompt injection, and it gets its own lesson later.

Some material is long, such as a report or a batch of reviews. Put it first, and put your instructions and question at the end. Models tend to answer questions about long documents better that way.

Quick check
Which prompt is most likely to return something your code can use as-is?
  1. Can you look at this review and tell me what you think about its sentiment? <review>…</review>
  2. Sentiment? <review>…</review>
  3. Classify the review in the <review> tags as positive, negative or mixed. Reply with the label only. <review>…</review>
  4. You are the world's best sentiment analyst. Analyze this review in depth. <review>…</review>
Show the answer

Classify the review in the <review> tags as positive, negative or mixed. Reply with the label only. <review>…</review>

It names the task, the allowed answers and the exact output. The others invite a chatty paragraph that your code would have to pick apart.

Templates: the same wording every time

An app sends the same kind of request many times, each with different material. Think of a form letter with blanks for the name and date. You write the prompt once, as a function. Then you fill in the blanks with an f-string:

def review_prompt(review, product):
    return f"""Classify the sentiment of this customer review of our {product}.

<review>
{review}
</review>

Reply with one word: positive, negative or mixed."""

print(review_prompt("Warm, light, and the pockets are huge.", "Ridgeline Fleece"))
It runs right here in your browser, with nothing to install.

Run it, and you'll see the full prompt with the product name and the review filled in.

With a template, every request is worded the same way. That makes results comparable from one review to the next. And when you improve the wording, every future request gets the improvement.

Test with more than one input

One good reply proves very little. It might be luck, and real inputs vary a lot. Before you rely on a prompt, run it on a handful of inputs. Include some awkward ones:

  • a very short review
  • a sarcastic one
  • one about a different product
  • one that's mostly a question

Check the replies with code wherever you can. When you change the prompt, run the same inputs again and compare. That list of test inputs is the start of an eval (short for evaluation). Phase 1 covers evals properly later.

Plan, too, for replies that ignore the format. Even "Reply with one word" can come back as "Mixed." or "Mixed: the reviewer liked the warmth but...". Clean up what you safely can, such as extra spaces, capital letters or a period at the end. Treat anything else as unknown. Don't guess.

Worked example

Worked example: one template, several reviews

This puts the lesson together. The code fills in the template for three reviews, sends each one, and cleans up each reply. When the academy has no API key, you get a simulated reply that quotes your prompt back. That isn't a label, so every result comes out unknown. That's the correct handling for a reply you can't use.

import requests

LABELS = ["positive", "negative", "mixed"]

def review_prompt(review, product):
    return f"""Classify the sentiment of this customer review of our {product}.

<review>
{review}
</review>

Reply with one word: positive, negative or mixed."""

def ask(prompt):
    response = requests.post(
        "https://api.anthropic.com/v1/messages",
        headers={"x-api-key": "added-by-the-academy-server", "anthropic-version": "2026-10-21"},
        json={"model": "claude-opus-5-5", "max_tokens": 1000, "messages": [{"role": "user", "content": prompt}]},
        timeout=60,
    )
    response.raise_for_status()
    text = ""
    for block in response.json()["content"]:
        if block["type"] == "text":
            text += block["text"]
    return text

def clean_label(reply):
    word = reply.strip().lower().rstrip(".")
    if word in LABELS:
        return word
    return "unknown"

reviews = [
    "Warm, light, and the pockets are huge.",
    "Oh great, another jacket that soaks through in a drizzle.",
    "Love the color. The sleeves are way too long, though.",
]
for review in reviews:
    label = clean_label(ask(review_prompt(review, "Ridgeline Fleece")))
    print(label, "|", review)
In the lesson you can change this and run it.

clean_label tidies each reply in three steps. strip() removes spaces and newlines from both ends. lower() turns capital letters into lowercase. rstrip(".") removes periods from the end. It works like strip, but only on the right-hand side.

Only an exact label counts. Everything else becomes unknown.

With a real model, watch the second review. It's sarcastic. "Oh great" sounds positive word by word, but the reviewer is unhappy. A prompt that labels it negative is doing real work.

Quick check
Predict the output.
def clean_label(reply):
    word = reply.strip().lower().rstrip(".")
    if word in ["positive", "negative", "mixed"]:
        return word
    return "unknown"

print(clean_label("NEGATIVE."), clean_label("Mixed, mostly"))
  1. NEGATIVE. Mixed, mostly
  2. negative unknown
  3. negative mixed
  4. unknown unknown
Show the answer

negative unknown

"NEGATIVE." is lowercased and loses its period, leaving "negative". "Mixed, mostly" becomes "mixed, mostly", which isn't an allowed label, so it turns into "unknown". The cleanup never guesses.

Practice what you just read

  • 2 code examples you can edit and run
  • a practice exercise that checks your code
  • a 5-question quiz
  • 5 review cards for spaced repetition

Create a free account

Try a quiz question

A prompt says only: "Write a product description for our fleece." Which addition would improve the result most?

  1. "Please" at the start and "thank you" at the end, since models answer polite requests with more care
  2. "You are a world-class copywriter with 20 years of experience."
  3. Who the description is for, the fleece's key features, a word limit and where it will appear
  4. "Try your very best, this is important, and my manager will read every word."

Answer it at the end of the lesson to see if you're right, and why.

Before this lesson