Shallow Researcher Agent#
The Shallow Researcher performs fast, bounded tool-augmented research. It handles the majority of queries – simple factual lookups, single-step questions, and straightforward comparisons – using a tight tool-calling loop with configurable iteration limits.
Location: src/aiq_agent/agents/shallow_researcher/agent.py
Purpose#
The shallow path is optimized for speed and cost:
A single LLM with bound tools handles the full research cycle
Tool calls are counted against a budget (
max_tool_iterations)When the budget is exhausted, a synthesis anchor forces the LLM to produce a final answer with citations instead of making more tool calls
Context compaction keeps the message window manageable for long tool chains
Internal Flow#
with tools, datetime, documents] B --> C[Build message list:
SystemMessage + history] C --> D{tool_iterations >= max?} D -->|yes| E[Append synthesis anchor:
'Synthesize final answer now'] E --> F[Invoke LLM without tools] F --> G[Return final response] D -->|no| H[Invoke LLM with bound tools
parallel_tool_calls=true] H --> I{Tool calls in response?} I -->|yes| J[Increment tool_iterations
by number of calls] J --> K[Execute tools using ToolNode] K --> L[Append tool results to messages] L --> C I -->|no| G G --> M[Return updated
ShallowResearchAgentState] style A fill:#e1f5fe style M fill:#e8f5e9 style H fill:#f3e5f5 style K fill:#fff3e0
LangGraph Structure#
The agent builds a two-node StateGraph:
agentnode: Renders the system prompt, invokes the LLM (with or without tools depending on iteration count), and tracks tool call budget.toolsnode:langgraph.prebuilt.ToolNodethat executes tool calls and appends results to messages.Routing:
tools_conditionfrom LangGraph checks whether the LLM response contains tool calls.
The recursion limit is set to (max_llm_turns * 2) + 10 to account for
the agent-tools round trips plus headroom.
State Model#
ShallowResearchAgentState#
Field |
Type |
Default |
Description |
|---|---|---|---|
|
|
required |
Conversation history with LangGraph message reducer |
|
|
|
User-selected data source IDs for tool filtering |
|
|
|
User information for prompt personalization |
|
|
|
Override tools info (used when data_sources filters tools) |
|
|
|
User-uploaded documents with summaries |
|
|
|
Knowledge collection name |
|
|
|
Counter tracking total tool calls made |
Configuration#
Configured through ShallowResearchAgentConfig (NeMo Agent Toolkit type name: shallow_research_agent):
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
|
required |
LLM to use for research |
|
|
|
Tools available for research (web search, document search, etc.) |
|
|
|
Maximum LLM interaction turns |
|
|
|
Maximum tool calls before forcing synthesis |
|
|
|
Enable verbose logging |
Example YAML:
functions:
shallow_research_agent:
_type: shallow_research_agent
llm: nemotron_llm
tools:
- web_search_tool
max_llm_turns: 10
max_tool_iterations: 5
verbose: true
Prompt Template#
The agent uses researcher.j2 located in
src/aiq_agent/agents/shallow_researcher/prompts/.
Template variables:
Variable |
Source |
|---|---|
|
List of |
|
User info dict or empty |
|
Current date and time string |
|
List of user-uploaded document summaries |
Query Rewriting#
When web search tools are available, the prompt includes a query rewriting section. Before calling any search tool, the agent rewrites the user’s question into a search-friendly query that adds implied context:
Time context: adds the current year for “upcoming” or “next” questions
Topic expansion: expands vague shorthand with the obvious topic or scope
This improves search result relevance by ensuring the search index receives queries with the full context the user assumed but did not state.
Synthesis Anchor#
When tool_iterations >= max_tool_iterations, the agent appends a
HumanMessage synthesis anchor after the conversation history:
“You have exhausted your research budget. Synthesize the final answer now using the citations [1], [2] and the ‘## References’ format. Do not attempt any further tool calls.”
This combats the “Lost in the Middle” problem by placing the instruction at the end of the context window.
Citation Verification#
The shallow researcher applies the same citation verification and report sanitization pipeline as the deep researcher. After the LLM produces a final response, all citations are validated against the sources actually retrieved during tool calls, and unsafe or unverifiable URLs are removed.
See Deep Researcher – Citation Verification for full details on the verification logic, URL matching strategies, and audit trail.