Prompt Engineering Pattern
Craft effective prompts for reliable, high-quality AI outputs with structured responses and consistent behavior.
Overview#
Prompt engineering is the practice of designing inputs to AI models that produce desired outputs reliably. Well-crafted prompts reduce errors, improve consistency, and enable complex behaviors.
When to use:
- Any AI-powered feature
- Structured data extraction
- Content generation
- Classification tasks
- Complex reasoning tasks
Key features:
- System prompt design
- Output format specification
- Few-shot examples
- Chain-of-thought reasoning
- Structured output with schemas
Code Example#
System Prompt Design#
1// lib/ai/prompts.ts
2export const systemPrompts = {
3 // Clear role and constraints
4 assistant: `You are a helpful customer support assistant for Acme Inc.
5Your role is to help customers with product questions and issues.
6
7Guidelines:
8- Be friendly and professional
9- Only discuss Acme products and services
10- If you don't know something, say so
11- Never make up product features or prices
12- Suggest contacting support for complex issues`,
13
14 // Technical assistant with specific format
15 codeReviewer: `You are an expert code reviewer.
16Review code for:
17- Bugs and potential errors
18- Security vulnerabilities
19- Performance issues
20- Code style and readability
21
22Format your response as:
23## Summary
24Brief overview of the code quality
25
26## Issues Found
27List each issue with severity (Critical/Warning/Info)
28
29## Suggestions
30Specific improvements with code examples`,
31
32 // Data extraction with schema
33 entityExtractor: `You are a data extraction system.
34Extract structured information from text.
35Always return valid JSON matching the requested schema.
36If information is not present, use null.
37Never add fields not in the schema.`
38}Structured Output with Zod#
1// lib/ai/structured.ts
2import { anthropic } from '@/lib/anthropic'
3import { z } from 'zod'
4
5const ProductSchema = z.object({
6 name: z.string(),
7 description: z.string(),
8 price: z.number(),
9 category: z.string()
10})
11
12export async function extractProduct(text: string) {
13 const response = await anthropic.messages.create({
14 model: 'claude-sonnet-4-20250514',
15 max_tokens: 1024,
16 system: `Extract product information and return as JSON.
17Return only the JSON object, no other text.`,
18 messages: [
19 {
20 role: 'user',
21 content: `Extract product information from this text:
22
23${text}
24
25Return JSON with: name, description, price (number), category`
26 }
27 ]
28 })
29
30 const content = response.content[0]
31 if (content.type !== 'text') throw new Error('Unexpected response')
32
33 const jsonMatch = content.text.match(/\{[\s\S]*\}/)
34 if (!jsonMatch) throw new Error('No JSON found')
35
36 const parsed = JSON.parse(jsonMatch[0])
37 return ProductSchema.parse(parsed)
38}Few-Shot Examples#
1// lib/ai/classification.ts
2import { anthropic } from '@/lib/anthropic'
3
4const CATEGORIES = ['bug', 'feature', 'question', 'docs'] as const
5
6export async function classifyIssue(
7 title: string,
8 body: string
9): Promise<typeof CATEGORIES[number]> {
10 const response = await anthropic.messages.create({
11 model: 'claude-sonnet-4-20250514',
12 max_tokens: 50,
13 messages: [
14 {
15 role: 'user',
16 content: `Classify GitHub issues. Categories: bug, feature, question, docs
17
18Examples:
19Title: "App crashes on login"
20Body: "When I try to log in, the app crashes"
21Category: bug
22
23Title: "Add dark mode support"
24Body: "It would be great to have a dark theme option"
25Category: feature
26
27Title: "How do I reset my password?"
28Body: "I forgot my password and can't find reset option"
29Category: question
30
31Title: "Fix typo in README"
32Body: "Line 42 says 'teh' instead of 'the'"
33Category: docs
34
35Now classify:
36Title: "${title}"
37Body: "${body}"
38Category:`
39 }
40 ]
41 })
42
43 const text = response.content[0].type === 'text'
44 ? response.content[0].text.trim().toLowerCase()
45 : ''
46
47 if (CATEGORIES.includes(text as any)) {
48 return text as typeof CATEGORIES[number]
49 }
50
51 return 'question' // default
52}Chain-of-Thought Reasoning#
1// lib/ai/reasoning.ts
2import { anthropic } from '@/lib/anthropic'
3
4export async function analyzeWithReasoning(problem: string) {
5 const response = await anthropic.messages.create({
6 model: 'claude-sonnet-4-20250514',
7 max_tokens: 2048,
8 system: `You are an analytical assistant.
9When solving problems, think step by step:
101. First, understand what is being asked
112. Break down the problem into parts
123. Analyze each part
134. Synthesize your findings
145. Provide a clear conclusion
15
16Format:
17## Understanding
18What the problem is asking
19
20## Analysis
21Step-by-step reasoning
22
23## Conclusion
24Final answer with confidence level`,
25 messages: [
26 { role: 'user', content: problem }
27 ]
28 })
29
30 return response.content[0].type === 'text'
31 ? response.content[0].text
32 : null
33}Entity Extraction#
1// lib/ai/extract.ts
2import { anthropic } from '@/lib/anthropic'
3import { z } from 'zod'
4
5const EntitiesSchema = z.object({
6 people: z.array(z.string()),
7 organizations: z.array(z.string()),
8 locations: z.array(z.string()),
9 dates: z.array(z.string())
10})
11
12export async function extractEntities(text: string) {
13 const response = await anthropic.messages.create({
14 model: 'claude-sonnet-4-20250514',
15 max_tokens: 1024,
16 system: `Extract named entities from text.
17Return a JSON object with arrays for: people, organizations, locations, dates.
18Use empty arrays if no entities found for a category.`,
19 messages: [
20 {
21 role: 'user',
22 content: `Extract named entities from:
23
24${text}
25
26Return only the JSON object.`
27 }
28 ]
29 })
30
31 const content = response.content[0]
32 if (content.type !== 'text') throw new Error('Unexpected response')
33
34 const jsonMatch = content.text.match(/\{[\s\S]*\}/)
35 if (!jsonMatch) throw new Error('No JSON found')
36
37 return EntitiesSchema.parse(JSON.parse(jsonMatch[0]))
38}Conversation Context Management#
1// lib/ai/conversation.ts
2import { anthropic } from '@/lib/anthropic'
3
4interface Message {
5 role: 'user' | 'assistant'
6 content: string
7}
8
9export async function chat(
10 messages: Message[],
11 systemPrompt: string
12) {
13 // Keep conversation within token limits
14 const recentMessages = messages.slice(-10)
15
16 // Add context summary for long conversations
17 let contextSummary = ''
18 if (messages.length > 10) {
19 contextSummary = `Previous conversation summary: ${await summarizeConversation(messages.slice(0, -10))}\n\n`
20 }
21
22 const response = await anthropic.messages.create({
23 model: 'claude-sonnet-4-20250514',
24 max_tokens: 1024,
25 system: systemPrompt + (contextSummary ? `\n\n${contextSummary}` : ''),
26 messages: recentMessages
27 })
28
29 return response.content[0].type === 'text'
30 ? response.content[0].text
31 : null
32}
33
34async function summarizeConversation(messages: Message[]): Promise<string> {
35 const response = await anthropic.messages.create({
36 model: 'claude-sonnet-4-20250514',
37 max_tokens: 200,
38 messages: [
39 {
40 role: 'user',
41 content: `Summarize this conversation in 2-3 sentences:
42
43${messages.map(m => `${m.role}: ${m.content}`).join('\n')}`
44 }
45 ]
46 })
47
48 return response.content[0].type === 'text'
49 ? response.content[0].text
50 : ''
51}Usage Instructions#
- Define clear roles - Start system prompts with the AI's role and purpose
- Set constraints - Explicitly state what the AI should and shouldn't do
- Specify output format - Tell the AI exactly how to structure responses
- Use examples - Provide few-shot examples for complex tasks
- Validate outputs - Parse and validate structured responses with Zod
Best Practices#
- Be specific - Vague prompts produce vague results
- Show, don't just tell - Include examples of desired outputs
- Separate concerns - Use system prompt for behavior, user message for task
- Handle edge cases - Tell the AI what to do when uncertain
- Iterate and test - Refine prompts based on real outputs
- Version your prompts - Track changes to important prompts
- Use structured output - Request JSON for data extraction
- Set constraints early - Put important rules at the beginning
Related Patterns#
- Claude API - Basic Claude integration
- Function Calling - Tool use patterns
- Streaming - Real-time responses