Prompt Engineering for Agents
Prompt engineering for an agent's system prompt and tool descriptions differs from prompting a chatbot -- it has to hold up across many unattended steps, not just one reply.
Learning objectives
- Apply four core prompt-engineering techniques specifically to agent system prompts
- Write a tool description that disambiguates when to use it versus similar tools
- Recognize why agent prompts need one extra ingredient chatbot prompts don't: explicit stopping guidance
ToolDix original visual
Frame
Name the outcome and constraints.
Build
Try one bounded workflow.
Review
Keep evidence, revise, and share.
Why agent prompts are a different problem
A chatbot's system prompt only has to hold up for one reply. An agent's system prompt has to hold up across every step of a run it hasn't happened yet -- it needs to anticipate tool failures, ambiguous intermediate results, and the question of when to stop, none of which a single-turn chatbot prompt has to address.
A chatbot prompt can say "if the user's question is unclear, ask for clarification." The chatbot replies once and exits.
An agent prompt must answer: "If a tool result is ambiguous, should I retry with different arguments? Retrieve different data? Move forward with what I have? Call a different tool? And how do I know when I've gathered enough information to answer the original question and should stop?"
These decisions happen dozens of times in a long-running agent without human intervention. The system prompt has to address all of them.
Four techniques that carry over, applied to agents
Technique 1: Be explicit about the goal and the definition of done
"Research this topic" is weaker than "Research this topic and produce a three-paragraph summary citing at least two sources; stop once you have that." The second version gives the model a concrete way to check whether it's finished. Without a definition of done, agents either:
- Stop too early ("I found one source, I'm done")
- Loop forever ("I have two sources... but maybe one more would help... maybe two more...")
- Misunderstand what "done" means in a different context on a different run
The best goal statements are checkable: the model can verify whether the task is complete without human judgment. "Analyze the market trends" is not checkable. "Retrieve data on three competitors' prices and summarize whether prices went up or down in the last quarter" is.
Technique 2: Give examples of the tool-use pattern you want
Don't just list tools. Show a worked example: "The user might ask 'What's the weather in Boston?' You would: 1) Recognize that weather is time-sensitive. 2) Call the get_weather tool with location='Boston'. 3) Read the result, which contains temp, conditions, and forecast. 4) Summarize it for the user: 'It's 68F and partly cloudy in Boston right now.'"
This pattern-teaching approach is more effective than a tool list because it shows:
- When to use the tool (time-sensitive queries)
- How to parse its result (it returns temp, conditions, forecast)
- What to do with the result (summarize it for the user, not just repeat it verbatim)
Most models learn tool-use patterns better from examples than from abstract descriptions.
Technique 3: Separate constraints from goals
State what the agent must never do (e.g. "never delete a file without asking first") as its own clearly labeled section, distinct from the goal. Mixing them causes problems:
Bad:
You are a file management assistant. Your goal is to help users organize their files,
clean up duplicates, and never delete files without asking first. You should also handle
large directories efficiently...
Good:
GOAL: Help users organize files and remove duplicates.
CONSTRAINTS: You must:
- Never delete a file without explicit user approval
- Never modify files outside the specified directory
- Never access files in system directories (~/bin, /usr/bin, etc.)
The good version makes it clear what you're trying to do versus what you must never do. Models weight constraints more carefully when they're separated.
Technique 4: Ask for reasoning before action on ambiguous steps
On ambiguous inputs, prompt the model to state its reasoning before choosing a tool. This is a lightweight chain-of-thought:
Before calling a tool, briefly state which tool you'll use and why.
For example: "Thought: The user wants current weather, which requires
the get_weather tool, not historical climate data."
This measurably improves tool selection accuracy on ambiguous queries, at the cost of ~50-100 extra tokens per step. It's most valuable on agents with many similar tools or specialized domains where wrong tool choices are expensive.
Example: a weak vs. a stronger tool description
Weak tool description:
search(query): searches the web
Stronger tool description:
search(query: string) -> list of {title, url, snippet}
Use this tool when you need:
- Current information updated after your training data cutoff
- Verification of specific facts or recent events
- Data you don't have in context already
Do NOT use this for:
- Simple arithmetic or logic problems (compute these yourself)
- Questions already answered earlier in this conversation
- Trivial factual lookups where you're confident in your training data
Return format: list of up to 5 results in {title, url, snippet} format.
- If 0 results are relevant, say so rather than guessing or making up sources.
- If results are inconclusive, try a refined query rather than using
the first partial result.
The stronger version specifies:
- The return shape (list of dicts with title/url/snippet) -- so the model knows what to expect
- When to use it (current info, verification, new data) -- reduces false positives
- When NOT to use it (logic problems, already-known facts) -- prevents wasted calls
- Edge cases (empty results, inconclusive results) -- tells the model how to recover
Models that read this description make better tool-choice decisions than those that only see the function signature. It costs a few more tokens in the system prompt but saves far more tokens in wasted tool calls.
Prompt technique effectiveness and token costs
The four techniques above improve tool-use accuracy, but at different costs. Here's a comparison based on illustrative testing estimates:
| Technique | Improvement in tool accuracy | Token cost per step | Use when | |---|---|---|---| | Basic tool list | Baseline | ~200 tokens | Tool set is small and unambiguous | | Explicit goal definition | +5-8% | +0 tokens | Goal has multiple possible stopping points | | Tool-use examples | +12-18% | +500-800 tokens | Tool set is large or decisions are ambiguous | | Separated constraints | +3-5% | +200-300 tokens | Agent could violate rules without explicit warnings | | Reasoning-before-action | +15-22% | +50-100 tokens per step | Tool set has similar-looking tools or specialized domain |
Cumulative effect: A prompt using all five techniques might add 1,000-1,500 tokens to the system prompt, but can reduce tool-use errors by 35-45%, which often translates to 10-30% fewer wasted steps in a multi-step loop. For an agent making 20 steps, this saves significant cost.
The extra ingredient: stopping guidance
Unlike a chatbot prompt, an agent's system prompt must explicitly say:
- When the loop is done: "You are done when you have gathered X facts from Y sources" -- not vague, but concrete.
- What to do if stuck: "If you've tried this step three times without progress, stop and report the blocker rather than retrying silently."
- How to handle partial success: "If you gather some but not all the requested information, stop and report what you found and what you couldn't find, rather than looping forever."
Without this, agents either:
- Stop too early: "I have some information, I'll call it done"
- Loop forever: "Maybe one more search will help... and one more..."
- Fail silently: Get stuck on a failed tool call and retry the same failing approach endlessly
A concrete stopping guidance section:
STOPPING GUIDANCE:
Success: You are done when you have:
- Retrieved pricing from all 3 competitors
- Identified the top 2 features each one emphasizes
- Summarized the pros and cons of each
Failure recovery: If you encounter an error or block:
- For a failed search: Try 1 refinement with different keywords. If still empty, move on.
- For a blocked webpage: Note that you couldn't access it and continue with other sources.
- If you've attempted the same step 3+ times: Stop and report what succeeded and what failed.
Do not loop indefinitely. Better to report "I found 2 of 3 competitors" than to get stuck retrying forever.
Assembling a full agent system prompt
A well-formed agent system prompt has four distinct labeled sections:
- GOAL section: States what "done" looks like in checkable terms.
- TOOLS section: Lists each tool with purpose, arguments, return shape, when to use/not use it, and edge case handling.
- CONSTRAINTS section: States hard rules the agent must never violate, kept separate from the goal.
- STOPPING GUIDANCE section: Covers success (when to stop) and failure (what to do if stuck).
Here's a real example:
GOAL:
Research three competitors' pricing and features. Produce a table comparing:
- Company name, product name, pricing tier, top 3 features, and overall value rating.
Stop once you have all three competitors or have exhausted all available public sources.
TOOLS:
search(query: string) -> list of {title, url, snippet}
- Use for: Finding competitor websites, product pages, pricing info
- Do NOT use for: Calculations, decisions about which is "better" (that comes later)
- If 0 results: Try one refined query. If still empty, note "not found" and move on.
visit_page(url: string) -> {title, body_text, extracted_tables}
- Use for: Reading full product pages to extract detailed pricing or features
- Do NOT use for: Every snippet result (too slow). Only for promising leads.
CONSTRAINTS:
- Only use public, published sources (no scraping private pages)
- Do not visit more than 10 URLs per competitor (budget constraint)
- Do not make up information; if you can't find pricing, say "pricing not public"
STOPPING GUIDANCE:
- Success: You've gathered info on 3 competitors
- Acceptable: You've gathered info on 2 competitors + exhausted public sources
- Failure: After 5 search attempts and 10 URLs, you have <2 competitors
This structure is explicit enough that the model knows what to optimize for, when to stop, and how to recover from failures. Lesson 15 of this course builds a complete, runnable agent with exactly this structure.
Edge cases in agent prompts: ambiguity and recovery
Agent prompts must handle scenarios that single-turn chatbot prompts never face:
1. Ambiguous intermediate results An agent retrieves data but it's unclear whether it answers the original question. The prompt must say what to do:
AMBIGUITY RECOVERY:
If a tool result is partially relevant but doesn't fully answer the question:
- If relevance > 70%: Move forward with the partial answer; note what's missing
- If relevance 30-70%: Try ONE refined query with different keywords before moving on
- If relevance < 30%: Consider an alternative tool or approach before retrying
Without this, agents either commit prematurely to partial answers or loop endlessly refining.
2. Tool failure handling What does an agent do when a tool call fails (timeout, permission denied, malformed response)? The prompt must differentiate:
TOOL FAILURE TYPES:
- Transient failure (timeout, rate limit): Retry ONCE after 1 second
- Permanent failure (permission denied, 404): Note failure and proceed with alternative tool
- Malformed response (unparseable JSON): Retry with clearer prompt to the tool
- Expected empty result (0 search hits): This is valid; note it and continue
3. Hallucination in intermediate steps If an agent makes up data because a tool didn't return what it expected, the outcome can compound through the loop. Mitigate with:
VERIFICATION RULE:
If a tool result is empty or missing expected fields, DO NOT assume defaults.
Always ask: "The tool returned [X]. Does this match what I expected? If no, what was unexpected?"
If the mismatch suggests a real problem (not just absent data), retry or switch tools.
Here's a practical example of a prompt that handles these edge cases:
full_agent_system_prompt = """
GOAL:
Research three competitors' pricing. Produce a comparison table.
You are done when you have pricing data (or clear evidence it's not public) for all three.
TOOLS:
search(query: string) -> list of {title, url, snippet}
visit_page(url: string) -> {title, body_text, tables}
CONSTRAINTS:
- Never scrape private pages or violate robots.txt
- Only use public, published information
- Do not make up pricing if you cannot find it
STOPPING GUIDANCE:
Success: Gathered pricing for 3 competitors
Partial success: Gathered for 2 competitors + documented why the 3rd is unavailable
Failure: After 10 search attempts across all three, you have <2 competitors
AMBIGUITY RECOVERY:
If search returns results but it's unclear if they match the competitor name:
- Visit the top 2 results to verify
- If neither is the right competitor, try a refined search with company name + "pricing"
- If still nothing, note that pricing is not publicly listed
TOOL FAILURE:
- search returns 0 results: Try ONE alternate query (e.g., "company name + price" → "company name + cost")
- visit_page returns empty body_text: Note that the page wasn't readable; move on
- visit_page times out: This is fine; assume the information is inaccessible
BEFORE YOU ACT:
For each search, briefly state which competitor you're targeting and why that query should find their pricing.
"""
4. Context window pressure As an agent loop runs, the context window fills with previous steps. The prompt should anticipate this:
CONTEXT MANAGEMENT:
Once you have retrieved information on a competitor, do NOT repeat searches for that competitor.
If you need to refine something you already know, summarize what you know and describe what's missing.
Case study: Retail agent with prompt failure
Scenario: A retail company deployed an agent to price-match competitors. The agent's initial prompt was minimal:
WRONG PROMPT:
You are a price-comparison assistant. Your goal is to find competitor prices.
You have access to search and visit_page tools. Use them to find pricing.
What happened:
- The agent searched for "competitor prices" and got 50 results. It visited 5 random pages and extracted numbers, then stopped because it had "something."
- For competitor B, the search returned fashion blogs and unrelated sites. The agent hallucinated a price that sounded reasonable ($49.99) rather than noting the search failed.
- The agent looped forever on competitor C because the search kept returning "not found" and the prompt didn't say when to give up.
- The agent submitted contradictory data: competitor A's price extracted from a 2-year-old cached page, not current pricing.
Revised prompt with stopping guidance:
CORRECT PROMPT:
[same goal but with:]
STOPPING GUIDANCE:
Gathered prices for all 3 competitors OR documented why unavailable → STOP
Otherwise, if you've attempted 3 searches per competitor → STOP and report what you found
TOOL FAILURE:
If search returns 0 results: Try ONE refined query. If still 0, note "pricing not found online"
AMBIGUITY:
If search returns results but uncertainty about whether they match the competitor:
- Visit the result and verify it's the competitor's official site (check domain, company name in page)
- If NOT the official site, try next result or search again
DO NOT HALLUCINATE: If you cannot find a price, say "not found" rather than guessing
With the revised prompt, the agent:
- Stopped after 3 failed searches for competitor C and reported "pricing not found"
- Verified domain names before extracting prices
- Differentiated between current pricing (visited today) and cached/stale prices
- Completed in 60% fewer steps with 0 hallucinated data
Common mistake
Writing an agent prompt as if it were a chatbot prompt with tools appended at the end. This looks like:
WRONG:
You are a helpful research assistant. Your goal is to research topics thoroughly.
You have access to these tools: search, visit_page, summarize. Use them as needed.
Tool descriptions, stopping guidance, and constraint handling are not optional extras -- they are the parts of the prompt that specifically determine whether a loop behaves predictably or gets stuck. A good agent prompt is longer, more structured, and more explicit than a good chatbot prompt. That's not padding; that's the difference between an agent that completes tasks and one that loops forever or forgets its constraints.
Sources and license context
These references informed the lesson. ToolDix adds its own explanation, workflow, and practice rather than reproducing source material. Every link below leaves ToolDix and opens the publisher's own site in a new tab.
- OpenAI: Prompt engineering guide (opens platform.openai.com in a new tab)External · platform.openai.com (Publisher terms apply)
- Anthropic: Building Effective Agents (opens anthropic.com in a new tab)External · anthropic.com (Publisher terms apply)
- Best practices for working with the Anthropic API (opens docs.anthropic.com in a new tab)External · docs.anthropic.com (Publisher terms apply)
Keep going
Read these next on ToolDix.
Original lessons that build on what you just read.