Outcome Prompts vs Vague Prompts: Before-and-After Examples

See how rewriting a vague prompt into an outcome-based prompt transforms AI coding results — with real before-and-after examples you can apply to your next session.

Author:
Codapress Publishing
Date:
19 April 2026

The difference between a session that ships in ten minutes and one that spirals into twenty rounds of back-and-forth often comes down to a single thing: how you asked. Vague prompts leave the model to guess your constraints, preferences, and success criteria. Outcome prompts hand it a spec.

The Anthropic prompt engineering guide makes the same point — specific instructions produce specific results. But the theory only clicks when you see both versions side by side.

What makes a prompt vague?

A vague prompt is not necessarily short. It is any instruction that omits the context the model needs to make good decisions on the first attempt.

Vague promptWhat it is missing
”Build a landing page”Target audience, tone, layout preferences, content sections
”Fix this bug”Error message, expected vs actual behaviour, reproduction steps
”Add validation”Validation rules, user feedback style, edge cases
”Style this button”Colour palette, hover/active states, breakpoint behaviour
”Make it faster”Current bottleneck, target metric, acceptable trade-offs

When a model fills in those blanks itself, it optimises for plausibility rather than your actual requirements. The result is code you have to re-roll or rewrite.

Vague prompts also feel faster in the moment. Typing “build a dashboard” takes five seconds; writing a proper spec takes thirty. That trade-off is deceptive. The vague prompt usually costs you several follow-up messages, each one re-explaining constraints you could have stated once. Outcome prompts front-load that thinking so the model spends tokens on implementation, not interrogation.

How to upgrade a vague prompt in thirty seconds

Before you send anything, run through three questions:

  1. What stack am I in? Name the framework, language version, styling approach, and test runner if they matter.
  2. What should the user see or experience? Describe behaviour, not implementation — loading states, error copy, hover effects, empty states.
  3. What does done look like? Export style, file location, types, tests, or performance targets.

If you cannot answer at least two of those, your prompt is still vague. Paste your draft into the chat and add the missing lines as bullet points. You do not need a perfect spec — you need enough specificity that the model cannot reasonably guess wrong.

Upgrade stepVague versionOutcome version
Name the stack”Add a form""Add a React form with React Hook Form and Zod validation”
Describe behaviour”Handle errors""Show inline field errors below each input; disable submit while loading”
Define done”Make it work""Export from components/ContactForm.tsx; include a Vitest test for invalid email”

This table is a cheat sheet, not a rigid template. The goal is to replace open-ended verbs — “improve”, “clean up”, “fix” — with observable outcomes you can verify in a diff or browser.

Example 1: Building a user profile card

Start with what most developers type into a new chat.

Build a user profile card for me.

The model will produce something — maybe an HTML card with inline styles, maybe a React component with CSS modules. But it cannot know your stack, your design system, or whether you want error states. You will probably get a first draft that misses on all three.

Now the outcome-based version.

Create a responsive user profile card component in React that displays:

- A circular avatar with the user's initials as a fallback if the image URL fails
- The user's display name, bio, and follower count
- A subtle hover effect that raises the card by 2px and adds a shadow

Use Tailwind CSS utility classes only. Export the component as a default export. The card should accept a `user` prop with TypeScript types defined inline.

This version describes the stack (React, Tailwind), the visual behaviour (hover effect, fallback), the interface (prop shape, export style), and the constraints (utility classes only). The model can produce a working component in one shot.

type User = {
  avatarUrl?: string;
  displayName: string;
  bio: string;
  followerCount: number;
};

export default function ProfileCard({ user }: { user: User }) {
  const initials = user.displayName
    .split(" ")
    .map((n) => n[0])
    .join("");

  return (
    <div className="rounded-xl border bg-white p-6 shadow-sm transition-all duration-200 hover:-translate-y-0.5 hover:shadow-md">
      {user.avatarUrl ? (
        <img
          src={user.avatarUrl}
          alt={user.displayName}
          className="h-16 w-16 rounded-full object-cover"
          onError={(e) => {
            (e.target as HTMLImageElement).style.display = "none";
          }}
        />
      ) : null}
      {!user.avatarUrl && (
        <div className="flex h-16 w-16 items-center justify-center rounded-full bg-blue-100 text-lg font-semibold text-blue-700">
          {initials}
        </div>
      )}
      <h3 className="mt-4 text-lg font-semibold">{user.displayName}</h3>
      <p className="mt-1 text-sm text-gray-600">{user.bio}</p>
      <p className="mt-2 text-xs text-gray-400">{user.followerCount} followers</p>
    </div>
  );
}

The vague version would have required at least two follow-ups to pin down stack and fallback behaviour. The outcome version produced the finished component in a single pass.

Notice what the outcome prompt did not do: it did not prescribe every CSS class or dictate the exact DOM structure. It specified constraints (Tailwind only, default export, inline types) and acceptance criteria (initials fallback, hover lift). That balance — enough detail to steer, not so much that you are writing the code yourself — is what separates useful outcome prompts from micromanagement.

Example 2: Debugging an API integration

Vague debugging prompts are the most common source of wasted token budget.

Why is my API call not working?

The model has no error message, no endpoint, no context. It will ask clarifying questions — each one costing you a round trip and tokens.

An outcome prompt for the same scenario.

I am calling the GitHub API to fetch a user's public repos, but the request returns a 403.

Endpoint: GET https://api.github.com/users/octocat/repos
Headers: { "Accept": "application/vnd.github.v3+json" }
Response body: { "message": "API rate limit exceeded", "documentation_url": "..." }

I need this to work without authentication for unauthenticated public access. If that is not possible, tell me the minimum auth scope required. Provide the corrected fetch call with error handling for both 403 and 429 responses.

The model now has everything it needs: the exact endpoint, the response it received, and a clear goal. It can tell you that unauthenticated requests to GitHub are rate-limited to 60 per hour, suggest adding a User-Agent header as a first step, or recommend a personal access token with the public_repo scope.

ApproachRounds to resolutionTokens spent on clarifying questions
Vague prompt3–5High
Outcome prompt1–2Minimal

Example 3: Refactoring a React component

Refactoring prompts benefit from the same treatment. Compare these two.

Refactor this component to be cleaner.

The model does not know what “cleaner” means to you — fewer lines, better separation of concerns, better TypeScript types, or all of the above.

Refactor this React component to split the data fetching logic into a custom hook called `useDashboardData`.

Requirements:
- The hook should return `{ data, isLoading, error }` with proper TypeScript types
- The component should only handle rendering and pass event handlers up
- Preserve the existing loading spinner and error state UI
- Do not add external dependencies

Here is the current component:

The difference is night and day. The outcome prompt defines the interface (useDashboardData with its return shape), the architectural boundary (component handles rendering only), and what to preserve (existing UI states). The model can produce the hook and the refactored component in a single response, ready to review.

Refactoring is where vague language hurts most. Words like “cleaner”, “better”, or “more maintainable” mean different things to every developer. An outcome prompt replaces taste with testable boundaries: this hook name, this return shape, these UI states preserved, no new dependencies. The model still chooses how to split files and name internal helpers — you are governing the contract, not the implementation.

When outcome prompts still need a follow-up

Outcome prompts reduce back-and-forth; they do not eliminate it. You may still need a second message if the model misread a constraint, if your codebase has patterns the model could not see, or if you discover an edge case mid-review. That is normal. The difference is that follow-ups become surgical — “the retry logic should cap at three attempts” — rather than foundational — “actually we use TypeScript, not JavaScript”.

Treat your first prompt as a brief for a contractor. Assume they are competent but have never opened your repository. Give them the stack, the spec, and the definition of done. Save the fine-tuning for round two once you have something concrete to react to.

The anatomy of an outcome prompt

Every outcome prompt contains the same six ingredients. Use them as a checklist before you press enter.

IngredientWhat it looks like
Stack or platformReact + Tailwind, Python 3.12, vanilla JS with no frameworks
Behavioural spec”Show initials when the image fails”, “retry on 5xx with exponential backoff”
Interface contractProp types, function signatures, return shapes
Constraints”No external dependencies”, “must work offline”, “keep it under 200 lines”
Acceptance criteria”The card lifts 2px on hover”, “tests pass with Jest”, “runs in under 100ms”
Context where it mattersError messages, current code, existing patterns to match

If your prompt is missing three or more of these, it is probably a vague prompt that will cost you extra rounds.

Keep a snippet of your best outcome prompts in a notes file or team wiki. Prompt patterns repeat across projects — auth flows, form validation, API wrappers — and a reusable template beats improvising from scratch every session.

Put it into practice

Next time you open a chat, spend thirty seconds upfront writing an outcome prompt. Specify the stack, the behaviour, the edge cases, and what “done” looks like. The model will return code that is closer to shippable on the first pass — and you will keep your flow instead of fighting the tool.

For a deeper walkthrough of prompt patterns, see The AI Coding Prompt Playbook. If you are newer to AI coding, A Simple Guide to AI Coding covers the fundamentals of writing outcome-based instructions from the ground up.

More insights

All Articles