Anatomy of a Good Prompt
The building blocks of a prompt that works: the task, context, input, output format, examples and constraints, and how to put them together.
The parts of a prompt
Prompts and prompt engineering lists the levers of a prompt and shows a before-and-after example for a service desk reply. This page takes the prompt apart in more detail. A prompt component is one functional part of a prompt, such as the task, the context, the input data, the output format, examples or constraints; a component can be one sentence or several pages, and a short prompt often combines several in one line.
Model providers describe the same idea with different lists (as of October 2026):
| Source | Parts it names |
|---|---|
| Microsoft Copilot help | Goal, context, expectations, source |
| Microsoft Foundry prompt engineering guide | Instructions, primary content, examples, cue, supporting content |
| Anthropic prompting best practices | Clear instructions, context and motivation, examples, sections marked with XML tags, a role, long documents at the top, guidance on the output format |
| Google Gemini prompt design strategies | Clear and specific instructions, examples, context placed before the question, sections marked with XML-style tags or Markdown headings; essential constraints, role and output format in the system instruction or at the start |
The lists overlap far more than they differ. One item is worth a remark: a cue is the first words of the answer, written into the prompt for the model to continue. It is still documented for some models, but Anthropic's API rejects a pre-filled final answer on its newer models (Claude 4.6 and later, as of October 2026); use an explicit format instruction or structured output instead.
The task
The task instruction is the part of a prompt that says what the model must do: one action, stated with a verb, applied to a named object. "Draft a first reply to the user", "List the error lines with their timestamps", "Classify the ticket as Network, Account, Portal or Billing". It is the one component no prompt can do without, and the one most often left vague: "Help with this ticket" can mean summarize it, answer it, solve the problem or write the internal note.
Three habits make the task unmistakable:
- One main task per prompt. "Summarize the incident, find the root cause and write the customer update" is three tasks of very different difficulty. Split them, or number them (see Breaking Down Tasks: Prompt Chaining).
- Numbered steps when the order matters. Anthropic recommends giving instructions "as sequential steps using numbered lists or bullet points when the order or completeness of steps matters".
- Advice or action? "Can you suggest changes?" and "Change this" lead to different results, and models differ in which way they lean. Say which one you want; see Clear and Specific Instructions.
Context and input
Two components carry information, and it helps to keep them apart. Context is background the model cannot know: who you are, who will read the answer, what the situation is, which rules apply. Input is the material to work on: the ticket, the log excerpt, the email, the policy text. Context shapes how the model works; input is what it works on.
Pasted material should be clearly marked off from your instructions, so the model cannot mistake a sentence in a ticket for an instruction from you. A common way is a pair of tags around each piece:
<ticket>
INC-40388 — Customer reports that the smart-meter reading for October shows 0 kWh in the customer portal. The meter display shows 18,204 kWh.
</ticket>
Summarize the ticket above in one sentence for the billing team.
Tags, headings and other ways of marking material, how much context to give and how to keep the model to the material you supplied are the subject of Giving Context and Reference Material.
The output format
The output format is the part of a prompt that describes the form of the answer: its length, structure (prose, bullets, a table, JSON), language, tone and the order of its parts. Without it the model picks a typical form for the task, which is often longer and more decorated than you want: headings and bullets for a two-line answer, a friendly preamble before the content.
Write the handover note for INC-40388 as exactly three lines, in this order:
Status: (one sentence)
Next step: (one sentence, who does what)
Waiting for: (a person or "nothing")
A template like this does two jobs at once: it fixes the structure and shows the length. Two more points help:
- The prompt's style rubs off. Anthropic notes that removing Markdown from your prompt can reduce the Markdown in the output. If you want plain prose back, write the prompt in plain prose.
- Programs need more than a request. When code reads the answer, ask for JSON with named fields and validate the result; see Structured Output.
Constraints and a way out
A prompt constraint is an instruction that limits what the answer may contain or do, such as a length limit, a source restriction ("use only the policy below"), a scope ("change only this function") or a rule ("never ask for the password"). Constraints exist because a model fills every gap with what is typical, and typical is sometimes exactly wrong for you: a typical reply to a locked account suggests a password reset; your policy may require a callback first.
The most useful constraint is a way out: what the model should do when the information it needs is not there. Microsoft's guide calls this giving the model an "out", for example answering "not found" if the answer isn't present. Without one, a model asked a question tends to answer it, even when the honest answer is "the ticket doesn't say".
From the ticket above, give the meter number. If the ticket does not contain a meter number, answer "not in ticket" and nothing else.
How to phrase constraints so that they work — positive rather than only negative, with a reason, without shouting — is on Clear and Specific Instructions.
Examples and a role
Two more components are optional but powerful. Examples of good answers show a pattern that is hard to describe, such as the exact labels to use or the tone of a reply; the model imitates them closely, quirks included. How many to give and how to choose them is on Zero-Shot, One-Shot and Few-Shot Prompting. A role ("You draft replies for the Kestrel Energy service desk") sets vocabulary, tone and focus, and in applications it usually lives in the system prompt; what a role does and does not do is on Roles and System Prompts.
Putting it together
For a long prompt, an order that follows the vendors' placement advice (see Position matters) works well: role and standing rules, then context, then the reference material and input, then examples, and the task last. Vendors differ on where format and constraints go: Anthropic places instructions after long documents, while Google puts essential constraints and output format in the system instruction or at the start, with only the question at the very end. If in doubt, state them in the system prompt or at the start and repeat the key one with the task. For a short prompt the order hardly matters. In code, building a prompt from named parts keeps that order the same every time:
# Assemble a prompt from named parts in a fixed order: reference material
# first, then the input, then the task, format and constraints last.
parts = {
"context": "Kestrel Energy is a Dutch energy supplier. You draft first "
"replies for the service desk; an analyst checks every reply.",
"policy": "Locked accounts are unlocked only after identity verification "
"by a callback to the phone number in the HR system.",
"ticket": "INC-40311: Field engineer gets 'account locked' after "
"a password change this morning.",
"task": "Draft a first reply to the user of the ticket.",
"format": "At most 80 words, friendly, ending with one question.",
"constraints": "Use only the policy above. If the policy does not cover "
"the situation, say that an analyst will follow up.",
}
def build_prompt(parts):
blocks = [f"<{name}>\n{parts[name]}\n</{name}>"
for name in ("context", "policy", "ticket")]
blocks.append(f"Task: {parts['task']}")
blocks.append(f"Format: {parts['format']}")
blocks.append(f"Constraints: {parts['constraints']}")
return "\n\n".join(blocks)
print(build_prompt(parts))
<context> Kestrel Energy is a Dutch energy supplier. You draft first replies for the service desk; an analyst checks every reply. </context> <policy> Locked accounts are unlocked only after identity verification by a callback to the phone number in the HR system. </policy> <ticket> INC-40311: Field engineer gets 'account locked' after a password change this morning. </ticket> Task: Draft a first reply to the user of the ticket. Format: At most 80 words, friendly, ending with one question. Constraints: Use only the policy above. If the policy does not cover the situation, say that an analyst will follow up.
The same parts in one place make the prompt easy to review and to change one part at a time; turning this into a reusable template with variables is covered in Prompt Templates and Reuse. In a chat you write the same structure by hand. The Try it yourself box uses the four parts from Microsoft's Copilot guidance: goal, context, expectations and source.
Try it yourself
Open a new chat in an AI assistant (Claude, ChatGPT, Copilot, Gemini) and paste the first prompt. Then start another new chat and paste the second.
Help Amara with this ticket: user can't log in.
Goal: draft a first reply to the user of ticket INC-40311.
Context: the user is a field engineer at Kestrel Energy, an energy supplier. Since changing their password this morning, they get the message "account locked" when they sign in to the field app. Amara Okafor of the service desk will send the reply after checking it.
Expectations: at most 80 words, friendly and plain, ending with one question to the user.
Source: use only the policy between the policy tags. If the policy does not cover the situation, say that an analyst will follow up.
<policy>
Service desk policy SD-07: A locked account is unlocked by the service desk only after the user's identity has been verified by a callback to the phone number registered in the HR system. Never ask for a password, by phone or in writing. Unlocking does not reset the password.
</policy>
What to look for: how many things the first answer has to assume (who Amara is, which system, whether to write to Amara or to the user) and whether it suggests generic steps such as a password reset; whether the second answer mentions the callback, stays under 80 words and ends with one question; whether either answer asks for the password.
Knowing what good looks like
Before you can improve a prompt you need to know what "better" means. A success criterion is a specific, checkable condition that a good answer must meet, such as "uses only labels from the list", "at most 80 words", "never asks for a password" or "names the ticket number". Anthropic puts this before any prompt writing: first have success criteria and a way to test against them, then write a first draft of the prompt.
Good criteria come straight from the components: the task says what must be done, the format what shape it must have, the constraints what it must never contain. Writing them down also shows which components your prompt is missing. Some checks can even be automated. The toy checker below looks for a few components with keyword patterns; it understands nothing, but it shows the idea of checking a prompt against a list:
import re
# A toy prompt checker: keyword heuristics, not understanding.
GAPS = {
"no output format named": r"\b(bullets?|table|json|list|sentences?|paragraphs?)\b",
"no length given": r"\b(at most|max(imum)?|under|no more than)\s+\d+|\b\d+\s+(words|sentences|bullets)\b",
"nothing on missing information": r"\bif\b[^.]*\b(missing|not (covered|found|known)|does not (say|cover))\b",
}
def review(prompt):
gaps = [gap for gap, pattern in GAPS.items()
if not re.search(pattern, prompt, re.IGNORECASE)]
if prompt.strip().splitlines()[-1].startswith("</"):
gaps.append("ends with pasted material instead of the task")
return gaps or ["no obvious gaps"]
prompts = {
"vague": "Help Amara with this ticket: user can't log in.",
"pasted last": "Summarize this ticket in 3 bullets.\n<ticket>\n...\n</ticket>",
"complete": "<ticket>\n...\n</ticket>\nSummarize the ticket in at most "
"3 bullets. If the ticket does not say which system, write 'unknown'.",
}
for name, prompt in prompts.items():
print(f"{name}:")
for finding in review(prompt):
print(f" - {finding}")
vague: - no output format named - no length given - nothing on missing information pasted last: - nothing on missing information - ends with pasted material instead of the task complete: - no obvious gaps
A checker like this says nothing about whether the answers are good. That needs real test cases, run before and after every change; see Iterating and Testing Prompts.