Prompt Engineering: Techniques Every Developer Should Know

Prompt Engineering: Techniques Every Developer Should Know

10 min de leitura

If you’re developing with AI in 2026 and still haven’t mastered prompting techniques, you’re leaving 70% of LLM capability on the table. I’m not exaggerating — the difference between a well-structured prompt and a generic one can be the difference between a mediocre response and a production-level solution.

After working on various projects involving LLMs, I’ve noticed that most developers underestimate the power of a good prompt. Let’s change that today.

Why Does Prompt Engineering Matter?

Before we dive into the techniques, understand this: LLMs are pattern-completion machines. They don’t “understand” in the human sense — they’re extraordinarily good at continuing the pattern you started. That’s why how you start that pattern (your prompt) completely determines the quality of the response.

Think of it like declarative programming: you don’t say how to do it, but describe what you want so clearly that the model can infer the correct path.

1. Zero-Shot Prompting: The Foundation

What it is: You simply ask for what you want, without prior examples.

1
Classify the sentiment of this review: "The product is good but delivery was late"

When to use: This technique works well for simple, straightforward tasks, especially with large, modern models like GPT-5+ and Claude 4.5+.

Avoid using it on complex problems or those requiring a specific output format.

Pro tip: Add role context (role prompting):

1
2
3
You are an expert in sentiment analysis for e-commerce.
Classify the sentiment of this review considering the local cultural context:
"The product is good but delivery was late"

This works 3x better than the basic prompt.

2. Few-Shot Prompting: Teach by Example

What it is: As the name says, provide examples before asking for the real task.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Extract structured information from reviews:

Review: "Battery lasts 2 days, excellent camera, but gets hot"
Result: {"battery": "positive", "camera": "positive", "temperature": "negative"}

Review: "Fast and beautiful, but the screen scratches easily"
Result: {"performance": "positive", "design": "positive", "durability": "negative"}

Review: "Perfect for gaming, immersive sound, fast delivery"
Result:

Why it works: You’re establishing the exact pattern you want.

The model learns:

  • The output format (JSON)
  • The level of granularity
  • How to handle mixed aspects

How many examples to give?: About 2-3 for large models and 5-8 for smaller models. Remember, more examples ≠ automatically better (can cause confusion).

3. Chain-of-Thought (CoT): The Technique That Changes Everything

This is, without a doubt, the most impactful technique I’ve discovered. CoT teaches the model to “think out loud.”

Poor prompt:

1
2
Problem: John has 3 apples. Mary has twice John's amount plus 2. Peter has half the total.
How many apples does Peter have?

Prompt with CoT:

1
2
3
4
Problem: John has 3 apples. Mary has twice John's amount plus 2. Peter has half the total.
How many apples does Peter have?

Solve step by step, explaining your reasoning.

Result:

1
2
3
4
5
6
7
1. John has 3 apples
2. Mary has (3 × 2) + 2 = 8 apples
3. Total = 3 + 8 = 11 apples
4. Peter has 11 ÷ 2 = 5.5, but we can't have half an apple

I'll reconsider: "half the total" probably means half of what Mary has.
Peter has 8 ÷ 2 = 4 apples

When to use CoT: This technique shines in mathematical or logical reasoning, code debugging, complex requirements analysis, and in general, any task that benefits from decomposition into smaller steps.

Zero-Shot CoT (the simplest and most powerful version): Simply add at the end: "Let's think step by step"

Seriously. This magic phrase increases accuracy in reasoning problems by up to 40%.

4. Self-Consistency: Multiple Perspectives

The concept: Generate multiple responses with CoT and choose the most common one.

Example in Python (with OpenAI API):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
from collections import Counter

def solve_with_consistency(problem, n=5):
    responses = []
    for _ in range(n):
        response = call_llm(
            f"{problem}\n\nLet's think step by step.",
            temperature=0.7  # Important: temperature > 0 for variation
        )
        # Extract final answer
        responses.append(extract_final_answer(response))
    
    # Majority vote
    return Counter(responses).most_common(1)[0][0]

Trade-off: 5x more API calls, but drastically more reliable for critical decisions.

Real use case: Business rule validation, structured data extraction from contracts, compliance analysis.

5. Generate Knowledge Prompting: Context Before the Question

Make the model generate relevant knowledge before answering.

Naive approach:

1
Why is the sky blue in the afternoon but red at sunset?

With Knowledge Generation:

1
2
3
4
5
First, explain the physical principles of light scattering in the atmosphere.

[Model generates explanation about Rayleigh scattering, wavelengths, etc.]

Now, using that knowledge, explain: why is the sky blue in the afternoon but red at sunset?

The second response is significantly more accurate and detailed because the model “activated” the relevant context.

Practical use in development:

1
2
3
4
5
6
Explain the principles of ACID transactions in databases.

[Model's response...]

Now, analyze this SQL code and identify consistency issues:
[YOUR CODE]

6. Prompt Chaining: Decompose Complex Tasks

Problem: A single prompt trying to do everything results in superficial responses, context loss, and debugging difficulty. The solution is to use a chain of specialized prompts, where each has a clear responsibility.

Example — Code Review Analysis System:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Prompt 1: Extract changes
prompt_1 = """
Analyze this diff and list the main changes:
{diff}
"""

# Prompt 2: Evaluate impact
prompt_2 = """
Based on these changes:
{changes}

Evaluate the impact on:
1. Performance
2. Security
3. Maintainability
"""

# Prompt 3: Suggest improvements
prompt_3 = """
Given these changes and these impacts:
{changes}
{impacts}

Suggest 3 concrete improvements with code examples.
"""

Advantages: Each step is individually verifiable, it’s easy to identify where something went wrong, you can cache intermediate steps to save API calls, and it also allows parallelization when steps are independent.

7. Tree of Thoughts (ToT): Solution Exploration

ToT is like CoT, but with multiple reasoning paths that are evaluated.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
Problem: Optimize this search algorithm

[Model explores 3 approaches]

Approach 1: Hash index
Pros: ...
Cons: ...
Feasibility: 7/10

Approach 2: B+ tree
Pros: ...
Cons: ...
Feasibility: 9/10

Approach 3: In-memory cache
Pros: ...
Cons: ...
Feasibility: 6/10

Justified choice: Approach 2

When to use: Ideal for architectural decisions, problems with multiple valid solutions, and especially when the cost of choosing the wrong implementation is high.

Simple implementation:

1
2
3
4
5
6
7
Generate 3 possible approaches for [PROBLEM].
For each approach, evaluate:
1. Implementation complexity (1-10)
2. Expected performance (1-10)
3. Risk (1-10)

Recommend the best option with justification.

8. ReAct: Reasoning + Action

ReAct combines thinking and action in iterative cycles. It’s the foundation of tools like LangChain Agents.

Pattern:

1
2
3
4
5
Thought: [What I need to do]
Action: [Tool/function to call]
Observation: [Result of the action]
Thought: [What I learned]
...

Real example — API Debugging:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
Thought: I need to find out why the API is returning 500
Action: read_logs(last=50)
Observation: "Database connection timeout at 2026-04-07 10:23:15"

Thought: Database connection issue. I need to check if the DB is accessible
Action: run_command("pg_isready -h db.prod")
Observation: "db.prod:5432 - no response"

Thought: The database isn't responding. I'll check the container status
Action: run_command("docker ps | grep postgres")
Observation: "container postgres-prod exited (1) 2 hours ago"

Thought: The database container crashed. I need to restart it
Action: run_command("docker restart postgres-prod")
Observation: "postgres-prod restarted successfully"

Final Answer: The API was returning 500 because the PostgreSQL container had crashed.
Solution applied: container restart.
Preventive action needed: investigate why the container crashed.

9. RAG (Retrieval Augmented Generation): External Knowledge

The fundamental problem with LLMs: Outdated knowledge limited to training data.

RAG solves this:

  1. Retrieve: Search for relevant information in your database/documents
  2. Augment: Inject that information into the context
  3. Generate: Model responds based on the augmented context

Example — Support System:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def answer_ticket(user_question):
    # 1. Retrieve
    relevant_docs = search_documentation(user_question, top_k=3)
    similar_tickets = search_history(user_question, top_k=2)
    
    # 2. Augment
    context = f"""
    Relevant documentation:
    {relevant_docs}
    
    Similar resolved tickets:
    {similar_tickets}
    
    User's question:
    {user_question}
    """
    
    # 3. Generate
    return llm(f"""
    Based ONLY on the information above, answer the user's question.
    If the information is insufficient, say so explicitly.
    {context}
    """)

Tips for effective RAG:

  • Always instruct to cite sources
  • Instruct to admit when it doesn’t know
  • Use semantic embedding for search (not just keywords)
  • Test different top_k values (3-7 is usually ideal)

10. Meta Prompting: The Model Creates Its Own Prompts

At the most advanced level: You use the LLM to create better prompts.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Your job is to create optimal prompts for data extraction.

Task: Extract information from PDF resumes
Required data: name, email, experience, skills, education

Create a prompt that:
1. Is robust to different resume formats
2. Handles missing information
3. Normalizes data (e.g., dates in different formats)
4. Returns structured JSON

Optimized prompt:

Result: A prompt often better than what you’d write manually.

Automatic iteration:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
def optimize_prompt(initial_prompt, test_cases, n_iterations=3):
    best_prompt = initial_prompt
    best_score = evaluate_prompt(initial_prompt, test_cases)
    
    for i in range(n_iterations):
        optimized_prompt = llm(f"""
        This prompt has score {best_score} out of 100:
        {best_prompt}
        
        Cases where it failed:
        {analyze_failures(best_prompt, test_cases)}
        
        Create an improved version correcting these issues.
        """)
        
        score = evaluate_prompt(optimized_prompt, test_cases)
        if score > best_score:
            best_prompt = optimized_prompt
            best_score = score
    
    return best_prompt

Technique Comparison: When to Use Each One

Technique Complexity Cost (API) Best For Avoid For
Zero-Shot Low Low Simple tasks, large models Specialized tasks
Few-Shot Medium Medium Specific formatting, structured extraction When examples are hard to create
Chain-of-Thought Medium Medium Reasoning, math, logic Purely creative tasks
Self-Consistency High High (5x) Critical decisions, high precision needed Simple tasks, subjective responses
Knowledge Gen Medium Medium Questions needing technical context Direct facts
Prompt Chaining High High Complex pipelines, multi-step processes Atomic tasks
Tree of Thoughts Very High Very High Architectural decisions, multiple solutions Problems with obvious solutions
ReAct High High Agents, automation, debugging Simple questions
RAG High Medium-High Domain-specific knowledge When model knowledge already suffices
Meta Prompting Very High High System optimization, production Rapid prototyping

Universal Principles: What Always Works

Regardless of technique:

1. Be Specific

❌ “Improve this code”
✅ “Refactor this function to reduce cyclomatic complexity below 10, maintaining the same public interface”

2. Provide Context

Always include:

  • Role: “You are a senior data engineer”
  • Objective: “The goal is to migrate this pipeline without downtime”
  • Constraints: “We cannot change the database schema”

3. Define the Format

1
2
3
4
5
6
7
Respond in JSON with the following structure:
{
  "problem": "description",
  "solution": "code",
  "tests": ["test1", "test2"],
  "risks": ["risk1"]
}

4. Show, Don’t Just Tell

Instead of “use best practices,” show:

1
2
3
4
5
Use this code style:
[EXAMPLE OF GOOD CODE]

Avoid this style:
[EXAMPLE OF BAD CODE]

5. Iterate Based on Evidence

  • Test different temperatures (0.1 for consistency, 0.8 for creativity)
  • A/B test prompt variations
  • Measure objectively (don’t rely on intuition)

Conclusion: From Knowledge to Mastery

Knowing these techniques is the first step. Mastery comes from applying the right technique at the right moment.

My recommendation for getting started:

  1. Week 1: Master Zero-Shot and Few-Shot in your real use cases
  2. Week 2: Add Chain-of-Thought whenever there’s reasoning involved
  3. Week 3: Implement Prompt Chaining for your most complex pipeline
  4. Week 4: Experiment with RAG if you have a knowledge base

After that, you’ll be in the top 10% of developers using AI.

And remember: LLMs are tools, not magic. They amplify your expertise, but don’t replace deep understanding of the problem domain.