A perfect memory system can't save an agent that doesn't know when to reach for the tool sitting right in front of it. Prompt engineering for an agent differs from prompting a chatbot in one key way: the system prompt is re-read fresh on every single step of a loop, not judged once.
This post continues my series on building agents. The previous one covered short-term vs long-term memory.
Why vagueness compounds in an agent prompt
A vague instruction in a one-shot prompt costs one bad answer. The same vagueness in an agent's system prompt costs one bad decision per step, and across a long conversation that adds up instead of averaging out — the same ambiguous text, reread with the same risk, every single time.
The five sections
- Role — one or two sentences, not a biography.
- Tools, and exactly when to use each — "use this whenever X," not just a capability list.
- Boundaries — what it must never do: invent data, act irreversibly without confirmation, go outside its given tools.
- Handling uncertainty — ask, guess, or escalate, picked explicitly.
- What "done" looks like — an explicit stopping condition.
Tool descriptions are prompts too
Going back through this series' actual code: add_expense has "Use it whenever the user says they spent money" — real trigger phrase, doing real work. get_total, from the same file, has no trigger phrase at all, and gets away with it only because nothing else in that toolset sounds like "total." The rule isn't "always add a trigger" as a blanket mandate — it's that the less distinguishable a tool's name is from its neighbors, the more the description has to do.
A structured prompt, and a way to check it
// agent/prompt-template.ts const SYSTEM_PROMPT = ` You are an expense-tracking assistant for a single user. ## Role Record expenses the user mentions and answer questions about what they've spent. You do not give financial advice. ## Tools and when to use them - add_expense: use this whenever the user states they spent money on something. - get_total: use this whenever the user asks for a total, a sum, or how much they've spent overall — not for a single expense or an average. - save_note: use this whenever the user states a lasting preference or constraint, not a one-off detail about today. ## Boundaries - Never invent an expense, a total, or a saved note the tools did not actually return. - Never delete or change a past expense unless the user explicitly asks to. ## When you're not sure If a message could mean more than one thing (for example, an amount with no stated purpose), ask one short clarifying question instead of guessing which tool to call. ## When you're done Once every expense or note the user mentioned has been recorded and any question has been answered, reply in plain text with no further tool calls. `.trim(); function hasTriggerPhrase(description: string): boolean { return /\buse (this|it) whenever\b/i.test(description); } const toolDescriptions: Record<string, string> = { add_expense: 'Record one expense. Use it whenever the user says they spent money.', get_total_before: 'Return the exact total of all recorded expenses in BDT.', get_total_after: "Return the exact sum of every expense recorded so far, in BDT. Use this whenever the user asks for a total, a sum, or how much they've spent overall — not for a single expense or an average.", }; for (const [name, description] of Object.entries(toolDescriptions)) { console.log(name, '->', hasTriggerPhrase(description) ? 'has trigger phrase' : 'MISSING trigger phrase'); } console.log('\n--- system prompt preview ---'); console.log(SYSTEM_PROMPT); Running the checker against the real get_total description and its rewrite shows the gap directly: the original fails, the rewrite passes, with no need to guess how a real model would respond to either one.
Common mistakes
- Treating the system prompt as one block of advice instead of distinct sections.
- Writing tool descriptions in isolation instead of reviewing them together.
- No explicit stopping condition.
- Padding the prompt with generic advice that doesn't change behavior.
Read the full version
I write each post in English and Bangla. The full version is on my blog: How to Write a Good Prompt for an AI Agent
Has a vague tool description ever made your agent guess wrong?

