Lesson 6.1
Prompt Engineering in Code
Turning prompt engineering techniques into maintainable code: system prompts, templates that separate instructions from data, XML structure, few-shot examples and the request parameters that shape output.
In an application a prompt is not a one-off message; it is a template that thousands of inputs flow through. Good prompt engineering in code means the same things Anthropic's prompting guide recommends, plus the discipline to keep instructions, data and parameters separate and versioned. The exam tests both the techniques and where each one belongs in the request.
Where instructions live
The system field carries the role, rules, output format and background that apply to every turn. The user message carries the task and the data. Keeping them apart makes the system prompt cacheable and makes it obvious which text is trusted instruction and which is untrusted input.
SYSTEM = """You are a support triage assistant for Acme.
Classify tickets, reply in British English, and never promise refunds.
Output format: one line with the category, then a two-sentence summary."""
def triage(ticket_text: str):
return client.messages.create(
model=MODEL, max_tokens=300, system=SYSTEM,
messages=[{"role": "user", "content":
f"<ticket>\n{ticket_text}\n</ticket>\nClassify and summarise this ticket."}],
)
Be direct and specific
Claude responds best to clear, explicit instructions. State the audience, the desired length, the format and what to do in edge cases ("if the ticket is not in English, reply unknown"). Explain why a rule exists when it is not obvious; the model generalises better from reasons than from bare commands. Avoid "do not" lists without alternatives; say what to do instead.
Structure with XML tags
Wrap distinct parts of the prompt in tags such as <document>, <examples>, <instructions> and <ticket>. Tags tell the model where data begins and ends, prevent instructions in the data from being confused with yours, and let you ask for tagged output you can parse reliably:
prompt = f"""<document>{doc}</document>
<question>{q}</question>
Answer inside <answer></answer> tags. If the document does not contain the answer, write <answer>NOT FOUND</answer>."""
Tags are plain text; the API attaches no special meaning to them, but Claude is trained to respect them.
Few-shot examples
Two to five examples of input and ideal output, wrapped in <example> tags, do more for consistency than paragraphs of description. Make examples diverse and realistic, and keep them in the system prompt or a cached prefix because they rarely change.
const system = `Extract the product and sentiment.
<examples>
<example><input>Love the new kettle, boils fast</input><output>{"product":"kettle","sentiment":"positive"}</output></example>
<example><input>Toaster died after a week</input><output>{"product":"toaster","sentiment":"negative"}</output></example>
</examples>`;
Give Claude room to think
For reasoning-heavy tasks, ask for the analysis before the answer ("Think through the evidence in <thinking> tags, then give the verdict in <verdict> tags"), or enable the model's native extended thinking where supported. Both improve accuracy on multi-step problems at the cost of more output tokens; neither is useful for trivial extraction.
Parameters that shape output
| Parameter | Effect |
|---|---|
max_tokens | Hard cap on output; set it to the task, not the maximum |
temperature | 0 for deterministic-leaning classification, higher for creative variety (not accepted by every model generation; check the model page) |
stop_sequences | Stop generation when a string appears, e.g. ["</answer>"] to avoid trailing text |
system | Persona and rules for the whole conversation |
Prefilling the assistant turn (starting the response with { or <answer>) was a classic steering technique on earlier models; the current generation rejects assistant prefill, so use structured output (lesson 6-2) or explicit format instructions instead.
Templates as code
- Keep prompts in version-controlled files or constants with a version identifier, and log that identifier with every request.
- Build messages with a function that takes typed inputs rather than scattered f-strings; escape or wrap user data in tags so it cannot break the structure.
- Never concatenate untrusted input into the
systemfield. - Keep the stable part of the template byte-identical between requests so prompt caching works.
- Pair every template with an eval case set (lesson 4-1) so edits are measured.
Iterating safely
Use the Console's prompt workbench to iterate quickly, then copy the final prompt into code. When a prompt underperforms, change one thing at a time: clarify the instruction, add an example, add structure, then consider thinking or a larger model. Record what moved the eval score.
Exam focus
- Instructions and persona belong in
system; task and data belong in the user message, with data wrapped in XML tags. - Clear, specific, explained instructions outperform vague ones; say what to do rather than only what not to do.
- Few-shot examples in
<example>tags are the most reliable way to fix format and consistency. stop_sequencesends generation at a string;temperaturecontrols randomness where the model supports it;max_tokenscaps length.- Asking for reasoning before the answer, or enabling extended thinking, helps complex tasks and wastes tokens on simple ones.
- Assistant prefill is not supported on current models; use structured output or explicit format instructions.
Check yourself
5 questions
1.In a Messages API request, where should the assistant's role, tone and standing rules ("You are a senior data engineer; answer in British English; never invent column names") be placed?
2.A prompt is built as: prompt = "Summarise this: " + user_document + " Output three bullet points." Sometimes the output ignores the bullet-point instruction because the document itself contains sentences like "write a long essay". What is the recommended improvement?
3.A developer wants consistent formatting from a ticket-triage prompt and decides to add few-shot examples. How should they be supplied?
4.A question-answering prompt places the user's question first, followed by a 60,000-token contract. Answer quality is mediocre. What does Anthropic's long-context guidance recommend?
5.The prompt "Write something about our product" produces unusable output. Which fix reflects Anthropic's core prompting advice?
