ChatGPTSoftwareInfra & DevOpsAI score · PendingAI-assisted edit · no obvious prompt-injection riskn8n.io

Host your own AI deep research agent with n8n, Apify and OpenAI o3

Form-based research query → recursive web search and scrape → reasoning model synthesis → Notion report

ExperiencedStepsWorkflowPromptTip
Who
Researchers and automation engineers who want to deploy OpenAI DeepResearch-like capabilities internally
You get
After a user submits a form, the workflow automatically performs multi-round web searches, content scraping, and reasoning synthesis to generate a structured research report saved to Notion
You need
n8n · apify · notion · gemini

Constraints

Prerequisites: accessible n8n instance; OpenAI API key (o3-mini or o1 series); Apify API key; Notion integration key with duplicated database template; optional Google Gemini API key. Import the template into n8n, configure credentials for each node, publish the workflow, and ensure the form URL is publicly accessible.

What they did

Author jimleuk built an n8n template replicating OpenAI's DeepResearch, based on David Zhang's open-source deep-research implementation. It uses n8n forms as the frontend, executes recursive sub-workflows for multi-round web search and scraping, leverages OpenAI o3-mini's reasoning capability to synthesize learnings into a Markdown report, and converts the output to Notion blocks for storage.

How it went

Author reports (author_report): depth=1 & breadth=2 takes ~5-10 minutes; depth=1 & breadth=3 takes ~15-20 minutes; depth=3 & breadth=5 takes 2+ hours. Cost increases exponentially with depth and breadth. Published on n8n.io with 79,870 views.

Worth knowing

1. Author explicitly chose Apify over Firecrawl.ai for cost and performance reasons, but users may swap in alternative search/scrape services; 2. Recursive looping relies on precise 'execute once' vs 'execute for each item' node settings—preserve these when modifying nodes; 3. Self-hosted n8n users may consider community nodes or martian/notionmd to replace LLM-based Notion block conversion for better efficiency; 4. Template LLM prompts have room for improvement—adjust for your use case; 5. Besides o3-mini, experiment with o1, Deepseek, and Gemini 2.0 reasoning models; 6. This site has not tested this workflow; reproduction=not_tested.

n8n workflow template

Structure checked · Not run-tested

Use “Import from File” in n8n, or copy the JSON and paste it into the editor. Connect your own accounts, then try test data. The template is inactive by default.

Setup and test checklist

Credentials to connect

  • OpenAI Chat Model node: connect OpenAI API credentials.
  • OpenAI Chat Model1 node: connect OpenAI API credentials.
  • OpenAI Chat Model2 node: connect OpenAI API credentials.
  • OpenAI Chat Model3 node: connect OpenAI API credentials.
  • OpenAI Chat Model4 node: connect OpenAI API credentials.
  • Create Row node: connect Notion API credentials.
  • Get Existing Row node: connect Notion API credentials.
  • Set In-Progress node: connect Notion API credentials.
  • Set Done node: connect Notion API credentials.
  • Google Gemini Chat Model node: connect Google Gemini/PaLM API credentials.
  • Upload to Notion Page node: connect Notion API credentials.
  • Get Existing Row1 node: connect Notion API credentials.
  • RAG Web Browser node: connect httpQueryAuth credentials.
  • RAG Web Browser node: connect HTTP Header Auth credentials.

Configuration to replace

  • Source template is n8n public workflow #2878 (~85 nodes). Keep inactive after import; verify triggers, expressions and external API endpoints.
  • Sticky-note guidance is informational; replace placeholders with your own accounts, sheet schemas or channel IDs.

Test input and expected output

  • Manually run the main path once in a test workspace and confirm credentialed nodes authenticate without errors.
  • Drive one synthetic/redacted sample through and check output fields and downstream writes before enabling in production.

Template changes

  • Author credential bindings, webhookId and execution data are removed; the workflow is inactive. Nodes, connections and original prompts are preserved. Not run-tested in n8n.
  • No business-logic edits; verify keys, quotas and privacy compliance before use.

Template retrieved: 2026-10-25

Steps

  1. Submit research query

    The user fills out a public form with a research question and selects depth (default 1, range 1-5) and breadth (default 2, range 1-5). After submission, an LLM generates up to 3 clarifying questions, collected via looping forms, then merged into a complete query.

    Execution prompt · Source text。Clarifying Questions node (Basic LLM Chain) text parameter

    =Given the following query from the user, ask some follow up questions to clarify the research direction. Return a maximum of 3 questions, but feel free to return less if the original query is clear: <query>{{ $json.prompt }}</query>`

    Execution prompt · Source text。Shared system message across Clarifying Questions, Generate SERP Queries, and DeepResearch Learnings nodes (messages.messageValues[0])

    =You are an expert researcher. Today is {{ $now.toLocaleString() }}. Follow these instructions when responding:
      - You may be asked to research subjects that is after your knowledge cutoff, assume the user is right when presented with news.
      - The user is a highly experienced analyst, no need to simplify it, be as detailed as possible and make sure your response is correct.
      - Be highly organized.
      - Suggest solutions that I didn't think about.
      - Be proactive and anticipate my needs.
      - Treat me as an expert in all subject matter.
      - Mistakes erode my trust, so be accurate and thorough.
      - Provide detailed explanations, I'm comfortable with lots of detail.
      - Value good arguments over authorities, the source is irrelevant.
      - Consider new technologies and contrarian ideas, not just the conventional wisdom.
      - You may use high levels of speculation or prediction, just flag it for me.
  2. Create placeholder report page in Notion

    From the merged query, an LLM generates a report title and description. A new page is created in the designated Notion database with status 'Not started' and the request ID recorded for later correlation.

    Execution prompt · Source text。Report Page Generator node (Basic LLM Chain) text parameter

    =Create a suitable title for the research report which will be created from the user's query.
    <query>{{ $json.query }}</query>
  3. Trigger deep research asynchronously

    The Execute Workflow node spawns a non-blocking sub-workflow to perform the deep research, while updating the Notion page status to 'In progress'. The user does not need to keep their browser open.

  4. Recursive search and knowledge accumulation

    The sub-workflow routes tasks via JobType Router. For each query: a Basic LLM Chain generates SERP queries → Apify RAG Web Browser performs search and page scraping → valid results are filtered → o3-mini extracts up to 3 learnings and follow-up questions. Learnings accumulate across iterations until the configured depth limit is reached.

    Execution prompt · Source text。Generate SERP Queries node (Basic LLM Chain) text parameter

    =Given the following prompt from the user, generate a list of SERP queries to research the topic.
    Reduce the number of words in each query to its keywords only.
    Return a maximum of {{ $('JobType Router').first().json.data.breadth }} queries, but feel free to return less if the original prompt is clear. Make sure each query is unique and not similar to each other: <prompt>{{ $('JobType Router').first().json.data.query.trim() }}</prompt>
    
    {{
    $('JobType Router').first().json.data.learnings.length
      ? `Here are some learnings from previous research, use them to generate more specific queries:\n${$('JobType Router').first().json.data.learnings.map(text => `* ${text}`).join('\n')}`
      : ''
    }}

    Execution prompt · Source text。DeepResearch Learnings node (Basic LLM Chain) text parameter

    =Given the following contents from a SERP search for the query <query>{{ $('Item Ref').first().json.query }}</query>, generate a list of learnings from the contents. Return a maximum of 3 learnings, but feel free to return less if the contents are clear. Make sure each learning is unique and not similar to each other. The learnings should be concise and to the point, as detailed and infromation dense as possible. Make sure to include any entities like people, places, companies, products, things, etc in the learnings, as well as any exact metrics, numbers, or dates. The learnings will be used to research the topic further.
    
    <contents>
    {{
    $input
      .all()
      .map(item =>`<content>\n${item.json.markdown.substr(0, 25_000)}\n</content>`)
      .join('\n')
    }}
    </contents>
  5. Generate final research report

    All accumulated learnings are passed to o3-mini to generate a complete Markdown research report, targeting 3+ pages, including all learnings, using headings, lists, and tables where appropriate.

    Execution prompt · Source text。DeepResearch Report node (Basic LLM Chain) text parameter

    =You are are an expert and insightful researcher.
    * Given the following prompt from the user, write a final report on the topic using the learnings from research.
    * Make it as as detailed as possible, aim for 3 or more pages, include ALL the learnings from research.
    * Format the report in markdown. Use headings, lists and tables only and where appropriate.
    
    <prompt>{{ $('JobType Router').first().json.data.query }}</prompt>
    
    Here are all the learnings from previous research:
    
    <learnings>
    {{
    $('JobType Router').first().json.data
      .all_learnings
      .map(item => `<learning>${item}</learning>`)  
      .join('\n')
    }}
    </learnings>
  6. Convert to Notion block format

    The report is first converted to HTML via the Markdown node, then split into semantic fragments. Each fragment is sent to Google Gemini 2.0 Flash to convert into Notion API-compliant JSON blocks (headings, paragraphs, lists, tables). Meanwhile, a Code node batch-converts source URLs into bulleted_list_item blocks.

    Execution prompt · Source text。Notion Block Generator node (Basic LLM Chain) messages.messageValues[0].message parameter

    =Convert the following html into its equivalent Notion Block as per Notion's API schema.
    * Ensure the content is always included and remains the same.
    * Return only a json response.
    * Generate child-level blocks. Should not define "parent" or "children" property.
    * Strongly prefer headings, paragraphs, tables and lists type blocks.
    * available headings are heading_1, heading_2 and heading_3 - h4,h5,h6 should use heading_3 type instead. ensure headings use the rich text definition.
    * ensure lists blocks include all list items.
    
    ## Examples
    
    1. headings
    ```
    <h3 id="references">References</h3>
    ```
    would convert to 
    ```
    {"object":  "block", "type": "heading_3", "heading_3": { "rich_text": [{"type": "text","text": {"content": "References"}}]}}
    ```
    
    2. lists
    ```
    <ul><li>hello</li><li>world</li></ul>
    ```
    would convert to
    ```
    [
    {
      "object": "block",
      "type": "bulleted_list_item",
      "bulleted_list_item": {"rich_text": [{"type": "text","text": {"content": "hello"}}]}
    },
    {
      "object": "block",
      "type": "bulleted_list_item",
      "bulleted_list_item": {"rich_text": [{"type": "text","text": {"content": "world"}}]}
    }
    ]
    ```
    
    3. tables
    ```
    <table>
      <thead>
        <tr><th>Technology</th><th>Potential Impact</th></tr>
      </thead>
      <tbody>
        <tr>
          <td>5G Connectivity</td><td>Enables faster data speeds and advanced apps</td>
        </tr>
      </tbody>
    </table>
    ```
    would convert to
    ```
    {
      "object": "block",
      "type": "table",
      "table": {
        "table_width": 2,
        "has_column_header": true,
        "has_row_header": false,
        "children": [
          {
            "object": "block",
            "type": "table_row",
            "table_row": {
              "cells": [
                [
                  {
                    "type": "text",
                    "text": {
                      "content": "Technology",
                      "link": null
                    }
                  },
                  {
                    "type": "text",
                    "text": {
                      "content": "Potential Impact",
                      "link": null
                    }
                  }
                ],
                [
                  {
                    "type": "text",
                    "text": {
                      "content": "5G Connectivity",
                      "link": null
                    }
                  },
                  {
                    "type": "text",
                    "text": {
                      "content": "Enables faster data speeds and advanced apps",
                      "link": null
                    }
                  }
                ]
              ]
            }
          }
        ]
      }
    }
    ```
    4. anchor links
    Since Notion doesn't support anchor links, just convert them to rich text blocks instead.
    ```
    <a href="#module-0-pre-course-setup-and-learning-principles">Module 0: Pre-Course Setup and Learning Principles</a>
    ```
    converts to
    ```
    {
      "object": "block",
      "type": "paragraph",
      "paragraph": {
        "rich_text": [
          {
            "type": "text",
            "text": {
              "content": "Module 0: Pre-Course Setup and Learning Principles"
            }
          }
        ]
      }
    }
    ```
    5. Invalid html parts
    When the html is not syntax valid eg. orphaned closing tags, then just skip the conversion and use an empty rich text block.
    ```
    </li>\n</ol>
    ```
    can be substituted with
    ```
    {
      "object": "block",
      "type": "paragraph",
      "paragraph": {
        "rich_text": [
          {
            "type": "text",
            "text": {
              "content": " "
            }
          }
        ]
      }
    }
    ```
  7. Write to Notion and mark complete

    The HTTP Request node calls the Notion API to append blocks sequentially (with retry logic), then updates the page status to 'Done' and records the last updated timestamp.

Prompt you can copy

Setup guidance · Editorial suggestion。Hand to setup assistant to help user complete environment preparation and template import configuration

This block is the prompt. Ads are never placed here.

You are an n8n workflow setup assistant. The user wants to replicate the 'Host your own AI deep research agent' template. Assist in this order: 1) Confirm the user has a running n8n instance, OpenAI API key, Apify API key, Notion integration key, and duplicated database template; 2) Guide importing workflow.json and configuring five credential nodes (openAiApi, notionApi, googlePalmApi, httpQueryAuth, httpHeaderAuth); 3) Explain depth/breadth parameter impact on time and cost; 4) Remind to publish the workflow and make the form URL publicly accessible. Do not perform any API calls or credential entry on behalf of the user.

Before setup, confirm all external service credentials are ready. Apify Header Auth must use 'Bearer <api_key>' format.

Source

Host your own AI deep research agent with n8n, Apify and OpenAI o3 · jimleuk · n8n.io · 2025-02-11

Comments & feedback

Tried this method? Share results, problems or improvements. Comments appear after moderation. Please avoid sensitive information.

Loading…

    Related