Book a call
LESSON14mVERIFIED 2026-08-02 · CLAUDE CODE 2.1.193 · CODEX CLI 0.146.0

Why agent prompting isn't chat prompting

In chat, a vague prompt costs you a mediocre paragraph. In an agent, we measured the same vagueness costing a 120-line diff across three files nobody asked it to touch.

The habits that transfer are the ones that hurt

The thing is, that most of the skills you have acquired during a few years of using chat are still very useful. Especially:

  • Saying things clearly

  • Providing examples

  • Saying what format you want the output to have

The thing is that they're not chatbots, so the price is different. In chat, if you ask sth, you get a text back which you can read and take what's useful from, but also ignore what's not. It costs you a mediocre paragraph and 15 seconds of a developer's time, which is really cheap, so in a lot of cases it makes sense to ask and see what it says, so people have a reflex to do it. But here, if you ask sth, the bot already runs a few tool commands before you can even see its summary.

As the Anthropic docs say, unlike a chatbot that answers questions and waits, Claude Code "can read your files, run commands, make changes, and autonomously work through problems while you watch, redirect, or step away entirely." The same vagueness, different prices, so let's have a look:

The same task, two prompts

We created a little Python project (receipt parser — two modules, README, and check.sh with two asserts), ran Claude Code 2.1.193 on it, and gave it these two prompts in two identical copies of the repo:

Prompt A (the typical one):

TEXT
make the error handling better

Prompt B (the same ask, with a location, a boundary and a check):

TEXT
In app/parse.py, parse_line raises KeyError when a record's currency code is not in
CURRENCIES. Make it fall back to the raw code as the symbol instead of raising, and add
one case to tests/check.py that covers it. Do not change app/api.py. Then run ./check.sh
and paste its output.

And these are the results we got (same model, same project, same day), for vague vs specific:

PromptTurnsTimeCostSource filesLines
A1176s$0.433+120/-10
B828s$0.252+3/-2

The money difference is obvious, but not that interesting; the code difference is much more instructive:

The prompt A got Claude to:

  • Create a new public ParseError class which is an exception, extending ValueError

  • Rewrite app/api.py in a way that handles this error, and inline one previously imported function

  • Add a few isinstance checks to 3 of the 4 functions in both files

  • Replace raw.split(" ") with raw.split() in app/parse.py, and add a line comment saying that OCR often returns lines padded with spaces

  • Expand the tests/check.py file from 2 asserts to 7

All these changes are reasonable — this is what's worth thinking about. Every one of them is defensible, several are genuine improvements, and expanding the tests is arguably sth a good developer would have done anyway.

So what we get from the prompt A is a new public exception in the API, changed behaviour of the parser, and 120 lines to review. From 5 words.

The prompt B is just that prompt A with three things bolted on — a where, a how far, and a done. We come back to those in a minute.

If you were to ask about the same thing in a chat, you'd get a paragraph with advices you'd probably skim through and ignore. But why is that? It's not like the model would be more keen to help here. It's what the harness tells it to do. Let's explore this:

Your prompt is a spec, not a question

Codex CLI ships its model instruction inside the binary. We pulled it out of the 0.146.0 build with strings, and this is what it contains:

TEXT
Unless the user explicitly asks for a plan, asks a question about the code, is
brainstorming potential solutions, or some other intent that makes it clear that code
should not be written, assume the user wants you to make code changes or run tools to
solve the user's problem. In these cases, it's bad to output your proposed solution in a
message, you should go ahead and actually implement the change.

As we said, Codex is just the one we could read it out of. Every tool needs to have its own stance towards the ambiguous input, and the stance that assumes conversation in these cases would be totally useless — as far as we know, they all choose the same default: code by default.

So in other words, the bot reads your message and thinks "that's what we're gonna do". If you wanted to ask a question, you could've said so. It's not like you didn't have an opportunity. If you wrote a sentence, it was an order. This:

"Can we improve the error handling?"

Is not:

"I'm wondering if we can improve the error handling, what do you think?"

It's:

"Let's improve the error handling"

A chat prompt is basically a question you work out together over a few turns. An agent prompt is a ticket you give to a competent person who starts working on it without asking and settles every ambiguity on their own, filling in sensible defaults — not the ones you would have chosen.

Let's have a look at a few habits that work well with chatbots but might not be so effective here:

The chat habits that break

Habit 1: Asking for alternatives

  • Good in chat — you can always ask for different solutions and pick one, no harm done

  • Here, it's not clear what you mean by "alternatives" — three descriptions, or one implementation and two paragraphs about the others? If you're looking for a plan rather than code, just say so in the prompt. The Cursor CLI docs use exactly this as their example: "you can use the prompt 'do not write any code' to ensure that the agent won't edit any files."

  • Better still, use the mode built for it — that's what plan mode is, and it gets its own lesson at the end of this chapter

Habit 2: Saying it again, more emphatically

  • With chatbots, if you feel like the bot didn't understand sth, saying it again but louder usually works — it's just a text-generation problem

  • Here, it's different. The bot probably wasn't ignoring you; it had probably formed an assumption at some point and acts on it from now on without checking with you again. What you need here is a different move — that's the Repair prompts lesson in this chapter

  • Except for one thing: as you can see in the Anthropic docs, emphasis really works in the persistent instruction file. On CLAUDE.md they say "you can tune instructions by adding emphasis (e.g., 'IMPORTANT' or 'YOU MUST') to improve adherence"

  • But that's a different thing than shouting at some point during the session — they describe CLAUDE.md as "a special file that Claude reads at the start of every conversation", so it's sth like a standing instruction that's there before the session forms any views

  • Saying it louder on turn 9 doesn't change the fact that it formed a view on turn 4 and still holds it

Habit 3: Asking the same question again to get a different answer

  • If you don't like what the bot says in chat, you can just click "try again". Here, the previous turn already wrote to your disk. There is an undo, but it's worth knowing exactly what yours covers before you rely on it:

  • Anthropic's own caveat on it: "Checkpoints only track changes made through Claude's file editing tools. Changes made through Bash commands or external processes are not captured. This isn't a replacement for git."

  • So basically, if your session ran some script, there's a part of undo history that's missing

Habit 4: Pasting code in

  • In chat, you just copy and paste. Here, it's an option; the bot can open the file itself.

  • In a separate test we gave it nothing but a path, and it read the file once and answered, so this is definitely sth you could ask it to do. Just remember that pasting comes with its own costs — that's its own lesson later in this chapter

Habit 5: Thinking in messages instead of turns

  • In chat, you ask a question and get an answer back. Here, a single prompt can run ten tool calls — that's what our vague run did — and the thing you end up having on your disk is the turn, not the message

  • So just ask for one reviewable thing per turn

  • Anthropic names the opposite as a failure pattern in its own right: "The kitchen sink session. You start with one task, then ask Claude something unrelated, then go back to the first task. Context is full of irrelevant information."

Habit 6: Treating context as free

  • In chat, threads aren't long enough for it to really matter. Here, the bot reads files and runs commands faster than you can count them, and:

  • Anthropic states the consequence plainly: "LLM performance degrades as context fills."

What a chat prompt is missing

These are the three things a chat prompt doesn't have:

  • Where — file, directory, or symbol. If you don't tell it where to work, it will choose the blast radius on its own, and will be really generous (three files in our tests)

  • How far — what's not to change, as a sentence. "Do not change app/api.py" is sth a reviewer can check; "Keep it focused" isn't

  • Done — a command you can run which returns pass or fail. Otherwise the only way for it to know it's done is for it to "look like it", and it's the model that decides if it does. That one is the subject of the next lesson

Prompt B is nothing more than prompt A plus those three. It's not better writing; it's the same request with the parts a spec needs. Here's the conversion on prompts people actually type:

Rewrite one prompt you'd type today

"Fix the flaky test"

  • No where

  • No how far

  • No done

The bot will go looking for both the test and the cause, so "where" is exactly the decision you've handed over.

Rewrite:

Identify tests/test_sync.py::test_retries as failing randomly every fifth run on the last assertion, about timing; make sure it doesn't increase the timeout to force a pass, don't modify files outside of tests/ folder, and show me the failure before proposing any solution

"Let's add some caching in the API layer"

  • No where

  • No how far

  • No done

Caching naturally leads to creating config file and dependency, and decorating everything.

Rewrite:

In-process cache in get_rates() in app/rates.py, keyed on (source, target, day), no dependencies, no new config file, ./check.sh still passes, making sure that if you run it with the same arguments twice, it doesn't reach RATE_TABLE again (with one more assertion just for that)

"Let's tidy this file"

  • No where

  • No how far

  • No done

It's genuinely ambiguous, and it's the one where a plan beats a better prompt. At this point you don't know what you want yet, so asking it to write first is the wrong order.

Rewrite:

Read app/parse.py and list changes you'd make with rationale, from the worst one, without modifying anything

As you can see, in the last case we didn't get more specific about the work at all — we got specific about the output, asking for a list instead of a diff. That's the other lever you have, and it's the one people forget they're allowed to pull.

When vague is still the right move

Just keep in mind that sometimes it's okay to leave sth vague. If you're gonna write a long prompt, know that it costs sth; specificity is not a virtue you should be showing off with. The reason we aim for being specific is not that being vague is irresponsible, but that correcting things here is expensive.

If it's cheap — like when you haven't written anything yet, are just exploring, and genuinely don't know what you want — it's okay to leave it a bit vague. Anthropic says as much in their docs:

Vague prompts can be useful when you're exploring and can afford to course-correct. A prompt like "what would you improve in this file?" can surface things you wouldn't have thought to ask about.

So not "be specific" — "determine which mode you're in and use a tool for it":

  • Exploring — place the agent somewhere it can't write, and ask an open question

  • Shipping — spend this extra sentence on where, how far, and done, before the turn, not after the diff

j / k to move between lessons