This workflow corresponds to n8n.io template #6691 — we link there as the canonical source.
This workflow follows the Execute Workflow Trigger → HTTP Request recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "researcher",
"nodes": [
{
"parameters": {
"jsCode": "// The AI response is nested deeply. Extract the real payload.\nconst root = $input.all()[0].json;\n\n// Path: root.output[0].content[0].text.input\n\nlet input;\n\ntry {\n\tinput = root.output[0].content[0].text.input;\n} catch (e) {\n\tthrow new Error(\"Invalid AI response format. Could not extract input object.\");\n}\n\nif (!input || !input.query) {\n\tthrow new Error(\"Missing 'query' field in AI response.\");\n}\n\n// Validate query\nif (input.query.trim().length < 3) {\n\tthrow new Error(\"Query too short. Minimum 3 characters required.\");\n}\n\n// Clean and preprocess\nconst processedQuery = {\n\toriginal_query: input.query,\n\tcleaned_query: input.query.trim().replace(/\\s+/g, \" \"),\n\tquery_length: input.query.trim().length,\n\testimated_complexity: input.query.split(\" \").length > 10 ? \"high\" : \"medium\",\n\n\t// these come from the AI or default values\n\tsearch_scope: input.search_scope || \"academic_papers\",\n\tresponse_style: input.response_style || \"comprehensive\",\n\tlanguage: input.language || \"spanish\",\n\toutput_format: input.output_format || \"markdown\",\n\tpriority_level: input.priority_level || \"medium\",\n\tuser_email: input.user_email || null,\n\n\tsession_id: `rag_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n\ttimestamp: new Date().toISOString(),\n\tprocessing_steps: []\n};\n\n// Add metadata step\nprocessedQuery.processing_steps.push({\n\tstep: \"input_validation\",\n\tstatus: \"completed\",\n\ttimestamp: new Date().toISOString()\n});\n\n// Keywords extraction\nprocessedQuery.search_keywords = processedQuery.cleaned_query\n\t.toLowerCase()\n\t.split(\" \")\n\t.filter(w => w.length > 3)\n\t.slice(0, 8);\n\n// Search strategy rules\nconst searchStrategies = {\n\tweb_general: [\"google\", \"bing\", \"duckduckgo\"],\n\tacademic_papers: [\"scholar\", \"arxiv\", \"pubmed\"],\n\tnews_articles: [\"news_api\", \"rss_feeds\"],\n\ttechnical_docs: [\"github\", \"stackoverflow\", \"documentation\"],\n\tcompany_internal: [\"drive\", \"confluence\", \"notion\"],\n\tmulti_source: [\"google\", \"scholar\", \"news_api\", \"github\"]\n};\n\nprocessedQuery.search_strategy =\n\tsearchStrategies[processedQuery.search_scope] || [\"google\"];\n\nreturn [{ json: processedQuery }];\n"
},
"id": "de5b5d88-8e1e-4bfc-91bf-905d709a6cb9",
"name": "\ud83d\udd0d Query Preprocessor",
"type": "n8n-nodes-base.code",
"position": [
1168,
912
],
"typeVersion": 2
},
{
"parameters": {
"workflowInputs": {
"values": [
{
"name": "query"
}
]
}
},
"type": "n8n-nodes-base.executeWorkflowTrigger",
"typeVersion": 1.1,
"position": [
608,
912
],
"id": "a10a0295-f097-45dd-a6a7-1acd89120ca6",
"name": "When Executed by Another Workflow"
},
{
"parameters": {
"modelId": {
"__rl": true,
"value": "gpt-3.5-turbo",
"mode": "list",
"cachedResultName": "GPT-3.5-TURBO"
},
"responses": {
"values": [
{
"content": "={{ $json.query }}"
},
{
"role": "system",
"content": "Eres un m\u00f3dulo cuyo \u00fanico prop\u00f3sito es transformar una consulta simple del usuario en un objeto JSON limpio bajo la clave \u201cinput\u201d.\nSi el usuario solo entrega \"query\", debes rellenar el resto de campos con valores por defecto:\n\nsearch_scope: \u201cacademic_papers\u201d\n\nresponse_style: \u201ccomprehensive\u201d\n\nlanguage: \u201cspanish\u201d\n\noutput_format: \u201cmarkdown\u201d\n\npriority_level: \u201cmedium\u201d\n\nuser_email: null\nDevuelve exclusivamente un JSON v\u00e1lido que cumpla exactamente el esquema.\nNunca agregues texto adicional, markdown o comillas externas."
}
]
},
"builtInTools": {},
"options": {
"textFormat": {
"textOptions": {
"type": "json_object"
}
}
}
},
"type": "@n8n/n8n-nodes-langchain.openAi",
"typeVersion": 2,
"position": [
848,
912
],
"id": "f3b12b03-b5e7-4592-856e-786d9917f701",
"name": "Message a model",
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"url": "https://api.crossref.org/works",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "query",
"value": "={{ $json.cleaned_query }}"
},
{
"name": "rows",
"value": "10"
},
{
"name": "sort",
"value": "relevance"
},
{
"name": "order",
"value": "desc"
}
]
},
"options": {
"timeout": 30000
}
},
"id": "9a805200-52bb-4e8b-8435-87be41b23c40",
"name": "crossref",
"type": "n8n-nodes-base.httpRequest",
"position": [
1488,
816
],
"typeVersion": 4.2
},
{
"parameters": {
"url": "http://export.arxiv.org/api/query?search_query=all:KEYWORDS",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "query",
"value": "={{ $json.cleaned_query }}"
},
{
"name": "rows",
"value": "10"
},
{
"name": "sort",
"value": "relevance"
},
{
"name": "order",
"value": "desc"
}
]
},
"options": {
"timeout": 30000
}
},
"id": "2a12c61b-1df7-4d9c-8161-2289c8007ce5",
"name": "arxiv",
"type": "n8n-nodes-base.httpRequest",
"position": [
1488,
1024
],
"typeVersion": 4.2
},
{
"parameters": {
"numberInputs": 3
},
"type": "n8n-nodes-base.merge",
"typeVersion": 3.2,
"position": [
1760,
912
],
"id": "4179be24-fbbd-43ad-baf1-6b1abae11db6",
"name": "Merge"
},
{
"parameters": {
"aggregate": "aggregateAllItemData",
"options": {}
},
"type": "n8n-nodes-base.aggregate",
"typeVersion": 1,
"position": [
1968,
928
],
"id": "e38d2787-f834-40ef-afd4-6c00aae0e0a5",
"name": "Aggregate"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "ae59c557-cc80-43db-9474-7b5df39ac719",
"name": "data",
"value": "={{$json}}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
2272,
928
],
"id": "9a03aab3-b65b-40c4-9f27-fecec7e3a8a9",
"name": "stringer"
},
{
"parameters": {
"jsCode": "// 1. Obtener el string JSON\nconst raw = $json.data;\n\n// 2. Parsearlo a objeto real\nconst parsed = JSON.parse(raw);\n\n// 3. Obtener la lista de \u00edtems de Crossref\nconst items = parsed.data[0].message.items;\n\n// 4. Mapeamos la informaci\u00f3n que necesitas y convertimos a string\nconst referencias = items.map(item => {\n const titulo = item.title?.[0] || \"N/A\";\n const a\u00f1o = item.issued?.[\"date-parts\"]?.[0]?.[0] || \"N/A\";\n const fuente = item.DOI || item.URL || \"N/A\";\n const resumen = item.abstract || \"N/A\";\n\n return `T\u00edtulo: ${titulo}\nA\u00f1o: ${a\u00f1o}\nFuente: ${fuente}\nResumen: ${resumen}\n-------------------------------------`;\n});\n\n// 5. Unir todo en un solo string\nconst resultadoFinal = referencias.join(\"\\n\");\n\n// 6. Retornar como un \u00fanico string\nreturn [\n {\n json: {\n formatted: resultadoFinal\n }\n }\n];\n"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2528,
928
],
"id": "4c635655-1532-4303-88d0-0ab733ddb710",
"name": "parse info"
},
{
"parameters": {
"modelId": {
"__rl": true,
"value": "gpt-4",
"mode": "list",
"cachedResultName": "GPT-4"
},
"responses": {
"values": [
{
"role": "system",
"content": "=You are an expert assistant specialized in summarizing and presenting bibliographic search results in a clean, friendly and well-structured format.\n\nYour task:\nGiven a list of article entries provided by the user (titles, years, summaries, sources, etc.), generate a well-written report that is:\n\n1. Clear, easy to read, and segmented into sections.\n2. Free of hallucinations \u2014 only use information explicitly contained in the user message.\n3. Written in a friendly tone with light emojis where appropriate (no exaggeration).\n4. Well formatted with spacing, headings, bullet points, and readable structure.\n5. Focused on presenting:\n \u2013 What articles were found \n \u2013 What each article is about (based on the summary provided) \n \u2013 Any notable ideas, themes or patterns \n \u2013 If information is missing (e.g., \u201cN/A\u201d), acknowledge it naturally.\n\nRules:\n- Do NOT invent information that is not in the user message.\n- Do NOT cite external sources.\n- If the provided list contains many items, group and summarize them intelligently.\n- If the list contains few items, describe them individually with slightly more detail.\n- If the user provides no valid articles, return a friendly message indicating that no relevant information was found.\n\nOutput:\nA polished, structured narrative summary of the articles sent by the user.\n"
},
{
"content": "={{ $('When Executed by Another Workflow').item.json.query }}\n\nEsto es lo que encontr\u00f3:\n\n{{ $json.formatted }}\n"
}
]
},
"builtInTools": {},
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.openAi",
"typeVersion": 2,
"position": [
2768,
928
],
"id": "089e320e-4989-44d5-90e5-03a5783aec7f",
"name": "formatter",
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "4e2923db-efb5-4c9a-a44c-613c282b9367",
"name": "response",
"value": "={{ $json.output[0].content[0].text }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
3072,
928
],
"id": "34197170-c97a-42be-8cc1-edc32fd9134e",
"name": "formateado"
}
],
"connections": {
"\ud83d\udd0d Query Preprocessor": {
"main": [
[
{
"node": "crossref",
"type": "main",
"index": 0
},
{
"node": "arxiv",
"type": "main",
"index": 0
}
]
]
},
"When Executed by Another Workflow": {
"main": [
[
{
"node": "Message a model",
"type": "main",
"index": 0
}
]
]
},
"Message a model": {
"main": [
[
{
"node": "\ud83d\udd0d Query Preprocessor",
"type": "main",
"index": 0
}
]
]
},
"crossref": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"arxiv": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"Merge": {
"main": [
[
{
"node": "Aggregate",
"type": "main",
"index": 0
}
]
]
},
"Aggregate": {
"main": [
[
{
"node": "stringer",
"type": "main",
"index": 0
}
]
]
},
"stringer": {
"main": [
[
{
"node": "parse info",
"type": "main",
"index": 0
}
]
]
},
"parse info": {
"main": [
[
{
"node": "formatter",
"type": "main",
"index": 0
}
]
]
},
"formatter": {
"main": [
[
{
"node": "formateado",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {},
"versionId": "7e4ad840-8467-4c39-9304-1ede1db60dc6",
"meta": {
"templateId": "6691",
"templateCredsSetupCompleted": true
},
"id": "iExTpMqatjBL5Jm9",
"tags": []
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
openAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
researcher. Uses executeWorkflowTrigger, openAi, httpRequest. Event-driven trigger; 11 nodes.
Source: https://github.com/vaskiax/LOW_AI_AGENT/blob/338414e7047696aaef95554ba302fd36a5041f7f/workflows/researcher.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
How it Works
The best content automation template in the market is now even better—with “deep research” on time-sensitive topics\! Unlike most n8n content automation templates that are mainly for “demo purposes,”
Template Carnaval - time instagram. Uses toolWorkflow, lmChatOpenAi, memoryBufferWindow, agent. Event-driven trigger; 56 nodes.
This workflow is a fully automated YouTube Shorts production pipeline. It takes the structured output from a video digestion workflow (transcript, key moments, metadata) and produces finished, rendere
Code Schedule. Uses memoryBufferWindow, agent, stickyNote, outputParserStructured. Event-driven trigger; 45 nodes.