Lesson 18: The Research Loop: Query Generation, Perplexity, and Human Feedback
In this lesson, we will explore the research loop that forms the core of our research agent’s intelligence. We will see how the agent generates relevant search queries based on content gathered in previous lessons and uses Perplexity to expand its knowledge base. We’ll also see how to integrate human feedback into the research workflow. This creates a powerful human-in-the-loop (HITL) system that allows users to guide the research direction while using the agent’s analytical capabilities.
You will:
- Learn how to generate contextual research queries using LLMs and structured outputs
- Understand how to integrate external research services like Perplexity for a comprehensive web search
- Implement human-in-the-loop feedback mechanisms in agentic workflows
- Explore the iterative design process behind building effective AI research agents
Open-ended research can easily drift without a control loop. We need a repeatable way to detect knowledge gaps, propose targeted queries, fetch cited answers, and pause for human approval before spending more of our budget.
In previous lessons, we laid the foundation for our research agent. We built the MCP server and client, defined our server-hosted prompts, and implemented a suite of ingestion tools to process URLs, GitHub repositories, and YouTube videos [1], [2]. Now we will build the agent’s core intelligence: a research loop that generates gap-filling queries, fetches cited answers from Perplexity, and allows for human oversight. You will learn to build a system that is controllable, explainable, and economical, a workflow you can reuse across your own projects.
Understanding the Research Loop
After gathering initial content from guidelines, the agent enters a three-round research cycle designed to fill knowledge gaps and expand its understanding.
Each round consists of two main steps:
- Generate new queries with the
generate_next_queriestool - Run those queries with the
run_perplexity_researchtool
This iterative process allows the agent to build on its knowledge with each cycle instead of starting from scratch every time.
Notice the file-first pattern we established in the previous lessons. The next_queries.md file is overwritten in each round with new queries, while perplexity_results.md is appended, creating a persistent and auditable log of all research findings [3].
In addition, the prompt includes our critical-failure policy: if any of the initial ingestion tools in Step 2 report zero successes (e.g., failed to scrape any URLs), the agent is instructed to halt and request human guidance before starting the research loop.
Why We Use Perplexity (The Philosophy)
Before diving into the implementation, it’s important to understand our architectural philosophy. Similar to our approach with web scraping, we’re using Perplexity for web search rather than building our own solution.
When there’s a general problem faced by many in the industry, it’s often more efficient to plug into dedicated tools rather than building every element yourself. Companies like Perplexity make LLM-based web search their entire business, investing heavily in:
- Comprehensive source coverage across the web
- Real-time information retrieval with source citations
- Advanced ranking and relevance algorithms
- Handling of dynamic content and paywalls
- Rate limiting and API reliability
This allows us to focus on the unique elements of our research agent: the intelligent query generation, human feedback integration, and workflow orchestration.
On the technical side, Perplexity offers two key benefits for our agent. First, it supports structured outputs, allowing us to request responses as objects containing a URL and the answer text. As we covered in Lesson 4, this is essential for reliable parsing. Second, its API is asynchronous, allowing us to run multiple queries in parallel to keep the research loop fast and efficient. The results are then appended to a single file for auditability [5], [6].
Query Generation: The Brain of the Research Loop
The generate_next_queries_tool is central to the research loop’s intelligence. It analyzes all available context and intelligently identifies knowledge gaps to fill.
Understanding the Implementation
Let’s examine the core implementation (from mcp_server/src/tools/generate_next_queries_tool.py).
The tool gathers three types of context:
- Article Guidelines : The original requirements and scope. This provides the foundational understanding of what the article should cover.
- Past Research : Previous Perplexity results. This ensures the LLM does not generate duplicate queries and can identify gaps in existing research.
- Scraped Content : All content from guideline URLs concatenated together. This provides a comprehensive background context that helps the LLM understand what information is already available.
The LLM analyzes all three contexts simultaneously. It uses the article guidelines to define the target scope, reviews prior research to identify what has already been covered, and examines scraped content to understand the existing knowledge base. This comprehensive analysis enables it to generate queries that specifically target knowledge gaps [7]. For example, if the article guidelines mention “error handling in AI agents” but neither prior research nor scraped content adequately covers this topic, the LLM will prioritize generating queries about error-handling strategies.
The LLM-Powered Query Generation
The actual query generation happens in the generate_queries_with_reasons function (from mcp_server/src/app/generate_queries_handler.py ).
This is the prompt used for query generation. It can potentially have contexts of ~100k tokens or more.
This prompt explicitly instructs the LLM to identify missing information and ensures queries cover different aspects rather than duplicating existing research [8]. Last, the generate_queries_with_reasons function uses Pydantic models to ensure consistent, structured responses.
This structured approach ensures the LLM returns exactly what we need: queries paired with clear justifications. These justifications help us understand the LLM’s thought process when generating queries, which is useful for debugging and for the human-in-the-loop to provide feedback to the agent [9].
Testing Query Generation
Let’s test the generate_queries_with_reasons function to see how it works in practice. We’ll use a simplified example about function calling with LLMs:
It outputs:
Understanding the Output
Observe the following:
- Gap Analysis : Notice how the LLM identified that the existing research only covers “basic function calling” and “simple examples”, then generated queries specifically targeting the missing advanced topics (security, performance, error handling).
- Section Mapping : Each generated query directly maps to sections mentioned in the article guidelines that lack coverage. The LLM demonstrates a sophisticated understanding by connecting article requirements to knowledge gaps.
- Query Quality : The queries are specific and actionable. Instead of generic questions like “What is security?”, it asks targeted questions like “What are the most common security vulnerabilities when implementing LLM function calling?”
- Reasoning Transparency : Each query comes with clear reasoning explaining why it’s important and which article section it addresses. This transparency helps users understand the LLM’s decision-making process.
- Progressive Complexity : The LLM naturally progresses from basic concepts (already covered) to advanced topics (security, performance, production practices), showing an understanding of knowledge hierarchies.
This intelligent gap analysis is what makes the research loop powerful.
P erplexity Integration: Concurrent Execution and Structured Outputs
Once we have our queries, we need to execute them efficiently. The run_perplexity_research_tool handles this integration with concurrent execution and structured outputs.
The Research Tool Implementation
The run_perplexity_research_tool (from mcp_server/src/tools/run_perplexity_research_tool.py) is the orchestrator that manages the entire Perplexity research process.
The key performance optimization is concurrent execution. Instead of running queries sequentially, it creates a list of tasks and executes them all at once with asyncio.gather(*tasks) [10]. Results from each round are appended to the same file, building up a comprehensive research database over the three rounds while maintaining a complete audit trail.
Structured Perplexity Responses
The core Perplexity integration uses structured outputs to ensure consistent, parseable results. We are not just getting raw text, but structured data that our system can reliably process. This code snippet is taken from mcp_server/src/app/perplexity_handler.py:
When you run a Perplexity search as above, you get a structured response like this:
This structured format ensures that each source is clearly separated, URLs are preserved for citation, the content is substantial, and the data is parseable by downstream tools.
The Perplexity Search Prompt
The prompt used for Perplexity searches is designed to extract maximum value.
This prompt ensures that each source is clearly identified and separated, provides detailed information, and returns the output in a consistent format for parsing and storage.
Testing the Tools Programmatically
Testing tools programmatically helps you understand their contracts before integrating them into the full agent workflow [11].
Testing the Query Generation Tool
Let’s test the query generation tool to understand its output.
The output will show a structured summary:
Testing the Perplexity Research Tool
Now let’s test the Perplexity research functionality.
It outputs:
Human-in-the-Loop: Adding Feedback Gates
One of the most powerful aspects of our research agent is its ability to integrate human feedback directly into the workflow. This transforms the agent from a fully automated system into a collaborative research partner.
How Human Feedback Works
The agent can be instructed to pause after generating queries and ask for human approval before proceeding. This is accomplished by modifying the workflow instructions when triggering the MCP prompt. When the user starts the research workflow, they can specify modifications like:
- “Ask for my feedback after generating each set of queries.”
- “Show me the proposed queries and wait for my approval before running them.”
- “Let me select which queries to run from the generated list.”
Let’s see how to run the complete research agent with HITL feedback. We’ll start the MCP client and demonstrate how to request user feedback integration.
It outputs:
Once the client is running, try these commands in sequence:
- Start the workflow with feedback :
/prompt/full_research_instructions_prompt - Request human feedback integration : When the agent asks for the research directory and workflow modifications, respond with:
The research folder is /path/to/your/research_folder. Please modify the workflow to ask for my feedback after generating each set of queries in the research loop. Show me the proposed queries and wait for my approval before running them with Perplexity. Run up to step 3 of the workflow and then stop there, don’t run the rest of the workflow from step 4 onwards. - Observe the agent behavior : The agent will run the initial data ingestion, generate the first set of research queries, and then pause and show you the queries, waiting for your feedback.
- Provide feedback : You can respond with “Approve all queries”, “Only run queries 1, 3, and 5”, or “Replace query 2 with: [your custom query]”.
- Continue the loop : The agent will repeat this process for each of the three research rounds.
This feedback gate is injected by modifying the prompt invocation. For example, you can add a policy like, “Stop after generating queries each round; show them to me; run Perplexity only on my approved subset.” No code changes are needed; the server-hosted prompt accepts these policy tweaks as plain text [12]. This is useful because you can add constraints without altering the codebase, and the same prompt can be used in different modes (fully autonomous vs. HITL).
We arrived at this design through an iterative process [13]. We started with a simple two-step process: generate questions and answer them. We experimented and found that three rounds of research provided good coverage at a reasonable cost. Then, we improved the output format from Perplexity to use structured outputs, as we covered in Lesson 4. Finally, we added the ability to provide workflow modifications to the agent, which enabled the HITL feedback gate. Human oversight ensures budget control, quality assurance, and alignment with research goals before spending on API calls [14].
You can experiment with different types of feedback to see how the agent responds:
- Approve as-is : Let the agent proceed with all generated queries.
- Edit queries : Modify the text of a query to make it more specific.
- Select a subset : Instruct the agent to run only a few of the proposed queries (e.g., “Only run queries 1, 3, and 5”).
- Replace queries : Provide entirely new queries to steer the research in a different direction.
As you do this, you can monitor the .nova/next_queries.mdand .nova/perplexity_results.md files to see what the agent proposed versus what it actually executed based on your feedback.
Conclusion
In this lesson, you built a controllable, three-round research loop. This system generates gap-filling queries using long-context analysis, fetches cited answers via Perplexity with structured outputs, and can pause for human approval between query generation and execution.
The design choices here are aimed at making the system practical to run in production. Structured outputs and normalized Markdown make parsing and auditing easier. The three-round limit keeps costs and drift under control. For example, if a Perplexity Sonar Pro query costs about 0.30 [15]. Because the prompt lives on the server, as we saw in Lesson 16, any MCP client can reuse the same workflow. Human-in-the-loop gates help avoid unnecessary spending and improve result quality, and all results are written to an append-only file for later review.
In our next lesson, we will focus on the final steps of the research process: curating the best sources from our Perplexity results, performing deep scrapes of those sources, and assembling the final research.md document.
References
- Amplify Partners. (n.d.). The AI Research Experimentation Problem. amplifypartners.com/blog-posts/the-ai-research-experimentation-p...
- Model Context Protocol. (n.d.). Prompts (server-hosted, discoverable). modelcontextprotocol.io/docs/concepts/prompts
- Decoding.io. (2023, November). Reviewing Append-Only Workflows. decoding.io/2023/11/reviewing-append-only-workflows
- Beam.ai. (n.d.). Perplexity. beam.ai/llm/perplexity
- Perplexity. (n.d.). Structured Outputs (JSON Schema & Regex). docs.perplexity.ai/guides/structured-outputs
- Instructor. (2023, November 13). Learn Async for LLMs. python.useinstructor.com/blog/2023/11/13/learn-async
- arXiv. (2025, August 29). A deep research pipeline with large language models. arxiv.org/html/2508.12752v1
- Mirascope. (n.d.). Prompt Engineering Best Practices. mirascope.com/blog/prompt-engineering-best-practices
- Lakera. (n.d.). The Ultimate Prompt Engineering Guide. lakera.ai/blog/prompt-engineering-guide
- Unite.AI. (n.d.). Asynchronous LLM API Calls in Python: A Comprehensive Guide. unite.ai/asynchronous-llm-api-calls-in-python-a-compr...
- Galileo. (n.d.). A Guide to Testing AI Agents. galileo.ai/learn/test-ai-agents
- Model Context Protocol. (n.d.). Prompts. modelcontextprotocol.info/docs/concepts/prompts
- Neural Concept. (n.d.). The Iterative Design Process: a Step-by-Step Guide & The Role of Deep Learning. neuralconcept.com/post/the-iterative-design-process-a-step-by-...
- WorkOS. (n.d.). Why AI still needs you: Exploring Human-in-the-Loop systems. workos.com/blog/why-ai-still-needs-you-exploring-human-...
- Perplexity. (n.d.). Sonar Pro model page. docs.perplexity.ai/getting-started/models/models/sonar-pro