GPT-Researcher Deep Dive

Autonomous Research Agent Framework โ€” Source Code Analysis
๐Ÿ“ฆ v0.14.7 ๐Ÿ Python 3.11+ ๐Ÿ”— LangChain 1.0 ๐Ÿ“Š LangGraph ๐Ÿ”Œ MCP Support ๐Ÿง  27 LLM Providers

Executive Summary

GPT-Researcher is a production-grade autonomous research agent that takes a query, plans sub-queries, searches the web via multiple retrievers, scrapes and compresses content, and generates structured reports. It supports both a single-agent mode (the GPTResearcher class) and a multi-agent mode (LangGraph-based ChiefEditorAgent orchestration). The framework is designed for extensibility: pluggable LLM providers, retrievers, scrapers, and prompt families.

Key Insight

The architecture is fundamentally a plan โ†’ search โ†’ scrape โ†’ compress โ†’ synthesize pipeline. The single-agent mode is the "fast path" optimized for single queries, while the multi-agent mode adds human-in-the-loop review, parallel subtopic research, and reviewer/reviser cycles via LangGraph state machines.

Architecture Overview

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ GPT-Researcher Architecture โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ User Query โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚ GPTResearcher โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚ Report Output โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ (Main Agent) โ”‚ โ”‚ (MD/PDF/DOCX) โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ–ผ โ–ผ โ–ผ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ResearchConductor โ”‚ โ”‚ReportGeneratorโ”‚ โ”‚ContextManager โ”‚ โ”‚ โ”‚ โ”‚(plan+search) โ”‚ โ”‚(write report) โ”‚ โ”‚(compress+retrieveโ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ Skills Layer โ”‚ โ”‚ โ”‚ โ”‚ BrowserManager โ”‚ SourceCurator โ”‚ DeepResearch โ”‚ โ”‚ โ”‚ โ”‚ ImageGenerator โ”‚ ContextManager โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ Infrastructure Layer โ”‚ โ”‚ โ”‚ โ”‚ LLM Providers โ”‚ Memory/Embeddings โ”‚ Retrievers โ”‚ โ”‚ โ”‚ โ”‚ Scrapers โ”‚ MCP Client โ”‚ VectorStoreโ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ Multi-Agent Layer (LangGraph) โ”‚ โ”‚ โ”‚ โ”‚ ChiefEditorAgent โ†’ Editor โ†’ Researcher โ”‚ โ”‚ โ”‚ โ”‚ โ†’ Reviewer โ†’ Reviser โ†’ Writer โ†’ Publisher โ”‚ โ”‚ โ”‚ โ”‚ + HumanAgent (human-in-the-loop) โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Core Research Workflow

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Single-Agent Research Flow โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”‚ 1. choose_agent(query) โ”‚ โ”‚ โ””โ”€โ–ถ LLM picks agent type + role prompt โ”‚ โ”‚ โ”‚ โ”‚ 2. plan_research(query) โ”‚ โ”‚ โ”œโ”€โ–ถ get_search_results(query, retrievers[0]) โ”‚ โ”‚ โ””โ”€โ–ถ plan_research_outline(query, results) โ”‚ โ”‚ โ””โ”€โ–ถ generate_sub_queries() via LLM โ”‚ โ”‚ โ”‚ โ”‚ 3. For each sub_query (async.gather): โ”‚ โ”‚ โ”œโ”€โ–ถ _search_relevant_source_urls(sub_query) โ”‚ โ”‚ โ”‚ โ”œโ”€โ–ถ Retriever.search() โ†’ URLs + prefetched content โ”‚ โ”‚ โ”‚ โ””โ”€โ–ถ Dedup via visited_urls set โ”‚ โ”‚ โ”œโ”€โ–ถ scraper_manager.browse_urls(urls) โ”‚ โ”‚ โ”‚ โ””โ”€โ–ถ WorkerPool parallel scraping โ”‚ โ”‚ โ”œโ”€โ–ถ context_manager.get_similar_content(query, data) โ”‚ โ”‚ โ”‚ โ””โ”€โ–ถ ContextCompressor (split โ†’ embed โ†’ filter) โ”‚ โ”‚ โ””โ”€โ–ถ _combine_mcp_and_web_context() โ”‚ โ”‚ โ”‚ โ”‚ 4. source_curator.curate_sources(context) โ”‚ โ”‚ โ””โ”€โ–ถ LLM ranks sources by relevance/credibility โ”‚ โ”‚ โ”‚ โ”‚ 5. report_generator.write_report(context) โ”‚ โ”‚ โ”œโ”€โ–ถ get_prompt_by_report_type() โ”‚ โ”‚ โ””โ”€โ–ถ create_chat_completion(prompt + context) โ”‚ โ”‚ โ”‚ โ”‚ 6. write_introduction() + write_report_conclusion() โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

GPTResearcher Class

The GPTResearcher class in gpt_researcher/agent.py is the main entry point. It's a God Object that owns all subsystems:

class GPTResearcher:
    def __init__(self, query, report_type, report_source, tone,
                 source_urls, document_urls, vector_store, ...):
        self.cfg = Config(config_path)
        self.memory = Memory(cfg.embedding_provider, cfg.embedding_model)
        
        # Composed skills
        self.research_conductor = ResearchConductor(self)
        self.report_generator = ReportGenerator(self)
        self.context_manager = ContextManager(self)
        self.scraper_manager = BrowserManager(self)
        self.source_curator = SourceCurator(self)
        self.deep_researcher = DeepResearchSkill(self)  # if DeepResearch
        self.image_generator = ImageGenerator(self)
        
        # MCP support
        self.mcp_configs = mcp_configs
        self.mcp_strategy = self._resolve_mcp_strategy(...)
Design Note

The GPTResearcher instance is passed as self.researcher to every skill, making it a Mediator pattern. Each skill accesses the researcher's state directly. This creates tight coupling but simplifies state sharing across the pipeline.

Key Constructor Parameters

ParameterTypePurpose
querystrThe research question
report_typeReportTyperesearch_report, resource_report, outline_report, custom_report, detailed_report, subtopic_report, deep
report_sourceReportSourceweb, local, azure, langchain_documents, langchain_vectorstore, hybrid
toneTone enum17 tone options from Objective to Casual
mcp_configslist[dict]MCP server configurations for tool-use research
mcp_strategystr"fast" (once), "deep" (per sub-query), "disabled"
source_urlslist[str]Pre-defined URLs to scrape instead of searching
vector_storeVectorStoreWrapperExternal vector store for RAG

Skills System

Skills are the decomposed capabilities of the researcher, each a class that takes the parent GPTResearcher as its constructor argument:

SkillFileResponsibility
ResearchConductor skills/researcher.py Plan sub-queries, orchestrate search + scrape + context gathering. Core of the research loop.
ReportGenerator skills/writer.py Write reports (intro, body, conclusion), manage subtopics for detailed reports.
ContextManager skills/context_manager.py Retrieve similar content via embedding compression, handle written-content dedup.
BrowserManager skills/browser.py Scrape URLs via WorkerPool, select top images, manage research sources.
SourceCurator skills/curator.py LLM-based source ranking by relevance, credibility, quantitative value.
DeepResearchSkill skills/deep_research.py Recursive breadthร—depth research with nested GPTResearcher instances.
ImageGenerator skills/image_generator.py Generate and embed images into reports (optional, pre-generation before writing).

Memory & Embeddings

The Memory class (gpt_researcher/memory/embeddings.py) is a factory for LangChain embedding providers, not a conversational memory store. It creates the embedding instance used by ContextCompressor for similarity filtering.

Supported Embedding Providers (21)

openai azure_openai cohere google_vertexai google_genai fireworks ollama together mistralai huggingface nomic voyageai dashscope bedrock aimlapi custom gigachat netmind openrouter minimax
class Memory:
    def __init__(self, embedding_provider: str, model: str, **kwargs):
        match embedding_provider:
            case "openai":
                from langchain_openai import OpenAIEmbeddings
                _embeddings = OpenAIEmbeddings(model=model, **kwargs)
            case "ollama":
                from langchain_ollama import OllamaEmbeddings
                _embeddings = OllamaEmbeddings(model=model, ...)
            # ... 19 more providers
    
    def get_embeddings(self):
        return self._embeddings
Architecture Pattern

Memory uses Python's match/case (structural pattern matching) with lazy imports โ€” only importing the required LangChain provider package when that provider is selected. This avoids installing all provider packages upfront.

Context Management

The ContextManager skill delegates to three compressor classes in gpt_researcher/context/compression.py:

1. ContextCompressor (Web Search Results)

class ContextCompressor:
    def async_get_context(self, query, max_results=5, cost_callback=None):
        # Optimization: skip compression for small content
        if total_chars < COMPRESSION_THRESHOLD and len(docs) <= max_results:
            return prompt_family.pretty_print_docs(direct_docs)
        
        # Standard: split โ†’ embed โ†’ filter by similarity
        splitter = RecursiveCharacterTextSplitter(chunk_size=1000, overlap=100)
        relevance_filter = EmbeddingsFilter(embeddings, threshold=0.35)
        pipeline = DocumentCompressorPipeline([splitter, relevance_filter])
        retriever = ContextualCompressionRetriever(pipeline, SearchAPIRetriever(pages))

2. VectorstoreCompressor (Pre-indexed Documents)

Simple similarity search on an existing vector store โ€” no compression pipeline needed.

3. WrittenContentCompressor (Dedup for Detailed Reports)

Finds similar previously-written sections to avoid repetition across subtopic reports. Uses the same splitโ†’filter approach but with SectionRetriever instead.

Smart Optimization

The ContextCompressor has a fast-path: if total content is under COMPRESSION_THRESHOLD (default 8000 chars) and doc count โ‰ค max_results, it skips the expensive embedding pipeline entirely and returns documents directly. This is significant for small research tasks.

Context Compression Pipeline

Scraped Content Query โ”‚ โ”‚ โ–ผ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ RecursiveCharโ”‚ โ”‚ Embeddings โ”‚ โ”‚ TextSplitter โ”‚ โ”‚ (e.g. OpenAI) โ”‚ โ”‚ (1000/100) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ–ผ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ EmbeddingsFilter โ”‚ โ”‚ Chunks โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚ (similarity โ‰ฅ 0.35)โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Relevant Context โ”‚ โ”‚ (formatted docs) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

LLM Provider Layer

The LLM integration follows a three-tier model strategy:

TierConfig KeyUsage
FastFAST_LLMQuick tasks (agent selection, summaries)
SmartSMART_LLMReport generation, source curation
StrategicSTRATEGIC_LLMSub-query generation, deep research planning

GenericLLMProvider (llm_provider/generic/base.py)

class GenericLLMProvider:
    @classmethod
    def from_provider(cls, provider, chat_log=None, verbose=True, **kwargs):
        if provider == "openai":
            from langchain_openai import ChatOpenAI
            llm = ChatOpenAI(**kwargs)
        elif provider == "anthropic":
            from langchain_anthropic import ChatAnthropic
            llm = ChatAnthropic(**kwargs)
        # ... 25 more providers
        return cls(llm, chat_log, verbose)
    
    async def get_chat_response(self, messages, stream, websocket=None):
        if not stream:
            output = await self.llm.ainvoke(messages)
            return output.content
        else:
            # Stream chunks via websocket
            async for chunk in self.llm.astream(messages):
                ...

27 Supported LLM Providers

openai anthropic azure_openai cohere google_vertexai google_genai fireworks ollama together mistralai huggingface groq bedrock dashscope xai deepseek litellm gigachat openrouter vllm_openai aimlapi netmind forge avian minimax

create_chat_completion Utility

The create_chat_completion() function in utils/llm.py is the central LLM call wrapper with:

Retriever Architecture

GPT-Researcher supports 15 retriever backends, each implementing a .search() method:

RetrieverTypeNotes
tavilySearch APIDefault retriever
googleSearch APIGoogle Custom Search
bingSearch APIBing Web Search
duckduckgoSearch APIFree, no API key needed
serperSearch APISerper.dev API
serpapiSearch APISerpAPI
searchapiSearch APISearchAPI.io
searxSelf-hostedSearXNG instance
arxivAcademicarXiv papers
semantic_scholarAcademicAI-focused papers
pubmed_centralAcademicBiomedical literature
exaSearch APINeural search
bochaSearch APIBoCha search
customUser-definedCustom retriever class
mcpTool-useMCP server tools
xquikSocialX/Twitter search

Multi-Retriever Support

Multiple retrievers can be configured simultaneously (comma-separated). The system iterates through all retrievers for each sub-query and deduplicates URLs via the visited_urls set. Some retrievers (like PubMed Central) return full content directly, bypassing the scraping step.

# In _search_relevant_source_urls:
for retriever_class in self.researcher.retrievers:
    if "mcpretriever" in retriever_class.__name__.lower():
        continue  # MCP handled separately
    
    results = retriever.search(max_results=cfg.max_search_results_per_query)
    for result in results:
        if raw_content and len(raw_content) > 100:
            prefetched_content.append(result)  # Skip scraping
        else:
            new_search_urls.append(url)  # Need scraping

MCP Integration

GPT-Researcher has first-class MCP (Model Context Protocol) support with a two-stage architecture:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ MCP Two-Stage Architecture โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”‚ Stage 1: Tool Selection (MCPToolSelector) โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ MCPClientMgr โ”‚โ”€โ”€โ–ถโ”‚ Get Tools โ”‚โ”€โ”€โ–ถโ”‚ LLM Selectโ”‚ โ”‚ โ”‚ โ”‚ (connect) โ”‚ โ”‚ from serverโ”‚ โ”‚ Top 3 โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ Stage 2: Research Execution (MCPResearchSkill) โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ LLM + Toolsโ”‚ โ”‚ โ”‚ โ”‚ bind_tools โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ Tool Calls + Results โ”‚ โ”‚ โ”‚ โ”‚ โ†’ Standard format โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ Strategy Modes: โ”‚ โ”‚ โ€ข fast: Run MCP once, cache results for all queries โ”‚ โ”‚ โ€ข deep: Run MCP for every sub-query โ”‚ โ”‚ โ€ข disabled: Skip MCP entirely โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

MCP Client Manager

The MCPClientManager converts GPT-Researcher configs to langchain-mcp-adapters format, supporting stdio, websocket, and HTTP transports with automatic URL-based transport detection.

MCP Tool Selector

Uses the Strategic LLM to analyze available tools and pick the most relevant ones (default max 3). Falls back to pattern-matching on tool names if LLM selection fails.

MCP Research Skill

Binds selected tools to the LLM via llm.bind_tools(selected_tools), then invokes the LLM which autonomously decides which tools to call. Results are normalized into the standard {title, href, body} format.

Scraper System

Multiple scraper backends for content extraction:

ScraperMethodBest For
BeautifulSoupStatic HTML parsingFast, lightweight pages
Browser (Playwright/nodriver)Headless browserJS-rendered pages
FirecrawlAPI-basedHigh-quality extraction
Tavily ExtractAPI-basedQuick extraction
PyMuPDFPDF parsingPDF documents
WebBaseLoaderLangChain loaderStandard web pages
ArXivarXiv-specificAcademic papers

Scraping is parallelized via WorkerPool with configurable max_scraper_workers and scraper_rate_limit_delay.

Multi-Agent Architecture

The multi-agent system is a LangGraph state machine with specialized agent roles. It's in multi_agents/ (separate from the single-agent gpt_researcher/).

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Multi-Agent Workflow (ChiefEditorAgent) โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ Browser โ”‚โ”€โ”€โ”€โ–ถโ”‚ Planner โ”‚โ”€โ”€โ”€โ–ถโ”‚ HumanAgent โ”‚ โ”‚ โ”‚ โ”‚(Research)โ”‚ โ”‚ (Editor) โ”‚ โ”‚(feedback) โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ accept / revise? โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ accept โ”‚ revise โ”‚ โ”‚ โ–ผ โ–ผ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” back to Planner โ”‚ โ”‚ โ”‚ Editor: run_parallel_researchโ”‚ โ”‚ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ Per-section subgraph: โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ Researcher โ†’ Reviewer โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ–ฒ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ revise โ”‚ accept โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ Reviser โ—„โ”€โ”€โ”€โ”€โ”˜ โ”€โ”€โ”€โ”€โ–ถโ”‚ END โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ–ผ โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ Writer โ”‚โ”€โ”€โ”€โ–ถโ”‚Publisher โ”‚ โ”‚ โ”‚ โ”‚(compose) โ”‚ โ”‚(MD/PDF) โ”‚โ”€โ”€โ”€โ–ถ END โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

LangGraph Integration

The langgraph.json defines the graph entry point:

{
  "python_version": "3.11",
  "dependencies": ["./multi_agents"],
  "graphs": {
    "agent": "./multi_agents/agent.py:graph"
  },
  "env": ".env"
}

State Definitions

ResearchState (outer workflow):

class ResearchState(TypedDict):
    task: dict
    initial_research: str
    sections: List[str]
    research_data: List[dict]
    human_feedback: str
    title: str
    headers: dict
    date: str
    table_of_contents: str
    introduction: str
    conclusion: str
    sources: List[str]
    report: str

DraftState (per-section sub-workflow):

class DraftState(TypedDict):
    task: dict
    topic: str
    draft: dict
    review: str
    revision_notes: str

Workflow Construction

# ChiefEditorAgent._create_workflow:
workflow = StateGraph(ResearchState)
workflow.add_node("browser", agents["research"].run_initial_research)
workflow.add_node("planner", agents["editor"].plan_research)
workflow.add_node("researcher", agents["editor"].run_parallel_research)
workflow.add_node("writer", agents["writer"].run)
workflow.add_node("publisher", agents["publisher"].run)
workflow.add_node("human", agents["human"].review_plan)

workflow.add_edge('browser', 'planner')
workflow.add_edge('planner', 'human')
workflow.add_edge('researcher', 'writer')
workflow.add_edge('writer', 'publisher')
workflow.set_entry_point("browser")
workflow.add_edge('publisher', END)

# Human-in-the-loop conditional
workflow.add_conditional_edges('human',
    lambda review: "accept" if review['human_feedback'] is None else "revise",
    {"accept": "researcher", "revise": "planner"}
)

Agent Roles in Multi-Agent Mode

AgentRoleLLM Usage
ResearchAgent Wraps GPTResearcher for initial + subtopic research Uses GPTResearcher's full pipeline
EditorAgent Plans section layout, runs parallel research per section LLM for planning + creates per-section sub-graph
WriterAgent Writes intro, conclusion, TOC, sources from research data LLM with JSON output format
ReviewerAgent Reviews drafts against guidelines, returns feedback or None LLM with guidelines checking
ReviserAgent Revises drafts based on reviewer feedback LLM with revision instructions
PublisherAgent Assembles final report, exports to MD/PDF/DOCX No LLM โ€” pure formatting
HumanAgent Collects human feedback on research plan WebSocket or console input

Deep Research Mode

The DeepResearchSkill implements a recursive breadth-first search over the research space:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Deep Research Algorithm โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚ โ”‚ generate_research_plan(query) โ”‚ โ”‚ โ””โ”€โ–ถ follow-up questions + initial search โ”‚ โ”‚ โ”‚ โ”‚ deep_research(combined_query, breadth=4, depth=2): โ”‚ โ”‚ 1. generate_search_queries(breadth=4) โ”‚ โ”‚ 2. For each query (concurrent, semaphore=2): โ”‚ โ”‚ a. Create nested GPTResearcher instance โ”‚ โ”‚ b. conduct_research() โ†’ context โ”‚ โ”‚ c. process_research_results() โ†’ learnings โ”‚ โ”‚ 3. If depth > 1: โ”‚ โ”‚ new_breadth = max(2, breadth // 2) โ”‚ โ”‚ For each result: โ”‚ โ”‚ deep_research(next_query, new_breadth, โ”‚ โ”‚ depth-1) โ”‚ โ”‚ 4. Return all learnings + citations + context โ”‚ โ”‚ โ”‚ โ”‚ Word limit: 25,000 words max (trim_context) โ”‚ โ”‚ โ”‚ โ”‚ Default: breadth=4, depth=2 โ†’ up to 4+8=12 queries โ”‚ โ”‚ Plus each creates its own sub-queries internally โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Key Implementation Details

Detailed Report Mode

The detailed report mode (ReportType.DetailedReport) generates a multi-section report:

  1. conduct_research() โ€” initial broad research
  2. get_subtopics() โ€” LLM generates subtopic headers using construct_subtopics()
  3. For each subtopic:
    • get_draft_section_titles() โ€” LLM generates H3 headers
    • get_similar_written_contents() โ€” find related previous sections
    • write_report() โ€” generate subtopic report with dedup awareness
  4. write_introduction() โ€” H1 + intro paragraph
  5. write_report_conclusion() โ€” summary + implications
Dedup Strategy

The subtopic report prompt explicitly instructs the LLM to check existing headers and written contents, avoid duplication, and highlight differences when covering similar topics. This is reinforced by passing existing_headers and relevant_written_contents directly into the prompt.

Report Types

TypeEnum ValueDescription
ResearchReportresearch_reportStandard comprehensive analysis
ResourceReportresource_reportBibliography-focused, analyzes each source
OutlineReportoutline_reportStructured outline with sections and key points
CustomReportcustom_reportUser-defined query prompt
DetailedReportdetailed_reportMulti-section with subtopic decomposition
SubtopicReportsubtopic_reportSingle subtopic section (internal use)
DeepResearchdeepRecursive deep research with learnings + citations

Report Source Options

SourceDescription
WebSearch + scrape from the internet
LocalLocal document files
AzureAzure Blob Storage documents
LangChainDocumentsPre-loaded LangChain Document objects
LangChainVectorStoreExisting vector store for retrieval
HybridLocal docs + web search combined

Configuration System

The Config class in gpt_researcher/config/config.py manages all settings with a layered override system:

Priority (highest โ†’ lowest): โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ 1. Environment variables (RETRIEVER=...) โ”‚ โ† Runtime overrides โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ 2. Custom config file (JSON) โ”‚ โ† User config โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ 3. DEFAULT_CONFIG (variables/default.py) โ”‚ โ† Built-in defaults โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Key Configuration Patterns

# LLM provider format: "provider:model"
FAST_LLM = "openai:gpt-4o-mini"
SMART_LLM = "openai:gpt-4o"
STRATEGIC_LLM = "openai:gpt-4o"

# Embedding format: "provider:model"
EMBEDDING = "openai:text-embedding-3-small"

# Retriever (comma-separated for multiple)
RETRIEVER = "tavily,google,arxiv"

# Deep research settings
DEEP_RESEARCH_BREADTH = 4
DEEP_RESEARCH_DEPTH = 2
DEEP_RESEARCH_CONCURRENCY = 2

# MCP strategy
MCP_STRATEGY = "fast"  # fast | deep | disabled

Smart Type Conversion

The convert_env_value() method uses Python's typing hints to auto-convert environment variables: str โ†’ string, int โ†’ int, bool โ†’ boolean ("true"/"1"/"yes"/"on"), List โ†’ JSON parse.

Prompt Engineering

All prompts are defined as static methods on the PromptFamily class in gpt_researcher/prompts.py. This is a centralized prompt registry pattern.

Key Prompt Methods

MethodPurposeNotable Instructions
generate_search_queries_prompt Generate sub-queries Asks for Google-style queries, includes current date, context-aware refinement
generate_report_prompt Main report writing Must determine own opinion, markdown headers, APA format, hyperlink citations, min word count, no TOC
generate_subtopic_report_prompt Subtopic sections Must avoid duplicating existing headers/content, explain differences from existing content, H2/H3 only
curate_sources Source curation Prioritize quantitative data, retain broad perspectives, never rewrite content
auto_agent_instructions Agent type selection Return JSON with server name + role prompt, emoji-based categorization
generate_deep_research_prompt Deep research synthesis Synthesize hierarchical research, prioritize deeper-level insights, cross-branch connections
generate_mcp_tool_selection_prompt MCP tool picking Select exactly N tools, rank by relevance, return JSON with reasoning
๐Ÿ“‹ View: generate_report_prompt (Main Report Writing)
Information: "{context}" --- Using the above information, answer the following query or task: "{question}" in a detailed report -- The report should focus on the answer to the query, should be well structured, informative, in-depth, and comprehensive, with facts and numbers if available and at least {total_words} words. Please follow all of the following guidelines: - You MUST determine your own concrete and valid opinion based on the given information. - You MUST write the report with markdown syntax and {report_format} format. - Structure your report with clear markdown headers: # for main title, ## for major sections, ### for subsections. - Use markdown tables when presenting structured data or comparisons. - You MUST prioritize the relevance, reliability, and significance of the sources. - You must also prioritize new articles over older articles. - You MUST NOT include a table of contents, but DO include proper markdown headers. - Use in-text citation references in {report_format} format with markdown hyperlink. - {reference_prompt} - {tone_prompt} You MUST write the report in the following language: {language}. Assume that the current date is {date}.
๐Ÿ“‹ View: curate_sources (Source Curation)
Your goal is to evaluate and curate the provided scraped content for the research task: "{query}" while prioritizing the inclusion of relevant and high-quality information, especially sources containing statistics, numbers, or concrete data. EVALUATION GUIDELINES: 1. Relevance: Include sources directly or partially connected. Err on the side of inclusion. 2. Credibility: Favor authoritative sources but retain others unless clearly untrustworthy. 3. Currency: Prefer recent information unless older data is essential. 4. Objectivity: Retain sources with bias if they provide unique perspective. 5. Quantitative Value: Give higher priority to sources with statistics or concrete data. CONTENT RETENTION: - DO NOT rewrite, summarize, or condense any source content. - Retain all usable information, cleaning up only clear garbage or formatting issues. - Keep marginally relevant sources if they contain valuable data or insights.

Prompt Families

GPT-Researcher supports model-specific prompt families that override formatting for particular LLMs:

FamilyTargetCustomization
PromptFamily (Default)General modelsStandard markdown formatting
GranitePromptFamilyIBM Granite (auto-detects version)Dispatches to version-specific family
Granite3PromptFamilyGranite 3.xCustom document prefix/suffix tags <|start_of_role|>documents<|end_of_role|>
Granite33PromptFamilyGranite 3.3Per-document ID tags with <|start_of_role|>document{"document_id": "..."}
Pattern

This is a Strategy Pattern for prompts. The get_prompt_family() factory function maps family names to classes. Each family must retain the same method signatures but can override implementations. This allows model-specific document formatting without changing agent logic.

Strengths

โœ… Strengths

Weaknesses

โš ๏ธ Weaknesses

Design Patterns Identified

PatternUsageQuality
Mediator GPTResearcher as central hub passing self to all skills Convenient but coupled
Strategy PromptFamily hierarchy for model-specific formatting Well-applied
Factory get_retriever(), GenericLLMProvider.from_provider(), Memory constructor Extensive & practical
State Machine LangGraph StateGraph for multi-agent workflow Industry-standard
Pipeline DocumentCompressorPipeline (split โ†’ filter โ†’ format) Clean LangChain pattern
Observer WebSocket streaming, log_handler, cost_callback Good event system
Recursive DeepResearchSkill.deep_research() with depth countdown Functional but simple
Semaphore Concurrency limiting in deep research and scraping Proper async pattern
Lazy Import Provider-specific imports only when needed Reduces startup cost

Final Verdict

Overall Assessment

GPT-Researcher is a feature-rich, production-viable research agent framework with impressive breadth of integration. Its greatest strength is the "batteries included" approach โ€” 27 LLM providers, 15 retrievers, 7 scrapers, MCP support, and multi-agent orchestration all out of the box.

The architecture is pragmatic rather than elegant. The GPTResearcher God Object and the dual single-agent/multi-agent codebases show the framework grew organically. The prompt engineering is functional but not sophisticated โ€” all prompts are f-strings in Python with no versioning or evaluation framework.

For teams building research agents, GPT-Researcher provides an excellent starting point and reference implementation. Its plugin architecture (retrievers, scrapers, LLM providers) is genuinely extensible. However, teams needing production reliability should invest in: (1) replacing the God Object with proper dependency injection, (2) adding structured logging and observability, (3) implementing prompt versioning, and (4) unifying the single-agent and multi-agent codepaths.

DimensionRatingNotes
ExtensibilityโญโญโญโญโญPluggable everything โ€” retrievers, LLMs, scrapers, prompts
ArchitectureโญโญโญFunctional but God Object + dual codebase
Code QualityโญโญโญWell-documented, but inconsistent patterns and runtime auto-install
MCP IntegrationโญโญโญโญSophisticated two-stage approach with strategy modes
Multi-AgentโญโญโญGood LangGraph implementation, but drifts from single-agent code
Production ReadinessโญโญโญCost tracking, streaming, retries โ€” but lacks observability and structured errors
Prompt EngineeringโญโญโญComprehensive prompts but hardcoded in Python, no evaluation
DocumentationโญโญโญโญGood docstrings, type hints, README โ€” but no architecture docs

Generated by Agent Deep Dive Analysis โ€ข Source: gpt-researcher v0.14.7 โ€ข Date: 2026-05-17