Applied Intelligence
Module 3: Context Engineering

Prompt anti-patterns and smells

The previous lesson cataloged patterns that work. This lesson examines the inverse: anti-patterns that reliably produce poor results, and the warning signs prompt smells that indicate underlying problems before execution.

Understanding these failures matters because iteration rarely rescues a flawed prompt. Research demonstrates that over 95% of successful code implementations occur on the first prompt attempt. When agents fail to produce working code initially, subsequent attempts with additional examples or corrections seldom improve outcomes. The agent struggles to effectively utilize iteratively supplemented requirements. It either understood the task from the start or it did not.

This finding inverts common assumptions about AI interaction. Many developers approach agents expecting to refine toward a solution through back-and-forth dialogue. The evidence suggests otherwise: initial prompt quality determines success. Recognizing anti-patterns before execution prevents wasted iterations on fundamentally flawed requests.

The prompt smell concept

In software development, "code smells" indicate potential problems without being outright bugs characteristics that suggest deeper issues warranting investigation. The same concept applies to prompts.

Prompt smells are semantic or syntactic characteristics that undermine output quality, explainability, or traceability between input and output. A smell does not guarantee failure, but it signals elevated risk.

Three categories of prompt smells emerge from research:

CategoryDescriptionRisk
VaguenessImprecise language fails to convey specific requirementsAgent interprets requirements differently than intended
OvercomplexityElaborate prompts obscure actual intentCannot trace which portion influenced output
Incoherent structureDisconnected prompts lack logical flowResults cannot be mapped to specific requests

Smells indicate problems; anti-patterns are the problems themselves.

Vagueness: the foundational anti-pattern

Vague instructions produce vague results. Research quantifies this: ambiguous task descriptions reduce code generation accuracy by 25-30%, while incomplete specifications cause 20-25% accuracy reduction.

Symptoms of vagueness

Vague prompts typically exhibit one or more of these characteristics:

  • Missing language specification for code generation
  • No function signatures, inputs, or outputs defined
  • Absent data types or expected behavior
  • Unspecified error handling requirements
  • No success criteria

Examples

Vague prompt:

Write a sorting algorithm.

This prompt fails to specify programming language, algorithm type, performance requirements, input constraints, or error handling expectations. The agent must guess at every dimension.

Specific prompt:

Write a Python implementation of merge sort that:
- Takes a list of integers as input
- Returns a new sorted list (does not modify original)
- Handles empty lists by returning empty list
- Raises TypeError for non-list inputs

The specific version constrains the solution space while preserving implementation flexibility.

Research from Microsoft found that prompts with explicit specifications reduced back-and-forth refinements by 68% for straightforward tasks. The upfront investment in specificity eliminates downstream correction cycles.

The specificity balance

Vagueness exists on a spectrum. The previous lesson discussed the specificity-flexibility tradeoff both under-specification and over-specification cause problems. The key distinction: vagueness as an anti-pattern refers to unintentional under-specification, not deliberate flexibility for exploratory tasks.

A prompt exploring architectural options may intentionally leave implementation details open. A prompt requesting a specific function should not leave the programming language unspecified. Match precision to task requirements rather than defaulting to vague requests.

Missing context

Missing context differs from vagueness. Vague prompts lack precision in what they ask for. Context-deficient prompts lack the information needed to answer correctly.

The context gap problem

Agents cannot infer what they do not know. When prompts omit relevant constraints, conventions, or dependencies, agents fill gaps with assumptions assumptions that may contradict project reality.

Context-deficient prompt:

Add validation to the user form.

Context-complete prompt:

Add validation to the user form in src/components/UserForm.tsx.
Follow the existing validation pattern using zod schemas (see src/schemas/addressSchema.ts for example).
Validate email format and require password minimum 8 characters.
Display errors inline below each field using the FormError component.

The second prompt references existing patterns, specifies the validation library, and defines success criteria. The agent has what it needs to produce conformant code.

Context omission causes different failures than vagueness. Vague prompts produce outputs that work but miss requirements. Context-deficient prompts produce outputs that contradict existing patterns, break conventions, or duplicate functionality that already exists.

Common context omissions

Missing ContextTypical Consequence
Existing patterns in codebaseAgent invents new patterns conflicting with established conventions
Technology stack constraintsWrong library or framework assumptions
Error handling requirementsNo error handling or inconsistent approach
Testing expectationsUntested code or wrong test framework
Performance constraintsNaive implementations unsuitable for production

Negative constraints: the pink elephant problem

Negative instructions ("don't do X") are unreliable in LLM prompts. This counter-intuitive finding stems from how language models process text.

Why negative instructions fail

Token generation in LLMs is fundamentally positive selection choosing what token comes next based on probability, not avoiding certain tokens. Negative prompts reduce probabilities of unwanted tokens only slightly, while positive prompts actively boost probabilities of desired outcomes.

Additionally, instructing a model to avoid something requires it to first process that concept. This mirrors the human cognitive phenomenon known as ironic process theory: "don't think of a pink elephant" forces you to think of exactly that. LLMs exhibit similar patterns, making them susceptible to the same ironic suppression effect.

Failure examples

Studies show that LLMs perform worse as more "DO NOTs" accumulate in prompts. Real-world failures include:

  • "NEVER create duplicate files" in CLAUDE.md model still created file-fixed.py and file-correct.py
  • "Do not use markdown in your response" model continued using markdown formatting
  • "Don't use mock data" model continued using mock data

Reframing negative to positive

The solution is reframing prohibitions as positive directions:

Negative InstructionPositive Alternative
"Do not use markdown""Write response as flowing prose paragraphs"
"Don't create helper files""Implement all functionality in existing files"
"Avoid deprecated APIs""Use only current stable API version"
"Don't hard-code values""Implement parameterized logic for all inputs"
"Never output verbose comments""Write concise, professional code comments"

When negative constraints feel unavoidable, pair them with positive alternatives. "Avoid creating new files; instead, add new functions to the existing utils.ts module" combines the prohibition with explicit guidance on what to do instead.

When negatives remain appropriate

Negative instructions serve specific limited purposes:

  • Hard safety boundaries: Preventing genuinely harmful outputs
  • Absolute prohibitions: Where any violation is unacceptable (not preferences)
  • Edge case elimination: After identifying specific recurring problems

Even in these cases, pairing negatives with positive directions improves reliability.

Single-responsibility violations

The overloaded prompt anti-pattern asks agents to accomplish too many things simultaneously.

The overloading problem

Overloaded prompt:

Generate a complete Node.js app with authentication, a front-end in React,
and deployment scripts.

This prompt combines multiple distinct concerns backend development, frontend development, and DevOps each substantial enough for dedicated attention. When forced to address everything at once, agents handle some aspects while neglecting others. The result is incomplete or inconsistent output across all requested features.

The decomposition principle

The previous lesson introduced decomposition patterns. Single-responsibility violations are the anti-pattern those patterns address.

Decomposed approach:

First: Create the Express.js authentication endpoints with JWT handling.
Second: Create React components for login and registration forms
that call the authentication endpoints.
Third: Create Docker configuration and deployment scripts for the application.

Each prompt handles one concern completely before moving to the next.

GitHub Copilot documentation explicitly recommends breaking complex tasks into smaller steps rather than requesting everything at once. A word search puzzle generator, for instance, decomposes into: (1) function to generate letter grid, (2) function to find words in grid, (3) function combining both.

Recognizing overload

Prompts exhibit single-responsibility violations when they:

  • Request multiple unrelated features in one request
  • Mix concerns across different architectural layers
  • Combine creation with modification with deletion
  • Span multiple files across unrelated parts of codebase

Formatting and ambiguity

Structural problems in prompts create interpretation challenges even when content is otherwise clear.

Ambiguous references

Pronouns without clear antecedents force agents to guess at meaning.

AmbiguousClear
"What does this do?""What does the validateUser function in auth.js do?"
"Fix it""Fix the null pointer exception in the login handler at line 47"
"This fix didn't work""The patch from commit abc123 didn't resolve the timeout issue"

In conversation context where files have been discussed, some reference is natural. But within individual prompts especially early in conversations explicit references eliminate guesswork.

Missing output specification

Undefined output format causes inconsistent results that may break downstream integration.

Unspecified:

Explain how the authentication flow works.

Specified:

Explain how the authentication flow works.
Format as numbered steps, each with:
- The action taken
- Which component handles it
- What data is passed

The format specification ensures output structure matches how the information will be used.

Structural best practices

Several techniques improve prompt clarity:

Section headers organize complex requests:

## Context
Current authentication uses session cookies.

## Task
Migrate to JWT-based authentication.

## Constraints
Maintain backward compatibility for 30 days.

Numbered steps sequence multi-part work:

1. Read the existing validation logic in UserValidator.java
2. Identify all validation rules currently implemented
3. Create equivalent validation using ValidationFramework
4. Ensure all existing tests continue to pass

Explicit delimiters separate content from instruction:

The following code has a bug:

```python
def divide(a, b):
    return a / b

Fix the bug by handling the division-by-zero case.


## Context overload

Context overload inverts the missing context problem too much information degrades performance rather than improving it.

### The counterintuitive finding

Research demonstrates that giving agents more context can reduce accuracy from 87% to 54%.
More context is not inherently better.
Models do not use context uniformly; performance grows increasingly unreliable as input length grows.

The "lost in the middle" phenomenon compounds this: LLMs prioritize information at the beginning and end of prompts, underweighting content in the middle.
Dumping large amounts of context buries critical information where it receives less attention.

### Context overload symptoms

| Symptom | Cause |
|---------|-------|
| Agent ignores explicit instructions | Instructions buried in middle of long context |
| Output addresses only some requirements | Model attention exhausted before processing all content |
| Contradictory statements in output | Model accessed conflicting information from different context portions |
| Confident but wrong answers | Model found plausible-seeming context without finding relevant context |

### The signal density principle

Effective prompts optimize for signal density maximum useful information with minimum noise.
This connects to the broader context engineering principle that smaller, high-signal token sets outperform verbose, low-signal alternatives.

Rather than including everything potentially relevant, include only what is necessary for the specific task.
Project context and documentation files handle background information.
Individual prompts should add only task-specific context.

## Combining anti-patterns

Anti-patterns rarely appear in isolation.
A problematic prompt often exhibits multiple issues simultaneously.

**Prompt with combined anti-patterns:**

I was thinking we should maybe add some validation or something to the forms in the app, because sometimes users can enter bad data and things break. Maybe look at how we did it before? But don't use that old library we had problems with. Can you also add tests and update the documentation while you're at it?


This prompt exhibits:
- **Vagueness**: "some validation or something," "bad data," "things break"
- **Missing context**: Which forms? What validation rules?
- **Negative constraint without alternative**: "don't use that old library" without specifying what to use
- **Single-responsibility violation**: Validation, tests, and documentation in one request
- **Ambiguous reference**: "how we did it before" without specification

**Refactored version:**

Add email validation to the UserRegistrationForm component in src/components/.

Requirements:

  • Validate email format using zod (see existing patterns in src/schemas/)
  • Display inline error using FormError component when invalid
  • Prevent form submission while validation errors exist

I will request tests in a separate prompt after implementation.


The refactored version addresses one concern with specific requirements and explicit patterns to follow.

## Recognition checklist

Before submitting a prompt, scan for these warning signs:

| Smell | Question to Ask |
|-------|-----------------|
| Vagueness | Would two developers interpret this identically? |
| Missing context | Does the agent have everything needed to match existing patterns? |
| Negative constraints | Can prohibitions be reframed as positive directions? |
| Overloading | Does this prompt request more than one distinct outcome? |
| Ambiguous references | Are all "this," "that," "it" references explicit? |
| Missing format | Is the expected output structure clear? |
| Context overload | Is everything included actually necessary for this task? |

A "no" to any question signals elevated failure risk.
Addressing smells before execution prevents wasted iterations.

## The 95% rule revisited

This lesson opened with research showing 95% of successful implementations occur on the first attempt.
The anti-patterns examined explain why iteration fails to rescue poor prompts.

Vague prompts leave agents guessing subsequent examples do not change the guess already made.
Missing context cannot be retroactively supplied once the agent has committed to an approach.
Negative constraints already activated the prohibited concept.
Overloaded prompts already produced partial results in wrong directions.

Understanding why iteration fails reinforces the importance of prompt quality.
The patterns from the previous lesson and the anti-patterns from this lesson together form a practical framework for constructing prompts that succeed on the first attempt.

## Summary

Prompt anti-patterns vagueness, missing context, negative constraints, single-responsibility violations, and formatting ambiguity reliably produce poor results.
Prompt smells signal these problems before execution, enabling correction when it is still cheap.

The 95% first-attempt success rate demonstrates that initial prompt quality determines outcomes.
Iteration rarely rescues flawed prompts.
Recognizing anti-patterns and addressing smells before submission prevents wasted cycles and produces better results with less effort.

This lesson concludes the module on context engineering fundamentals.
The next module examines advanced context engineering techniques including long session management, context window mechanics, and multi-turn strategies at scale.

On this page