Ask most people where you do prompt engineering and they'll point at the user message — the question you send the model. For a chatbot that's right. For an agent, it's mostly wrong, and the gap is where a lot of flaky agents come from.
Here's the one-line version: an agent re-reads its system prompt, its tool descriptions, and its output contract on every turn of the loop — and those, not the task sentence, decide what it does. So that's where your prompt engineering effort now belongs.
The prompt moved to the tool descriptions#
When a model runs inside a loop, each turn it looks at the tools available and picks one, then fills in the arguments. It makes that choice from your tool descriptions and parameter docs — the text, not the code behind them. A vague description (query — "runs a query") gives the model nothing to choose on; a precise one tells it the tool's job and when not to reach for it.
That "when not to" line is the single highest-value edit you can make. Most wrong-tool errors aren't the model misunderstanding what a tool does — they're it not knowing which of two similar tools should win. Spell out the boundary:
search_orders — Look up a customer's past orders by email or order ID.
Use this for anything about existing orders (status, refunds, history).
Do NOT use this to place a new order — that's create_order.
Then treat every parameter description as a prompt too, because it is: the model fills arguments from that text alone. Give the format and an example (date: ISO-8601, e.g. "2026-07-30"), not just a type — we go deeper on this in how to write tool descriptions for AI agents. Both Anthropic's guidance on writing tools for agents and OpenAI's function-calling docs converge on the same point: the description is read on every turn, so write it for the model that has to choose — not for the engineer who built the endpoint.
The system prompt sets the frame once#
The system prompt is the one place you pay for a turn and get it applied to all of them. Use it for what's stable across the whole run: the agent's role, its hard constraints, and — easy to forget — its stop conditions, so it knows when it's done instead of looping. Keep it lean. Stuffing it with everything you might need is how you invite context rot: the more low-signal text sits in the window, the worse the model attends to the parts that matter this turn.
A chatbot prompt is a sentence you polish. An agent's prompt is a rack of tool labels and an output form the model reaches for again and again — polish those.
The output contract is what keeps the loop alive#
An agent acts on its own output. If a turn comes back malformed, the loop stalls or does the wrong thing — and it does it unattended. So give the model an output contract: a JSON schema, a required set of fields, a strict format your code can parse without guessing. Enforce it with structured outputs or a validating library, and pair it with clean stop-reason handling. This is the difference between an agent that runs fifty turns and one that derails on turn six.
What to stop doing#
Three habits carry over from chatbot-era prompting and actively hurt in agents:
- "Think step by step" on a reasoning model. It already reasons internally; the instruction duplicates or distorts that and adds latency. Chain-of-thought was a fix for base models — reasoning models moved it inside. Save explicit CoT for the models that still need it.
- A maximalist system prompt. Every token you add is re-read every turn and competes for attention with the live task. Cut it to what's stable and load the rest through retrieval and memory instead.
- Describing tools by their implementation.
pg_query_v2tells the model nothing.search_orderstells it everything. Name and describe tools by their job.
The skills transfer — the surface moved#
None of the classic moves died. Be specific, show examples, use delimiters, put long context before the instruction — they all still work. You just apply them to the system prompt, the tool schema, and the response format instead of to a one-off question. And you apply them inside the bigger job of deciding what occupies the window each turn, which is context engineering, not prompt engineering. If you're wiring the loop yourself, the tool descriptions and the contract are the agent you're building — write them like it.



