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?
Top comments (0)