Master prompt engineering for Agentic RAG. Learn to build reliable AI agents using hard retry limits, tool selection boundaries, state compression, and structured JSON outputs.
Table of Contents
What’s Actually Going Wrong?
Why Prompt Engineering Matters More Than You Think
How to Stop Infinite Loops (The Hard Stop Rule)
Teaching Agents to Pick the Right Tool
Defeating “Lost in the Middle”
Breaking Down Complex Questions
Preventing Hallucinations From Empty or Conflicting Context
Building a Reflection Evaluator That Actually Works
Routing Smartly: Simple vs Complex Requests
Fixing the JSON Problem Once and For All
Compressing Conversation History Without Losing Context
The Complete Agentic RAG System Prompt Template
Testing Prompts Like Software
The Golden Rules
The Bottom Line
1. What’s Actually Going Wrong?
You’ve built an Agentic RAG system. It’s supposed to be smart. It retrieves documents, calls tools, rewrites queries, evaluates answers, and tries again when things go wrong.
That sounds powerful. It is.
But without carefully designed prompts, the same intelligence becomes chaotic.
Your agent might:
retry the same failed search forever
call the wrong tool for the job
invent an answer when the context is empty
bury important evidence inside a huge prompt
produce invalid JSON that breaks your parser
spend most of its budget rereading its own history
This is where prompt engineering for Agentic RAG becomes more than writing clever instructions. It becomes the design of the agent’s behavioral contract.
A good prompt tells the agent:
what it is allowed to do
what it must never do
when it should continue
when it should stop
what format it must return
2. Why Prompt Engineering Matters More Than You Think
Many developers treat prompts like secret spells. They keep changing words: “Please try again,” “Try a different search,” “Be more accurate,” “Think carefully.”
These instructions sound reasonable, but they are not enough for production systems.
A reliable prompt needs five things:
A clear role — Who is the agent?
A specific task — What exactly should it do?
Hard constraints — What can’t it do?
A failure policy — What happens when things go wrong?
A machine-readable output format — How should it respond?
The strongest prompt is not the longest one. It is the one that removes ambiguity.
3. How to Stop Infinite Loops (The Hard Stop Rule)
The Problem :
Imagine this workflow:
User Question ↓ Retrieve Documents ↓ Grade Documents ↓ Documents Irrelevant? ↓ Rewrite Query ↓ Retrieve Again
Now imagine the rewritten query is also bad. The agent retrieves again, fails again, rewrites again, and repeats until the token budget disappears.
The Wrong Prompt :
If the documents are not relevant, rewrite the query and search again.
What’s missing?
How many times can the agent retry?
What counts as “not relevant”?
What happens after the final attempt?
Should it ask the user for clarification?
Without those rules, the agent has no exit strategy.
The Better Prompt :
You are a retrieval decision agent.
Your task is to evaluate the retrieved documents and decide the next action.
Rules:
1. You may request at most 2 retrieval attempts.
2. Each retry must materially change the search query.
3. Do not repeat a previous query.
4. If the second retrieval attempt fails, stop immediately.
5. Do not invent an answer.
6. Return "UNCERTAIN" when the evidence is insufficient.
7. Return only valid JSON.
Allowed actions:
- "answer"
- "retry"
- "uncertain"
Output schema:
{
"action": "answer | retry | uncertain",
"reason": "short explanation",
"next_query": "required only when action is retry"
}Bad vs Good: Hard Stop Rules :
| Aspect | ❌ Weak Prompt | ✅ Strong Prompt |
|---|---|---|
| Retry limit | Not specified | Max 2 attempts |
| Query change | Not defined | Must materially change |
| Duplicate check | Not mentioned | Cannot repeat previous query |
| Failure behavior | Vague | Stop and return UNCERTAIN |
| Output format | Free text | Structured JSON |
The Production Truth
A prompt-level retry limit is useful, but it should not be your only protection. The application code should also enforce the limit:
MAX_RETRIES = 2 if state["retry_count"] >= MAX_RETRIES: return { "status": "UNCERTAIN", "answer": "I do not have sufficient information." }
The prompt expresses intent. The controller enforces reality.
The Escape Hatch Pattern
Every agentic loop should have:
a maximum iteration count
a retry counter in state
a duplicate-query check
a minimum-improvement rule
a final fallback
Continue only if: - retry_count < max_retries, - the new query is different, - and the previous attempt showed a meaningful retrieval gap. If any of these conditions fails, stop.
Practical State Shape :
from typing import TypedDict class RAGState(TypedDict): query: str documents: list answer: str retry_count: int status: str # SUPPORTED | INSUFFICIENT | CONFLICTING | UNCERTAIN
4. Teaching Agents to Pick the Right Tool
An Agentic RAG system may have several tools: vector search, SQL, web search, calculator, document retrieval, CRM lookup, or internal APIs.
The agent must understand not only what each tool does, but also when not to use it.
The Classic Tool-Selection Mistake
User: “What were our sales in Q2?”
The agent calls vector search and retrieves a PDF report. But the actual answer lives in PostgreSQL, where the latest structured numbers are stored.
Or the user asks: “Explain our refund policy.” The agent calls SQL even though the answer is in policy documents.
The problem is not that the tools are broken. The problem is that the prompt did not clearly define their boundaries.
Tool Descriptions Should Be Short and Specific :
| Aspect | ❌ Bad Description | ✅ Good Description |
|---|---|---|
| What it does | “Search for useful information” | “Query structured sales tables for exact metrics” |
| What it doesn’t do | Not specified | “Do not use for policies or documents” |
| Use cases | Not specified | “Revenue, orders, customer counts” |
Bad tool description:
“Search the company database for useful information.”
Better:
“Use this tool for exact numerical queries over structured business data, such as revenue, sales, orders, employee counts, and dates. Do not use it for policy explanations or unstructured documents.”
Few-Shot Tool-Selection Examples :
Few-shot examples teach the model by showing the correct decision.
Example 1 User query: "What was total revenue in Q2 2026?" Correct tool: sql_database Reason: This requires an exact numerical value from structured records. Example 2 User query: "What is the employee reimbursement policy?" Correct tool: vector_search Reason: This requires semantic search across policy documents. Example 3 User query: "What happened in the latest RBI circular?" Correct tool: web_search Reason: This requires current external information.
Dynamic Few-Shot Routing
For systems with many tools, you can dynamically retrieve the few-shot examples that most closely match the user’s query. This keeps the router prompt short and fast while still providing relevant guidance.
def get_relevant_examples(query, example_store, top_k=3): """Retrieve the most relevant few-shot examples for the current query""" query_embedding = embed(query) example_scores = [] for example in example_store: score = cosine_similarity(query_embedding, example["embedding"]) example_scores.append((score, example)) # Sort by relevance and return top-k example_scores.sort(reverse=True, key=lambda x: x[0]) return [ex for _, ex in example_scores[:top_k]]
A Router Output Contract :
{ "tool": "sql_database", "confidence": 0.94, "reason": "The query asks for an exact numerical business metric.", "requires_multiple_tools": false }
Tool-Selection Rule
Use vector search for semantic documents and policies
Use SQL for exact structured data
Use web search for current external information
Use calculator or code execution for arithmetic and deterministic computation
Use multiple tools only when the query genuinely requires them
5. Defeating “Lost in the Middle”
A retrieval system can return the right documents and still fail because the important information is buried in the middle of a long context.
Research from Stanford and other institutions has documented the “Lost in the Middle” phenomenon, where models attend more strongly to information near the beginning or end of a prompt while missing critical passages in the center .
A Weak Context Format
Document 1 [large text] Document 2 [large text] Document 3 [important answer hidden here] Document 4 [large text]
A Stronger Context Format :
# RETRIEVED EVIDENCE ## Highest-Relevance Evidence [Most relevant passage] ## Supporting Evidence [Second relevant passage] ## Additional Evidence [Third relevant passage] ## Evidence Rules - Prefer higher-ranked passages. - Do not treat missing information as a fact. - Report contradictions explicitly.
Bad vs Good: Context Formatting :
| Aspect | ❌ Weak Format | ✅ Strong Format |
|---|---|---|
| Structure | Flat text dump | Hierarchical sections |
| Relevance | Not indicated | Clear ranking labels |
| Metadata | Missing | Document IDs, dates, scores |
| Evidence rules | Not specified | Explicit preference rules |
| Summary | None | Key evidence summary first |
Add Metadata
Metadata helps the model judge evidence quality:
[DOCUMENT_ID: HR-2026-04] [SOURCE_TYPE: Official Policy] [REGION: Bengaluru] [YEAR: 2026] [RELEVANCE_SCORE: 0.94] [CONTENT] Employees in the Bengaluru office receive...
Repeat Only What Matters
Instead of duplicating every retrieved chunk, create a small evidence summary first, then place the full source passages below it.
# KEY EVIDENCE SUMMARY - Bengaluru policy: 18 paid leave days. - Mumbai policy: 16 paid leave days. - Both policies are dated 2026. # FULL SOURCE PASSAGES [Full documents here]

6. Breaking Down Complex Questions
Complex questions should not be answered as one giant task.
Consider: “Compare Q1 revenue, customer growth, and profitability of Company A and Company B, then explain which one has stronger momentum.”
This question contains multiple jobs:
Find Company A’s revenue
Find Company B’s revenue
Find customer growth for both
Find profitability for both
Normalize the time period
Compare the data
Explain the conclusion
The Decomposition Prompt :
You are a query-planning agent.
Break the user request into the smallest independent research tasks.
Rules:
1. Create one task for each distinct fact or comparison.
2. Do not answer the question.
3. Do not invent missing entities or dates.
4. Mark tasks as parallel if they do not depend on each other.
5. Mark tasks as sequential if one requires the result of another.
6. Return only valid JSON.
Output:
{
"tasks": [
{
"id": "task_1",
"question": "...",
"depends_on": [],
"execution": "parallel"
}
]
}Example Output :
{ "tasks": [ { "id": "task_1", "question": "Find Company A Q1 revenue.", "depends_on": [], "execution": "parallel" }, { "id": "task_2", "question": "Find Company B Q1 revenue.", "depends_on": [], "execution": "parallel" }, { "id": "task_3", "question": "Compare revenue, customer growth, and profitability.", "depends_on": ["task_1", "task_2"], "execution": "sequential" } ] }
Why JSON Matters Here :
A downstream orchestrator can execute a JSON plan. It cannot reliably execute a paragraph like “First, perhaps search both companies, then compare the results…” Machine-readable plans reduce ambiguity and make retries easier.
Article went a little over your head? No worries at all. If you want a fun, interactive way to figure out how these AI agents actually think without staring at code, jump into our BEGINNER AI LABS – PROMPT ENGINEERING – The AI Command Center — Prompt Engineering Lab at Neural Ninjas]. Zero complex headaches, 100% gamified visual learning!
7. Preventing Hallucinations From Empty or Conflicting Context
LLMs often want to be helpful even when the evidence is missing. That is dangerous.
Empty Context
If retrieval returns nothing, the agent should not answer from general knowledge. If the retrieved context is empty, do not answer the question.
Return:
{
"status": "INSUFFICIENT_CONTEXT",
"answer": "I do not have sufficient information."
}Conflicting Context :
Suppose one document says: “Employees receive 18 paid leave days.” Another says: “Employees receive 15 paid leave days.”
The agent should not invent a compromise like 16.5 days. It should report the conflict.
Bad vs Good: Handling Uncertainty :
| Scenario | ❌ Bad Response | ✅ Good Response |
|---|---|---|
| Empty context | “Employees get 18 days” (hallucinated) | “I do not have sufficient information.” |
| Conflicting docs | “Employees get 16.5 days” (invented) | “Documents conflict: 18 days vs 15 days” |
| Partial evidence | “The policy states…” (overconfident) | “Based on available evidence…” (hedged) |
Grounding Prompt :
You are a grounded answer agent. Use ONLY the supplied context. If the context is empty: - do not answer from memory; - return "INSUFFICIENT_CONTEXT". If the context contains contradictions: - do not merge or average the claims; - identify each conflicting claim; - include the source or document identifier; - return "CONFLICTING_CONTEXT". If the answer is not directly supported: - return "UNSUPPORTED".
Grounding States :
A production system can use explicit statuses:
SUPPORTED
INSUFFICIENT_CONTEXT
CONFLICTING_CONTEXT
UNSUPPORTED
These statuses make uncertainty visible to the application and the user.
8. Building a Reflection Evaluator That Actually Works
A reflection agent should not produce vague feedback like “The answer could be better.” That is useless.
It should evaluate retrieval and generation using a fixed rubric.
Relevance Evaluator Prompt
You are a retrieval evaluation agent.
Evaluate whether the retrieved documents can answer the user question.
User question:
{query}
Retrieved documents:
{documents}
Score the evidence from 1 to 5:
1 = completely irrelevant
2 = weakly related but insufficient
3 = partially useful
4 = mostly sufficient
5 = directly sufficient
Check:
1. Does the evidence address the exact question?
2. Is the evidence specific rather than generic?
3. Is it current enough?
4. Are important sub-questions unanswered?
5. Are there contradictions?
Return only valid JSON:
{
"score": 1,
"decision": "RETRY | ANSWER | UNCERTAIN",
"missing_information": [],
"contradictions": [],
"suggested_query": ""
}Why a Rubric Works ?
| Aspect | ❌ Weak Evaluation | ✅ Strong Evaluation |
|---|---|---|
| Feedback | “Could be better” | “Score: 3/5, missing specific revenue figures” |
| Criteria | Vague | Explicit checklist (relevance, specificity, freshness) |
| Output | Paragraph | Structured JSON with actionable fields |
| Action | Not specified | Clear decision: RETRY, ANSWER, or UNCERTAIN |
Don’t Let the Evaluator Rewrite Endlessly
The evaluator itself needs limits:
If score < 4 and retry_count < 2:
RETRY
If score >= 4:
ANSWER
If retry_count >= 2:
UNCERTAIN9. Routing Smartly: Simple vs Complex Requests
Not every request needs a full Agentic RAG loop.
A simple question like “What is the company’s office address?” does not need multi-hop planning, reflection, multiple retrieval attempts, or an expensive model.
Router Prompt :
You are a request router.
Classify the query into exactly one category:
- SIMPLE_RAG: one direct document lookup
- COMPLEX_RAG: multiple retrieval or reasoning steps
- TOOL_TASK: requires an external action or structured system
- CLARIFICATION: the request is ambiguous
- GENERAL_CHAT: no retrieval is needed
Rules:
1. Return only valid JSON.
2. Do not answer the query.
3. Use COMPLEX_RAG only when multiple steps are necessary.
Output:
{
"route": "SIMPLE_RAG",
"confidence": 0.0,
"reason": "short explanation"
}Why Routing Saves Money
Simple query → small model + one retrieval
Complex query → larger model + planning + reflection
Action request → tool-enabled agent
Ambiguous query → clarification
Framework Support
These routing patterns integrate naturally with frameworks like LangGraph (for stateful routing), LlamaIndex (for query planning), CrewAI (for multi-agent orchestration), or AutoGen (for agent handoffs).
10. Fixing the JSON Problem Once and For All
A prompt saying “return JSON” is not a guarantee.
Native Structured Outputs
Modern models (like GPT-4o, Claude 3.5, and Gemini) support native structured outputs or strict function calling at the API level. This guarantees schema compliance better than prompt-level JSON instructions.
from openai import OpenAI client = OpenAI() # Native structured output with schema completion = client.beta.chat.completions.parse( model="gpt-4o-2024-08-06", messages=[{"role": "user", "content": "Classify this query"}], response_format=RouterDecision # Pydantic model )
The Output Contract
When using prompt-level JSON instructions:
Return ONLY a valid JSON object.
Do not include:
- explanations,
- greetings,
- Markdown fences,
- comments,
- trailing text,
- or additional keys.
Use exactly this schema:
{
"status": "success | failure",
"answer": "string",
"confidence": 0.0
}The Reliable Pipeline :
Generate ↓ Parse ↓ Validate schema ↓ Validate business rules ↓ Retry or repair if invalid
Bad vs Good: JSON Handling :
| Aspect | ❌ Weak Approach | ✅ Strong Approach |
|---|---|---|
| Schema enforcement | “Return JSON” | Schema + Pydantic/Zod validation |
| Error handling | Assume valid | Validate and retry on failure |
| Markdown fences | Sometimes present | Explicitly forbidden |
| Native support | Not used | Use API structured outputs |
Pydantic Validation Example :
from pydantic import BaseModel, Field from typing import Literal class RouterDecision(BaseModel): route: Literal["SIMPLE_RAG", "COMPLEX_RAG", "TOOL_TASK", "CLARIFICATION"] confidence: float = Field(ge=0.0, le=1.0) reason: str
Now the application can reject invalid responses.
11. Compressing Conversation History Without Losing Context {#compression}
Agentic workflows can generate huge histories. After ten turns, the prompt becomes enormous.
Rolling Summary Prompt :
You are a conversation memory compressor.
Summarize the conversation into a compact state for future agent steps.
Preserve only:
1. User goals
2. Confirmed facts
3. User preferences
4. Completed actions
5. Failed actions
6. Open questions
7. Important document IDs
8. Safety or permission decisions
Remove:
- greetings,
- repeated explanations,
- verbose tool outputs,
- abandoned reasoning,
- and duplicate facts.
Return valid JSON:
{
"goals": [],
"confirmed_facts": [],
"completed_actions": [],
"failed_actions": [],
"open_questions": [],
"important_sources": []
}What to Keep Raw :
Keep recent and important information raw:
the latest user request
unresolved conflicts
permission decisions
tool errors
source identifiers
current workflow state
Compress the rest.
12. The Complete Agentic RAG System Prompt Template :
SYSTEM ROLE You are a grounded Agentic RAG assistant. PRIMARY OBJECTIVE Answer the user's question using reliable retrieved evidence. Do not use outside knowledge when answering factual questions. RETRIEVAL RULES 1. Use retrieved context as the source of truth. 2. Prefer recent, specific, and authoritative documents. 3. Do not treat metadata or relevance scores as factual evidence. 4. If evidence is missing, do not guess. 5. If evidence conflicts, report the conflict. RETRY RULES 1. You may retry retrieval at most 2 times. 2. Every retry must use a materially different query. 3. Never repeat the same query. 4. If all attempts fail, return: "I do not have sufficient information." TOOL RULES 1. Use SQL for exact structured metrics. 2. Use vector search for semantic documents. 3. Use web search only for current external information. 4. Use tools only when the query requires them. 5. Do not call destructive tools without explicit approval. PLANNING RULES 1. Decompose multi-part questions into independent sub-tasks. 2. Run independent tasks in parallel when possible. 3. Do not create unnecessary sub-tasks. 4. Do not answer until required evidence is available. OUTPUT RULES 1. Return only the requested format. 2. If JSON is required, return valid JSON only. 3. Do not include Markdown fences or extra commentary. 4. Cite the source document IDs when available. UNCERTAINTY RULES Return one of: - SUPPORTED - INSUFFICIENT_CONTEXT - CONFLICTING_CONTEXT - UNSUPPORTED STOP CONDITION Stop when: - the answer is supported, - the retry limit is reached, - the evidence is conflicting, - or user clarification is required.
13. Testing Prompts Like Software :
A prompt is not finished because it worked once.
Test it against adversarial cases.
Evaluation Table :
| Test | Expected Behavior |
|---|---|
| No documents retrieved | Abstain |
| Two conflicting policies | Report conflict |
| First search fails | Retry with a new query |
| Second search fails | Stop |
| Same query suggested again | Reject duplicate |
| Simple question | Use fast path |
| Complex question | Decompose |
| Invalid JSON | Retry or fail safely |
| Destructive tool request | Ask for approval |
14. The Golden Rules :
Every loop needs a hard stop.
Every tool needs a clear boundary.
Every factual answer needs evidence.
Empty context means abstain, not guess.
Conflicting context means report, not average.
Complex questions should become structured sub-tasks.
JSON should be validated by code, not trusted because the prompt said so.
Long history should be compressed before it becomes expensive noise.
The application must enforce limits that the prompt describes.
A shorter, clearer prompt often beats a longer, cleverer one.
15. The Bottom Line :
Prompt engineering for Agentic RAG is not about making the model sound intelligent.
It is about making the agent predictable under pressure.
A good prompt helps the agent choose the right tool, use the right evidence, stop when it should, admit uncertainty, and return output that your software can safely consume.
The best Agentic RAG prompt is not the one that says “Think harder.” It is the one that says:
“Here is your job. Here is the evidence. Here are the limits. Here is what to do when things go wrong.”
That is how you turn an enthusiastic AI model into a reliable engineering system.
