Open Deep Research

repository·main·Indexed 11 days ago

https://github.com/langchain-ai/open_deep_research

An open-source, configurable deep research agent designed for complex information gathering and report generation. Built with LangGraph, it orchestrates multi-step workflows including user clarification, research planning, parallel execution via researcher subgraphs, and final report synthesis. It supports various LLM providers, search APIs like Tavily, and Model Context Protocol (MCP) servers. Version 0.0.16.

Tokens
6.1K
Snippets
10
Records
20
Agent score
95%

What's inside Open Deep Research

  1. Quickstart: Install and run Open Deep Research locally

    main

    To run the Open Deep Research agent locally using the LangGraph server, follow these steps:

    1. Clone and Setup Environment:

      git clone https://github.com/langchain-ai/open_deep_research.git
      cd open_deep_research
      uv venv
      source .venv/bin/activate  # On Windows: .venv\Scripts\activate
    2. Install Dependencies:

      uv sync
      # or
      uv pip install -r pyproject.toml
    3. Configure Environment Variables: Create a .env file from the example to set up model providers, search tools, and other settings:

      cp .env.example .env
    4. Launch the LangGraph Server: Run the following command to start the server and open the LangGraph Studio UI:

      uvx --refresh --from "langgraph-cli[inmem]" --with-editable . --python 3.11 langgraph dev --allow-blocking

    Once launched, you can access:

    • Studio UI: https://smith.langchain.com/studio/?baseUrl=http://127.0.0.1:2024
    • API: http://127.0.0.1:2024
    • API Docs: http://127.0.0.1:2024/docs

    In the Studio UI, enter a question in the messages input field and click Submit. You can manage different configurations in the "Manage Assistants" tab.

    git clone https://github.com/langchain-ai/open_deep_research.git
    cd open_deep_research
    uv venv
    source .venv/bin/activate
    uv sync
    cp .env.example .env
    uvx --refresh --from "langgraph-cli[inmem]" --with-editable . --python 3.11 langgraph dev --allow-blocking
  2. Run and extract evaluations using LangSmith

    main

    To evaluate the agent against the Deep Research Bench (a dataset of 100 PhD-level tasks), follow these steps:

    1. Run Evaluation: Execute the evaluation script which runs the agent against the LangSmith dataset:

      python tests/run_evaluate.py

      This will generate a LangSmith experiment name (e.g., YOUR_EXPERIMENT_NAME).

    2. Extract Results: Convert the LangSmith experiment results into a JSONL file compatible with the Deep Research Bench:

      python tests/extract_langsmith_data.py --project-name "YOUR_EXPERIMENT_NAME" --model-name "you-model-name" --dataset-name "deep_research_bench"
    3. Submission: The resulting file will be located at tests/expt_results/deep_research_bench_model-name.jsonl. This file can then be submitted to the Deep Research Bench repository for official ranking.

    # Run evaluation
    python tests/run_evaluate.py
    
    # Extract results
    python tests/extract_langsmith_data.py --project-name "YOUR_EXPERIMENT_NAME" --model-name "you-model-name" --dataset-name "deep_research_bench"
  3. Deploy Open Deep Research to LangGraph Platform or OAP

    main

    There are several ways to deploy the agent for production or non-technical users:

    • LangGraph Platform: Deploy the agent directly to the managed LangGraph Platform for hosted execution.
    • Open Agent Platform (OAP): Use OAP to provide a UI for non-technical users to configure agents with custom MCP tools and search APIs.
      • To deploy your own instance of OAP and add the Deep Researcher, follow the guides at docs.oap.langchain.com.
    • LangGraph Studio: Best for local development and testing.
  4. Use the supervisor subgraph for research delegation

    main

    The supervisor_subgraph is a specialized workflow that manages the high-level research strategy. It uses a SupervisorState and can be integrated into larger graphs. It relies on three primary tool capabilities:

    • think_tool: Used for strategic reflection and planning.
    • ConductResearch: Used to delegate specific research topics to sub-researchers.
    • ResearchComplete: Used to signal that the supervisor is satisfied with the current findings.

    It respects the max_concurrent_research_units configuration to prevent resource exhaustion.

  5. Manage resource ownership with @auth.on hooks

    main

    LangGraph provides event hooks to manage access control and metadata for different resources. You can use these hooks to ensure users can only interact with their own data.

    Thread Hooks

    • @auth.on.threads.create and @auth.on.assistants.create: Use these to inject ownership metadata into the resource during creation. You modify the value object's metadata dictionary.
    • @auth.on.threads.read, .delete, .update, .search: Use these to return a filter object (e.g., {"owner": user_id}) that restricts the operation to resources matching that metadata.

    Assistant Hooks

    • @auth.on.assistants.create: Injects ownership metadata.
    • @auth.on.assistants.read, .delete, .update, .search: Returns a filter to restrict access.

    Store Hooks

    • @auth.on.store(): Used to authorize access to items in the LangGraph store. You can validate that the item's namespace matches the user's identity.

    Note: If the user is a StudioUser, these hooks should typically return early to allow full access.

    # Example: Setting ownership on thread creation
    @auth.on.threads.create
    async def on_thread_create(ctx: Auth.types.AuthContext, value: Auth.types.on.threads.create.value):
        if isinstance(ctx.user, StudioUser):
            return
        metadata = value.setdefault("metadata", {})
        metadata["owner"] = ctx.user.identity
    
    # Example: Filtering threads on read
    @auth.on.threads.read
    async def on_thread_read(ctx: Auth.types.AuthContext, value: Auth.types.on.threads.read.value):
        if isinstance(ctx.user, StudioUser):
            return
        return {"owner": ctx.user.identity}
  6. Use the researcher subgraph for focused research

    main

    The researcher_subgraph is a worker unit designed to handle a single research topic. It follows this flow:

    1. researcher: Uses tools like tavily_search, web_search, or MCP tools to gather data.
    2. researcher_tools: Executes the tool calls and handles the results.
    3. compress_research: Synthesizes the accumulated messages and tool outputs into a compressed_research summary.

    It outputs a ResearcherOutputState which contains the compressed findings and raw notes.

  7. How the override_reducer works

    main

    The override_reducer is a custom reducer function used in the state definitions to control how new data merges with existing state.

    By default, many state fields use operator.add (which appends to lists). However, override_reducer allows a node to explicitly replace a value. If the new_value is a dictionary containing {"type": "override"}, the reducer will return the value associated with the "value" key instead of appending it.

    Logic:

    • If new_value is a dict with type == "override": Return new_value.get("value", new_value).
    • Otherwise: Return operator.add(current_value, new_value) (standard list/sequence appending).
    def override_reducer(current_value, new_value):
        """Reducer function that allows overriding values in state."""
        if isinstance(new_value, dict) and new_value.get("type") == "override":
            return new_value.get("value", new_value)
        else:
            return operator.add(current_value, new_value)
  8. How the Deep Research agent workflow works

    main

    The deep_researcher is a LangGraph-based agent that follows a multi-stage lifecycle to transform a user query into a comprehensive research report:

    1. Clarification (clarify_with_user): The agent analyzes the user's request. If allow_clarification is enabled in the configuration and the scope is unclear, it asks the user for more details. Otherwise, it proceeds.
    2. Planning (write_research_brief): The agent transforms the user's messages into a structured research_brief and initializes the supervisor with specific instructions.
    3. Execution (research_supervisor): A supervisor subgraph manages the research process. It breaks the brief into tasks and delegates them to multiple researcher subgraphs in parallel. The supervisor can use think_tool for planning, ConductResearch to delegate, or ResearchComplete to finish.
    4. Researching (researcher): Individual researchers use tools (search, MCP, think_tool) to gather information. Once a researcher finishes its task, it runs compress_research to synthesize its findings into a concise summary.
    5. Reporting (final_report_generation): The agent collects all compressed findings from all researchers and synthesizes them into a final, well-structured report.
  9. Configure Search APIs and MCP tools

    main

    You can customize how the agent searches for information using the search_api and mcp_config fields in the configuration.

    • Default: Uses the Tavily search API.
    • Capabilities: Supports full Model Context Protocol (MCP) compatibility and native web search for Anthropic and OpenAI models.

    Configuration can be managed through the LangGraph Studio UI or by modifying the configuration settings defined in src/open_deep_research/configuration.py.

  10. Configure LLM models for research tasks

    main

    Open Deep Research uses different LLMs for specific stages of the research process. These can be configured via the LangGraph Studio UI or by editing the configuration settings. All selected models must support structured outputs and tool calling.

    Supported roles include:

    • Summarization (default: openai:gpt-4.1-mini): Summarizes search API results.
    • Research (default: openai:gpt-4.1): Powers the search agent.
    • Compression (default: openai:gpt-4.1): Compresses research findings.
    • Final Report Model (default: openai:gpt-4.1): Writes the final report.

    Models are initialized using the init_chat_model() API. For OpenRouter or local models via Ollama, refer to the specific community setup guides in the repository issues.

  11. Example: AI Inference Market Analysis Report

    main

    This document serves as a demonstration of the output generated by the open_deep_research project. It showcases a comprehensive, multi-perspective research report on the 'AI Inference Market', illustrating how the system synthesizes data from various sources to create structured profiles, comparative analyses, and market outlooks.

    Key features demonstrated in this example include:

    • Market Overviews: High-level summaries of industry trends and growth projections.
    • Company Profiles: Deep dives into specific players (e.g., Fireworks.ai, Together.ai, Groq) covering technical differentiation, pricing tiers, and funding.
    • Comparative Benchmarking: Structured data (tables) comparing providers across metrics like Time To First Token (TTFT), Tokens/Second, and Cost per 1M tokens.
    • Source Attribution: Explicitly listing sources used to validate the research findings.
  12. Configure the Open Deep Research agent

    main

    The Configuration class is the primary way to manage settings for the Deep Research agent. It covers general agent behavior, research parameters, model selection, and MCP server integration. You can instantiate it directly or use the from_runnable_config method to load settings from a LangChain RunnableConfig or environment variables.

    from src.open_deep_research.configuration import Configuration
    
    # Example of manual configuration
    config = Configuration(
        max_researcher_iterations=10,
        search_api="tavily",
        research_model="openai:gpt-4o"
    )
    
    # Example of loading from a RunnableConfig (e.g., in a LangGraph node)
    # This will prioritize environment variables, then values in 'configurable'
    config = Configuration.from_runnable_config(runnable_config)