With each new model generation, Anthropic updates its prompting best practices, and the 5th generation is no exception.
This post distils the practical guidance from Anthropic’s documentation into actionable rules for Sonnet 5, Open 5, and Fable 5.1, focused on cloud engineering workflows.
Rules for every current model
Give the reason, not just the rule
The model will use the why or the reason to generalise and find an answer on what wasn’t present in the prompt.
Don’t do: Don't use Write-Host in the script.
Do: Don't use Write-Host: this script runs as an Azure DevOps pipeline task where only the streams are captured, and Write-Host output is invisible in the job log.
Write the output contract explicitly
The model has no idea of your convention and format.
Don’t do: Write me a PowerShell function to get ExpressRoute circuit status.
Do: Write a PowerShell 7 function Get-ErCircuitHealth. Contract:
- [CmdletBinding()], approved Verb-Noun, singular noun, comment-based help with at least one .EXAMPLE
- Accepts -SubscriptionId (mandatory, ValidateNotNullOrEmpty) and -ResourceGroupName (optional); pipeline input by property name - Emits one [PSCustomObject] per circuit: CircuitName, ServiceProviderProvisioningState, CircuitProvisioningState, PeeringLocation, BandwidthInMbps. No formatted text, no Write-Host
- try/catch with -ErrorAction Stop inside the try; rethrow with context, never an empty catch
- Filter server-side via Az cmdlet parameters, not | Where-Object after the fact
Show examples instead of describing style
Using 3-5 examples help the model to get what you want. Use
Don’t do: Write Azure Policy definitions in our usual style.
Do: Write an Azure Policy definition that denies public network access on Storage accounts. Match the conventions in these examples
— note that they cover deny, audit and deployIfNotExists, and both a single-condition and an allOf policyRule:
{ ...our existing deny-public-ip policy JSON... } { ...our existing audit-diagnostic-settings policy JSON... }
{ ...our existing deployIfNotExists policy JSON... }
State what to do, not what to avoid
a prohibition describes a space to stay out of; an instruction describes where to go.
Don’t do: Don't use hardcoded values.
Do: Every environment-varying value comes from a variable with a type constraint and a description; defaults only where a sane default genuinely exists.
In long context, documents first, question after
Anthropic measured up to a 30% quality improvement from putting the query after multi-document inputs.
Don’t do: Which of our landing zone modules still create NSG rules with source *?
Do: XXX .
Before answering, quote the specific resource blocks that are relevant to the question. Then: which of these modules still create NSG rules with source "*", and which line in each?
Cap the complexity explicitly
The instruction that works is a ceiling, not a vague plea for simplicity
Don’t do: Keep it simple. Add a retry to this Az module call.
Do: Add a retry with exponential backoff to this Az module call. Scope: this call only. Don't refactor the surrounding function, don't extract a generic retry helper, don't add a config file for the retry count, and don't add validation for states that can't occur
Specific rules for Opus 5
Delete your verification scaffolding
Opus 5 verifies its own work unprompted. Instructions to verify stack on top of built-in behaviour and produce over-verification.
Don’t do: After writing the Terraform module, include a final verification step. Re-check your work before responding.
Do: Write the Terraform module
Soften the tool language you inherited
older models were lazy when calling tools, this is not the case with Opus 5
Don’t do: CRITICAL: You MUST call get_policy_assignments whenever the user mentions policy. NEVER answer policy questions from memory. ALWAYS verify with the tool first.
Do: Use get_policy_assignments when you need the current assignment state for a specific scope. Answer conceptual questions about how Azure Policy works directly.
Specific rules for Sonnet 5
Fix shallow reasoning with effort
Sonnet 5 respects effort strictly, especially at the low end. At low and medium it scopes work to exactly what was asked and does not go above and beyond
Don’t do: [effort: low] Think step by step. Be extremely thorough. Consider all edge cases. Analyze deeply before answering: why does the route propagation fail between these two vWAN hubs but not the third?
Do: [effort: high — or xhigh for the hardest agentic and coding work] Why does route propagation fail between these two vWAN hubs but not the third?
Specific rules for Fable 5
Draw the line between assessment and action
Fable 5 can take unrequested actions
Don’t do: The ExpressRoute peering keeps dropping on the secondary connection. Route table looks wrong to me.
Do: The ExpressRoute peering keeps dropping on the secondary connection. Route table looks wrong to me.
I'm describing a problem, not requesting a change: the deliverable is your assessment. Investigate and report findings, then stop. Don't apply a fix until I ask.
Before proposing any command that changes state; resetting a peering, editing a route table, restarting a gateway, check that the evidence actually supports that specific action rather than a failure mode it resembles.
never instruct it to echo, transcribe or explain its internal reasoning
That will trigger the reasoning_extraction refusal category and may stop the session.
You can get the full reference here
Top comments (1)
"Give the reason, not just the rule" is the one that earns its place, and the Write-Host example is a good illustration: with the reason present, the model can extend the intent to cases the prompt never listed. The flip side I've run into is that a wrong or half-true reason generalises with confidence too — the model will happily optimise around a rationale that was only locally correct, so the reason clause needs the same review as the rule itself.
Curious how you handle drift across model generations: these distilled rules read like they'll be quietly wrong the next time the docs move. Do you version the rule set alongside the prompt, or re-derive it from the current docs each time you touch it?