Define role, constraints, and output format up front. The system prompt is your contract with the model.
response = client.messages.create(
model="claude-sonnet-4-6-20250514",
max_tokens=2048,
system="You are a senior TypeScript developer. Review code for bugs, "
"security issues, and performance. Output as a markdown checklist.",
messages=[{"role": "user", "content": code_to_review}]
)Your Claude Code skills use this pattern — every skill's frontmatter defines the role, trigger conditions, and guardrails before the model sees any task content.
Provide concrete input/output pairs to anchor the model's formatting and reasoning.
- 1-3 examples: formatting, tone, structure tasks
- 5+ examples: classification, labeling, pattern-matching tasks
- Place examples in the system prompt or early in the conversation for cache efficiency
Make reasoning explicit. Two flavors:
- Implicit: "Think step by step before answering"
- Structured: Use XML tags like
<thinking>to separate reasoning from output — lets you parse just the answer while keeping the reasoning for debugging
Ask the model to check its own work before finalizing:
- "Review your answer for factual errors and correct them"
- "Rate your confidence 1-5 and explain any uncertainty"
- Works well as a second pass — generate, then critique, then revise
Break complex tasks into subtasks the model handles independently. This is exactly what your skill system does — a Plan agent decomposes, then specialist skills execute each piece.
"You are an expert X" improves output when domain framing matters (security reviewer, data engineer). Less useful for generic coding tasks where Claude already has strong priors.