Few-Shot Prompting in Practice
AI generated
Claude
>_
Claude AI · Prompt Engineering · Few-Shot Learning
Few-Shot Prompting in Practice
Examples instead of endless instructions

Few-shot prompting uses a handful of concrete input and desired output pairs to teach Claude a format or style more reliably than any instruction, no matter how detailed. This article shows, through code style and commit message examples, how to pick representative examples, cover edge cases, and avoid common mistakes in prompt design.

14 min read In-Context Learning · Example Selection Claude · Claude Code · Anthropic API

1. What few-shot prompting actually does

Few-shot prompting means giving a language model not just a task description, but also a small number of concrete examples of how a given input should be transformed into the desired output. The model picks up the pattern from the examples in context and applies it to new, similar inputs, an effect referred to in research as in-context learning. Unlike fine-tuning, this does not change a single model weight, the pattern only works within the current context window.

For developers this matters because many everyday tasks follow exactly this structure: raw text needs to be turned into a specific format, a function needs to be documented following a fixed schema, a diff needs to become a commit message with a fixed structure. Such tasks can technically also be described through pure instruction, but the description would have to spell out every format rule, every exception, and every stylistic nuance explicitly. Few-shot prompting shifts this work from writing a complete specification to curating a few, but highly informative, examples.

2. Zero-shot, one-shot, and few-shot compared

With zero-shot prompting, the model only receives the task description, no examples. This works well for tasks Claude already knows well from training, such as general summaries or standard translations. For project-specific formats, unusual conventions, or ambiguous style questions, zero-shot often produces usable but inconsistent results, because the model has to fill in the missing details itself, and that interpretation can vary slightly from request to request.

One-shot prompting with exactly one example already reduces this variance considerably, because a concrete pattern serves as an anchor. The risk here: the model can over-generalize properties of that single example, for instance treating a random variable naming convention as a binding rule. Few-shot prompting with typically three to eight examples strikes a balance, enough examples to separate the actual pattern from random detail, but few enough to avoid unnecessarily bloating the context and noticeably slowing down response time.

3. Why examples steer more reliably than instructions

Natural-language instructions such as write concise, idiomatic code are semantically underspecified. What counts as concise depends on the context, the language, and a team's conventions, and the model has to fill that gap with its own, often plausible but not always fitting, assumptions. A concrete example, by contrast, shows the desired result directly, without an abstract rule first having to be translated into concrete form. The model no longer has to interpret, it can interpolate, that is, produce a new result that sits structurally between the shown examples.

A second effect concerns consistency across multiple requests. Because language models do not respond deterministically to the same input, purely instruction-based results scatter more than example-based ones, especially on formatting questions such as indentation, parameter ordering, or docblock structure. Examples act like guardrails that deliberately narrow the model's solution space. This shows up clearly in practice: a team that only instructs Claude to write commits in Conventional Commits format tends to see more format deviations than a team that additionally supplies three real example commits from its own repository.

4. Practical example: teaching consistent code style

A typical scenario from Magento development: every new method should get a complete PHPDoc block with a description, an @param entry for every parameter, and an @return entry, as the project conventions require. A plain instruction to that effect usually works, but details such as the exact phrasing of the description, how optional parameters are handled, or the order of @param and @throws stay inconsistent unless explicitly specified.

Two to three example pairs from real project code pin this pattern down far more reliably. It is important that the examples do not only show the standard case, but also at least one method with an optional parameter and one with a void return type, so the model does not wrongly assume that every method has exactly one required parameter and a return value. The following JSON shows a few-shot set as it could live in a prompt template or a CLAUDE.md file.


{
  "task": "Add a complete PHPDoc block above each public method",
  "examples": [
    {
      "input": "public function getPriceForCustomer(int $productId, int $customerGroupId): float\n{\n    return $this->priceResolver->resolve($productId, $customerGroupId);\n}",
      "output": "/**\n * Resolves the effective price for a product within a customer group.\n *\n * @param int $productId Product entity id.\n * @param int $customerGroupId Customer group id used for tier pricing.\n * @return float Resolved price including applicable customer group rules.\n */\npublic function getPriceForCustomer(int $productId, int $customerGroupId): float\n{\n    return $this->priceResolver->resolve($productId, $customerGroupId);\n}"
    },
    {
      "input": "public function logDeprecationWarning(string $message, ?string $context = null): void\n{\n    $this->logger->warning($message, ['context' => $context]);\n}",
      "output": "/**\n * Logs a deprecation warning with optional context.\n *\n * @param string $message Human readable deprecation message.\n * @param string|null $context Optional context information, null if not applicable.\n * @return void\n */\npublic function logDeprecationWarning(string $message, ?string $context = null): void\n{\n    $this->logger->warning($message, ['context' => $context]);\n}"
    }
  ]
}

5. Practical example: enforcing a commit message format

A second, very common example is automatically formulating commit messages from a git diff. An instruction like use Conventional Commits with type and scope describes the format, but not how granular a team names its scopes, how long the summary line usually is, or whether a body paragraph is expected. These details differ from project to project and are hard to capture fully in text rules without making the prompt unwieldy.

It is more effective to supply three or four real, well-formed commits from the actual git history as examples, chosen so they cover different change types: a feature, a bugfix, and a pure refactor. The following script extracts such example commits automatically from the history and prepares them for a few-shot prompt.


#!/usr/bin/env bash
# collect-commit-examples.sh - extract well-formed commits as few-shot examples
set -euo pipefail

readonly REPO_DIR="${1:-.}"
readonly EXAMPLE_COUNT=4

cd "$REPO_DIR"

# Pick recent commits that already follow the conventional commit pattern
git log --pretty=format:"%H" -n 200 \
  | while read -r hash; do
      subject="$(git log -1 --pretty=%s "$hash")"
      if [[ "$subject" =~ ^(feat|fix|refactor|docs|test)(\([a-z0-9_-]+\))?:\ .+ ]]; then
        echo "$hash"
      fi
    done \
  | head -n "$EXAMPLE_COUNT" \
  | while read -r hash; do
      echo "=== Example commit $hash ==="
      git show --stat --format="%s%n%n%b" "$hash" | head -n 20
      echo
    done

These examples are then appended as a few-shot block in the prompt, followed by the current git diff --staged. In practice this noticeably reduces the amount of rework needed, because Claude no longer has to guess how long a summary line is allowed to be in this particular project, or whether scopes like checkout or catalog are in use, it derives that directly from the examples.

6. Choosing representative examples and covering edge cases

The quality of a few-shot prompt depends almost entirely on the selection of examples, not on their number. Three carefully chosen examples that show different aspects of a task outperform ten nearly identical examples that all cover the same case. A useful rule of thumb: at least one example for the standard case, at least one example for an edge case such as an empty input, an optional parameter, or an exception, and if possible one example that shows what the model should explicitly not do.

A common mistake is that all examples happen to come from the same part of the codebase and therefore share superficial similarities, for instance always the same variable names or always a return type of array. The model can wrongly interpret such coincidences as part of the actual pattern, an effect similar to overfitting in classical machine learning. The order of examples also matters, since models tend to weigh the most recently shown example slightly more heavily. Anyone who wants to emphasize a particular example should therefore place it deliberately at the end of the list, right before the actual request.


# build_fewshot_prompt.py - select diverse examples covering edge cases
from dataclasses import dataclass


@dataclass
class Example:
    label: str
    input_text: str
    output_text: str


def select_representative_examples(pool: list[Example], max_examples: int = 5) -> list[Example]:
    """Pick a diverse subset: standard case, edge cases, and a negative example."""
    required_labels = ["standard", "empty_input", "optional_param", "exception_path"]
    selected: list[Example] = []

    for label in required_labels:
        match = next((ex for ex in pool if ex.label == label), None)
        if match:
            selected.append(match)

    # Fill remaining slots with additional diverse examples, avoiding near-duplicates
    for ex in pool:
        if len(selected) >= max_examples:
            break
        if ex not in selected:
            selected.append(ex)

    return selected[:max_examples]


def render_prompt(task: str, examples: list[Example], new_input: str) -> str:
    blocks = "\n\n".join(
        f"Input:\n{ex.input_text}\n\nOutput:\n{ex.output_text}" for ex in examples
    )
    return f"Task: {task}\n\n{blocks}\n\nInput:\n{new_input}\n\nOutput:"

7. Using few-shot in Claude Code and the Anthropic API

In Claude Code, few-shot examples can be anchored permanently in two ways: directly in the project's CLAUDE.md file, with a short section containing two or three before-and-after examples for code style or commit format, or as a dedicated slash command template that pulls in the right examples on every invocation. The advantage over a plain text instruction in CLAUDE.md: the examples stay stable and reproducible across different sessions, while an abstract rule can be reinterpreted slightly differently in every new conversation. A section like this for commit messages could look like this in the CLAUDE.md file:


## Commit Message Format (Few-Shot Examples)

Example 1:
Input: git diff with a new payment method
Output: feat(checkout): add PayPal Express as payment method

Example 2:
Input: git diff with a bugfix to price calculation
Output: fix(catalog): correct tier price rounding for decimal quantities

Example 3:
Input: git diff with a refactor without behavior change
Output: refactor(customer): extract address validation into service class

When using the Anthropic API directly, few-shot examples are usually passed as alternating user and assistant messages in the messages array, followed by the actual new request as the final user entry. This structure uses the model more efficiently than examples bundled as plain text in a single message, because it matches the actual conversational format the model was trained on.


// build-fewshot-messages.js - construct a few-shot message array for the API
const client = require("@anthropic-ai/sdk");

function buildFewShotMessages(examples, newDiff) {
  const messages = [];

  for (const example of examples) {
    messages.push({ role: "user", content: `Diff:\n${example.diff}\n\nWrite a commit message.` });
    messages.push({ role: "assistant", content: example.commitMessage });
  }

  messages.push({ role: "user", content: `Diff:\n${newDiff}\n\nWrite a commit message.` });
  return messages;
}

async function generateCommitMessage(anthropic, examples, newDiff) {
  const response = await anthropic.messages.create({
    model: "claude-sonnet-4-5",
    max_tokens: 200,
    messages: buildFewShotMessages(examples, newDiff),
  });

  return response.content[0].text;
}

module.exports = { buildFewShotMessages, generateCommitMessage };

8. Limits and risks of few-shot prompting

Few-shot prompting is not a free mechanism. Every example consumes tokens in the context window, which shows up as measurable additional API cost and slightly increased latency for frequently repeated requests. With very long examples, such as entire files instead of short excerpts, the overhead can outweigh the benefit, especially when the prompt already carries a lot of project context. A sensible practice is to keep examples as short as possible but as complete as necessary.

A second risk concerns the quality of the source: if examples come from real but flawed or inconsistent existing code, the model learns those flaws along with the pattern. Examples should therefore be curated rather than pulled blindly from the repository. Third, examples drawn from sensitive code can accidentally carry internal details, customer names, or credentials into the prompt and potentially into logs or a provider's training data, which is why examples should be screened for sensitive content before use. And finally: few-shot improves consistency and format, but it does not replace code review, because a formally correct but logically wrong result often looks more convincing thanks to good examples, not less flawed.

9. Few-shot prompting in direct comparison

The following overview summarizes where plain instructions hit their limits and how a well-built few-shot pattern addresses each weakness directly.

Task Instruction only Few-shot pattern Benefit
Enforcing code style Free text: "write clean code" 2-3 before/after examples Concrete pattern instead of interpretation
Commit messages Instruction: "use Conventional Commits" 3-4 real commits from history Format is reliably adopted
Edge case coverage Happy-path examples only At least one edge case per variant More robust generalization
Number of examples One example for a complex task 3 to 8 diverse examples Reduces overfitting to one pattern
Format guidance Examples without explanatory context Examples plus a short rule summary Combination beats either alone

In practice, the two columns are rarely strictly separate: a short explanatory sentence before the examples helps the model understand the overall goal, while the examples pin down the concrete implementation. Combining both, rather than picking one side, typically produces the most reliable results at a reasonable token cost.

Mironsoft

Claude-powered development workflows for Magento and Hyvä projects

Consistent AI prompts for your dev team?

We help build few-shot prompts, CLAUDE.md conventions, and slash commands so Claude reliably and reproducibly delivers code style, commit messages, and review feedback in your project.

Prompt Audit

Review existing prompts and CLAUDE.md files for consistency and example quality

Few-Shot Libraries

Build representative example sets for code style, commits, and reviews

Claude Code Setup

Set up slash commands and project conventions for reproducible AI workflows

10. Summary

Few-shot prompting solves a fundamental problem of plain instruction prompts: natural language leaves too much room for interpretation on formatting questions, style decisions, and detail rules. Two to eight concrete input and desired-output pairs pin down this pattern far more precisely, because the model can interpolate instead of interpret. The effect is especially visible with code style requirements such as complete PHPDoc blocks and with commit message formats, because both tasks are strongly format-driven and hard to capture completely in text rules.

What matters for quality is not the number of examples but their diversity: at least one standard case, at least one edge case, and where useful a negative example. Anyone who makes this selection deliberately and stores the examples permanently in CLAUDE.md files or prompt templates gets noticeably more consistent results across many requests, but has to budget for extra tokens, maintenance effort, and the risk of overfitting to superficial patterns.

Few-shot prompting in practice, the essentials at a glance

Examples over rules

Concrete input-output pairs pin down format and style more precisely than abstract instructions.

3 to 8 examples

Enough to separate the pattern from randomness, few enough to keep context and cost low.

Diversity over volume

Combine a standard case, an edge case, and a negative example instead of collecting many similar ones.

No substitute for review

Few-shot improves consistency and format, but does not replace substantive review of the result.

11. FAQ: Few-Shot Prompting in Practice

1What exactly is few-shot prompting?
Giving the model several concrete input and desired-output example pairs alongside the task description. The model picks up the pattern in context and applies it to new inputs without changing model weights.
2How many examples does a good few-shot prompt need?
Usually three to eight. Diversity matters more than quantity: a standard case, an edge case, and if possible a negative example beat ten similar examples.
3When is few-shot worth it over zero-shot?
As soon as format or style are project-specific, for example individual commit formats or docblock conventions. For general, already well-handled tasks, zero-shot is often enough.
4How do you choose representative examples?
Standard case plus at least one edge case such as empty input or an exception, and where useful a negative example. Examples should show different aspects, not variations of the same case.
5Can few-shot be combined with system prompts?
Yes, often the most effective combination. System prompt or CLAUDE.md explain the goal, the examples pin down the concrete implementation. Both layers complement each other.
6What is the difference from fine-tuning?
Few-shot only works within the current context window without changing weights. Fine-tuning trains the model permanently on a larger dataset. Few-shot is faster to set up, fine-tuning pays off only with very large datasets.
7How do you avoid overfitting to superficial patterns?
Deliberately diversify examples so random details are not identical across all of them. A counter-example helps when the model picks up a random property shared by several examples.
8Does the order of examples affect the result?
Yes, later examples tend to be weighted slightly more heavily. Place a particularly important example closer to the end of the list.
9How do you store few-shot examples in Claude Code projects?
Most practically in a short CLAUDE.md section or as a slash command template that pulls in examples as needed. This keeps them stable across sessions.
10What does few-shot prompting cost in extra tokens?
Every example consumes tokens in the context window, slightly raising API cost and response time. Short, concise examples keep the overhead manageable.