Merge branch 'main' into NODE-1256

This commit is contained in:
freakwriter 2024-06-24 09:51:23 -04:00
commit 95b01cce01
179 changed files with 2807 additions and 1123 deletions

View File

@ -5,4 +5,4 @@ Vocab = default
BasedOnStyles = from-write-good, n8n-styles, from-microsoft, Vale
Vale.Terms = NO
from-alex.Profanity = NO
TokenIgnores = (\-\-8\<\-\- \".*\"), (-only), (\*\*.*\*\*), (\*\*Release date:\*\*.*), (\[\[\%.*\%\]\]), (\[.*\]\(.*\)), (\[.*\]\(.*\)\{:target=_blank .external-link\}), (\[\[.*\]\]), (Rocket\.Chat), (\(https.*\))
TokenIgnores = (\-\-8\<\-\- \".*\"), (-only), (\*\*.*\*\*), (\*\*Release date:\*\*.*), (\[\[\%.*\%\]\]), (\[.*\]\(.*\)\{:target=_blank .external-link\}), (\[\[.*\]\]), (Rocket\.Chat), (\(https.*\)), (how\smany), (too\smany)

View File

@ -7,15 +7,6 @@
<!-- Header -->
<header class="{{ class }}" data-md-component="header">
<nav class="md-tabs n8n-top-nav" aria-label="{{ lang.t('tabs') }}" data-md-component="tabs">
<div class="md-grid">
<ul class="md-tabs__list n8n-top-nav-list" >
<li class="md-tabs__item"><a href="https://n8n.io/" class="md-tabs__link" target="_blank">n8n home</a></li>
<li class="md-tabs__item"><a href="https://community.n8n.io/" class="md-tabs__link" target="_blank">Forum</a></li>
<li class="md-tabs__item"><a href="https://blog.n8n.io/" class="md-tabs__link" target="_blank">Blog</a></li>
</ul>
</div>
</nav>
<nav
class="md-header__inner md-grid"
aria-label="{{ lang.t('header.title') }}"

View File

@ -0,0 +1,16 @@
{% import "partials/tabs-item.html" as item with context %}
<nav class="md-tabs" aria-label="{{ lang.t('tabs') }}" data-md-component="tabs">
<div class="md-grid n8n-other-sites">
<ul class="md-tabs__list">
{% for nav_item in nav %}
{{ item.render(nav_item) }}
{% endfor %}
</ul>
<!-- start n8n customisation -->
<ul class="md-tabs__list">
<li class="md-tabs__item"><a href="https://n8n.io/" class="md-tabs__link" target="_blank">n8n home ↗</a></li>
<li class="md-tabs__item"><a href="https://community.n8n.io/" class="md-tabs__link" target="_blank">Forum ↗</a></li>
<li class="md-tabs__item"><a href="https://blog.n8n.io/" class="md-tabs__link" target="_blank">Blog ↗</a></li>
</ul>
</div>
</nav>

View File

@ -0,0 +1,5 @@
This node is useful when you:
* Can't add a memory node directly.
* Need to do more complex memory management, beyond what the memory nodes offer. For example, you can add this node to check the memory size of the Agent node's response, and reduce it if needed.
* Want to inject messages to the AI that look like user messages, to give the AI more context.

View File

@ -5,7 +5,7 @@ Vector Store nodes in n8n have three modes: **Get Many**, **Insert Documents** a
<!-- vale off -->
#### Get Many
In this mode, you can retrieve multiple documents from your vector database by providing a prompt. The prompt will be embedded and used for similarity search. The node will return the documents that are most similar to the prompt with their similarity score. This is useful if you want to retrieve a list of similar documents and pass them to a chain as additional context.
In this mode, you can retrieve multiple documents from your vector database by providing a prompt. The prompt will be embedded and used for similarity search. The node will return the documents that are most similar to the prompt with their similarity score. This is useful if you want to retrieve a list of similar documents and pass them to an agent as additional context.
<!-- vale on -->
#### Insert Documents

Binary file not shown.

View File

@ -239,15 +239,13 @@
margin-top: 1.75em;
}
/* extra top nav */
/* The tab links for other n8n sites */
.n8n-top-nav {
margin-bottom:1em;
.n8n-other-sites {
display: flex;
justify-content: space-between;
}
.n8n-top-nav-list {
border-bottom: 1px solid #707183;
}
/* ensure headings don't disappear below top nav after adding extra top nav */
@media screen and (min-width: 76.25em) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 900 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 554 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 329 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 371 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 179 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 775 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 891 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 280 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 532 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 584 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 957 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 471 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 822 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

View File

@ -0,0 +1 @@
If you add more than one [[ page.meta.title ]] node to your workflow, all nodes access the same memory instance by default. Be careful when doing destructive actions that override existing memory contents, such as the override all messages operation in the Chat Memory Manager node. If you want more than one memory instance in your workflow, set different session IDs in different memory nodes.

View File

@ -0,0 +1,718 @@
{
"name": "Populate a Pinecone vector database from a website",
"nodes": [
{
"parameters": {
"model": "text-embedding-3-large",
"options": {},
"requestOptions": {}
},
"id": "856f2426-b4b5-4180-a422-d26692844afb",
"name": "Embeddings OpenAI",
"type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
"typeVersion": 1,
"position": [
80,
1040
],
"credentials": {
"openAiApi": {
"id": "tW3bkXa0SAK0OzvR",
"name": "OpenAi account Debs"
}
}
},
{
"parameters": {
"options": {},
"requestOptions": {}
},
"id": "1e702984-6f79-416e-981a-6728d4b3c233",
"name": "Default Data Loader",
"type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader",
"typeVersion": 1,
"position": [
260,
960
]
},
{
"parameters": {
"options": {
"splitCode": "markdown"
},
"requestOptions": {}
},
"id": "2d1f30fd-f251-4389-8f6d-2c950018a91f",
"name": "Recursive Character Text Splitter",
"type": "@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter",
"typeVersion": 1,
"position": [
300,
1160
]
},
{
"parameters": {
"batchSize": 10,
"options": {}
},
"id": "4e8a9d4c-6009-4d9b-b603-0438c65ba9df",
"name": "Loop Over Items",
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
-840,
1040
]
},
{
"parameters": {
"model": {
"__rl": true,
"value": "gpt-4o",
"mode": "list",
"cachedResultName": "gpt-4o"
},
"options": {},
"requestOptions": {}
},
"id": "e7967355-41b4-4bc5-b192-c8bc0699e925",
"name": "OpenAI Model",
"type": "@n8n/n8n-nodes-langchain.lmOpenAi",
"typeVersion": 1,
"position": [
-1320,
1680
],
"credentials": {
"openAiApi": {
"id": "tW3bkXa0SAK0OzvR",
"name": "OpenAi account Debs"
}
}
},
{
"parameters": {
"url": "https://n8n-io.github.io/n8n-demo-website/sitemap.xml",
"options": {}
},
"id": "5fb88663-f28b-4da2-acd9-1cbb0c5d28e7",
"name": "Get sitemap",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-1480,
740
]
},
{
"parameters": {
"options": {
"explicitRoot": false,
"ignoreAttrs": true
}
},
"id": "0e6287b8-9a65-4af0-8e69-3aae3648fd13",
"name": "Turn XML sitemap into JSON",
"type": "n8n-nodes-base.xml",
"typeVersion": 1,
"position": [
-1260,
740
]
},
{
"parameters": {
"fieldToSplitOut": "url",
"options": {}
},
"id": "acd3e717-99f5-4238-aa4d-795caef660b1",
"name": "Turn the URL array into multiple items",
"type": "n8n-nodes-base.splitOut",
"typeVersion": 1,
"position": [
-1040,
740
]
},
{
"parameters": {},
"id": "f3b4ad5e-b261-4b97-9077-3b9259d5b37d",
"name": "Wait 5 seconds",
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
-320,
1060
],
"webhookId": "f4e7dead-77ad-4216-a5a0-ef95914bf3ab"
},
{
"parameters": {
"url": "={{ $json.loc }}",
"options": {}
},
"id": "361b2a70-d0c5-4498-8a70-0688710e76e6",
"name": "Get pages listed in the sitemap",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-580,
1060
]
},
{
"parameters": {},
"id": "14ddd282-9bf0-459f-9595-5154e16f9cc0",
"name": "Chat Trigger",
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
"typeVersion": 1,
"position": [
-1620,
1420
],
"webhookId": "4b338d3c-b03f-42f2-94c1-9353d0f1fbc2"
},
{
"parameters": {
"promptType": "define",
"text": "={{ $('Chat Trigger').item.json.chatInput }}"
},
"id": "263585e6-02bb-4940-9bb3-15f32b0f8079",
"name": "Question and Answer Chain",
"type": "@n8n/n8n-nodes-langchain.chainRetrievalQa",
"typeVersion": 1.3,
"position": [
-1280,
1420
]
},
{
"parameters": {
"topK": 10,
"requestOptions": {}
},
"id": "91ad53ec-a761-43f6-a6f1-835263222e0c",
"name": "Vector Store Retriever",
"type": "@n8n/n8n-nodes-langchain.retrieverVectorStore",
"typeVersion": 1,
"position": [
-1080,
1620
]
},
{
"parameters": {
"model": "text-embedding-3-large",
"options": {},
"requestOptions": {}
},
"id": "5c55cb38-be26-405d-bd39-d29e0a33b683",
"name": "Embeddings OpenAI2",
"type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
"typeVersion": 1,
"position": [
-780,
2040
],
"credentials": {
"openAiApi": {
"id": "tW3bkXa0SAK0OzvR",
"name": "OpenAi account Debs"
}
}
},
{
"parameters": {
"fieldsToAggregate": {
"fieldToAggregate": [
{
"fieldToAggregate": "content"
}
]
},
"options": {}
},
"id": "48dbd7f7-1ca1-41e2-9fd5-e916ea76589b",
"name": "Aggregate",
"type": "n8n-nodes-base.aggregate",
"typeVersion": 1,
"position": [
-100,
740
]
},
{
"parameters": {
"content": "**Aggregate into one item**\n\nThe Pinecone node loops over each input item. This is standard n8n node behavior.\n\nThis means if you want to use the **Clear namespace** setting in the Pinecone node, you need to input a single item.",
"height": 381.66422439067196,
"color": 5
},
"id": "5b70d4ae-1889-43d3-b92d-bf73e43236bd",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-160,
520
]
},
{
"parameters": {
"content": "### Workflow to scrape data and send it to Pinecone",
"height": 878.8927796727229,
"width": 2382.6739342193496,
"color": 7
},
"id": "e9b5d557-51af-48d1-af33-8783f9ca3718",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1856.703373323493,
480
]
},
{
"parameters": {
"content": "### Workflow to chat and get answers from the Pinecone vector database",
"height": 825.9872504327399,
"width": 1181.407211476183,
"color": 7
},
"id": "7efa097b-d4f2-49a4-9da5-4fcf6b83be3b",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1680,
1380
]
},
{
"parameters": {
"content": "## Try it out \n\n1. Set credentials and choose your Pinecone vector database. See the notes on individual nodes for details.\n2. Select **Test workflow** to run the main workflow and load data into Pinecone.\n3. Select **Chat** and try asking:\n\n_What is the purpose of the n8n demo website?_",
"height": 326.49681260818465,
"color": 4
},
"id": "f21bc32b-a405-4d71-b6c9-7bffbb6faed9",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-2040,
560
]
},
{
"parameters": {
"content": "**Setup**\n\n1. In Pinecone, create a vector database. Set **Dimensions** to `3072` and **Metric** to `cosine`. You can use the free starter plan.\n2. In the Pinecone node, set your credentials.\n3. Select your Pinecone index.",
"height": 381.3701016273242,
"width": 304.1011298750183,
"color": 2
},
"id": "4be87782-f811-418f-b4b5-9e12c4cf7970",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
140,
520
]
},
{
"parameters": {
"mode": "insert",
"pineconeIndex": {
},
"options": {
"clearNamespace": true,
"pineconeNamespace": "test-web-scraper"
}
},
"id": "94035a97-5a09-493c-aaae-dcba7bbf8526",
"name": "Pinecone Vector Store",
"type": "@n8n/n8n-nodes-langchain.vectorStorePinecone",
"typeVersion": 1,
"position": [
160,
740
],
"credentials": {
"pineconeApi": {
"id": "lruA9GaKZSEY8dky",
"name": "Debs Pinecone"
}
}
},
{
"parameters": {
"content": "## Next steps\n\nLearn more about [Advanced AI in n8n](https://docs.n8n.io/advanced-ai/)",
"width": 331.8066536811489
},
"id": "2be1433b-0488-4c7e-8c10-e771d4dd4686",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
460,
1280
]
},
{
"parameters": {
"content": "**Set your credentials**",
"height": 206.68134932939768,
"width": 182.42633582707612,
"color": 2
},
"id": "fffbb04d-6d61-4dfa-bfd3-46b8c92a36d5",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
20,
1000
]
},
{
"parameters": {
"content": "**Set your credentials**",
"height": 184.89671964234537,
"width": 173.09006596119673,
"color": 2
},
"id": "810ac5e1-d730-47af-9282-64ab0b4fca16",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1369.107685156473,
1620.2285847094058
]
},
{
"parameters": {
"content": "**Set your credentials**",
"height": 192.67694453057842,
"width": 221.3274602682409,
"color": 2
},
"id": "2cecc8ac-3c65-4294-8a5d-2842bc07d10a",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-860,
1980
]
},
{
"parameters": {
"pineconeIndex": {
"__rl": true,
"value": "debs-test",
"mode": "list",
"cachedResultName": "debs-test"
},
"options": {
"pineconeNamespace": "test-web-scraper"
}
},
"id": "e673c46e-0815-4b58-9a8f-2fb86445b578",
"name": "Pinecone Vector Store2",
"type": "@n8n/n8n-nodes-langchain.vectorStorePinecone",
"typeVersion": 1,
"position": [
-980,
1840
],
"credentials": {
"pineconeApi": {
"id": "lruA9GaKZSEY8dky",
"name": "Debs Pinecone"
}
}
},
{
"parameters": {
"content": "**Set your credentials**\n\n**Select your Pinecone index***",
"width": 367.59568816702017,
"color": 2
},
"id": "ca4499ae-4e27-4848-9654-f7e744c081e7",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1080,
1760
]
},
{
"parameters": {},
"id": "b43ddbd1-adfd-4bba-bee5-4b81229e88dd",
"name": "Start the workflow by clicking \"Test workflow\"",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
-1700,
740
]
},
{
"parameters": {
"operation": "extractHtmlContent",
"extractionValues": {
"values": [
{
"key": "content",
"cssSelector": ".md-content",
"returnValue": "html"
}
]
},
"options": {
"trimValues": true,
"cleanUpText": true
}
},
"id": "d39624d7-93c0-4452-81b1-ffa04b216ceb",
"name": "Extract main content",
"type": "n8n-nodes-base.html",
"typeVersion": 1.2,
"position": [
-380,
740
]
},
{
"parameters": {
"content": "**Batch the calls to the website**\n\nFor the small demo website in this example, this is not essential. If you want to use this example with a larger website, batching like this helps avoid timeouts. Using the Wait node between batches avoids hitting the website with too many requests too fast.",
"height": 298.48800301054644,
"width": 316.2462039046831,
"color": 5
},
"id": "9825926d-ce6d-429e-9006-6ff5fd1f46ca",
"name": "Sticky Note10",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-1220,
1020
]
},
{
"parameters": {
"content": "## How to scrape a different website\n\nThis workflow uses a small example website provided by n8n. To use a different site:\n\n1. Change the sitemap URL in **Get sitemap**.\n2. Update **Extract main content** according to the HTML structure of the website you're scraping.",
"height": 356.06166718347
},
"id": "7c2e4bde-3900-49b0-9bee-704e34664163",
"name": "Sticky Note11",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-2040,
960
]
}
],
"pinData": {},
"connections": {
"Embeddings OpenAI": {
"ai_embedding": [
[
{
"node": "Pinecone Vector Store",
"type": "ai_embedding",
"index": 0
}
]
]
},
"Default Data Loader": {
"ai_document": [
[
{
"node": "Pinecone Vector Store",
"type": "ai_document",
"index": 0
}
]
]
},
"Recursive Character Text Splitter": {
"ai_textSplitter": [
[
{
"node": "Default Data Loader",
"type": "ai_textSplitter",
"index": 0
}
]
]
},
"Loop Over Items": {
"main": [
[
{
"node": "Extract main content",
"type": "main",
"index": 0
}
],
[
{
"node": "Get pages listed in the sitemap",
"type": "main",
"index": 0
}
]
]
},
"Get sitemap": {
"main": [
[
{
"node": "Turn XML sitemap into JSON",
"type": "main",
"index": 0
}
]
]
},
"Turn XML sitemap into JSON": {
"main": [
[
{
"node": "Turn the URL array into multiple items",
"type": "main",
"index": 0
}
]
]
},
"Turn the URL array into multiple items": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Wait 5 seconds": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Get pages listed in the sitemap": {
"main": [
[
{
"node": "Wait 5 seconds",
"type": "main",
"index": 0
}
]
]
},
"Chat Trigger": {
"main": [
[
{
"node": "Question and Answer Chain",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Model": {
"ai_languageModel": [
[
{
"node": "Question and Answer Chain",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Vector Store Retriever": {
"ai_retriever": [
[
{
"node": "Question and Answer Chain",
"type": "ai_retriever",
"index": 0
}
]
]
},
"Embeddings OpenAI2": {
"ai_embedding": [
[
{
"node": "Pinecone Vector Store2",
"type": "ai_embedding",
"index": 0
}
]
]
},
"Aggregate": {
"main": [
[
{
"node": "Pinecone Vector Store",
"type": "main",
"index": 0
}
]
]
},
"Pinecone Vector Store2": {
"ai_vectorStore": [
[
{
"node": "Vector Store Retriever",
"type": "ai_vectorStore",
"index": 0
}
]
]
},
"Start the workflow by clicking \"Test workflow\"": {
"main": [
[
{
"node": "Get sitemap",
"type": "main",
"index": 0
}
]
]
},
"Extract main content": {
"main": [
[
{
"node": "Aggregate",
"type": "main",
"index": 0
}
]
]
}
}
}

View File

@ -1,5 +1,5 @@
---
contentType: overview
contentType: explanation
title: Agents vs chains
description: A workflow example that demonstrates key differences between agents and chains.
workflowFile: advanced-ai/examples/agents_vs_chains.json

View File

@ -1,5 +1,5 @@
---
contentType: overview
contentType: howto
title: Call an API to fetch data
description: Use the n8n workflow tool to load data from an API using the HTTP Request node into your AI workflow.
workflowFile: advanced-ai/examples/let_your_ai_call_an_api.json

View File

@ -1,5 +1,5 @@
---
contentType: overview
contentType: howto
title: Set a human fallback for AI workflows
description: Have a workflow that triggers a human answer when the AI can't help.
workflowFile: advanced-ai/examples/ask_a_human.json

View File

@ -25,7 +25,20 @@ This section provides explanations of important AI concepts, and workflow templa
[:octicons-arrow-right-24: What is a tool in AI?](/advanced-ai/examples/understand-tools/)
[:octicons-arrow-right-24: Chat with Google Sheets](/advanced-ai/examples/data-google-sheets/)
[:octicons-arrow-right-24: Call an API to fetch data](/advanced-ai/examples/api-workflow-tool/)
[:octicons-arrow-right-24: Set up a human fallback](/advanced-ai/examples/human-fallback/)
[:octicons-arrow-right-24: Set up a human fallback](/advanced-ai/examples/human-fallback/)
- __Vector databases__
Learn about vector databases in AI, along with related concepts including embeddings and retrievers. Then try out an example that scrapes a website, loads date into a vector database, and allows you to chat with an AI that uses the data.
[:octicons-arrow-right-24: What is a vector database?](/advanced-ai/examples/understand-vector-databases/)
[:octicons-arrow-right-24: Populate a Pinecone vector database from a website](/advanced-ai/examples/vector-store-website/)
- __Memory__
Learn about memory in AI.
[:octicons-arrow-right-24: What is memory in AI?](/advanced-ai/examples/understand-memory/)
- __More concepts and examples coming soon__

View File

@ -14,7 +14,7 @@ Chains bring together different components of AI to create a cohesive system. Th
n8n provides three chain nodes:
* [Basic LLM Chain](/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.chainllm/): use to interact with an LLM, without any additional components.
* [Retrieval Q&A Chain](/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.chainretrievalqa/): can connect to a vector store using a retriever, or to an n8n workflow using the Workflow Retriever node. Use this if you want to create a workflow that supports asking questions about specific documents.
* [Question and Answer Chain](/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.chainretrievalqa/): can connect to a vector store using a retriever, or to an n8n workflow using the Workflow Retriever node. Use this if you want to create a workflow that supports asking questions about specific documents.
* [Summarization Chain](/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.chainsummarization/): takes an input and returns a summary.
There's an important difference between chains in n8n and in other tools such as LangChain: none of the chain nodes support memory. This means they can't remember previous user queries. If you use LangChain to code an AI application, you can give your application memory. In n8n, if you need your workflow to support memory, use an agent. This is essential if you want users to be able to have a natural ongoing conversation with your app.

View File

@ -0,0 +1,24 @@
---
title: What is memory in AI?
description: Understand memory in the context of AI. Learn what's special about memory in n8n.
contentType: explanation
---
# What is memory in AI?
Memory is a key part of AI chat services. The memory keeps a history of previous messages, allowing for an ongoing conversation with the AI, rather than every interaction starting fresh.
## AI memory in n8n
To add memory to your AI workflow you can use either:
* [Window Buffer Memory](/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.memorybufferwindow/): stores a customizable length of chat history for the current session. This is the easiest to get started with.
* One of the memory services that n8n provides nodes for. These include:
* [Motorhead](/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.memorymotorhead/)
* [Redis Chat Memory](/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.memoryredischat/)
* [Xata](/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.memoryxata/)
* [Zep](/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.memoryzep/)
If you need to do advanced AI memory management in your workflows, use the [Chat Memory Manager](/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.memorymanager/) node.
--8<-- "_snippets/integrations/builtin/cluster-nodes/langchain-sub-nodes/chat-memory-manager-purpose.md"

View File

@ -16,15 +16,16 @@ Here are a couple of other ways of expressing it:
> We can think of these tools as being almost like functions that your AI model can call ([source](https://www.udemy.com/course/chatgpt-and-langchain-the-complete-developers-masterclass/){:target=_blank .external-link})
## Tools in n8n
## AI tools in n8n
n8n provides tool sub-nodes that you can connect to your AI agent. As well as providing some popular tools, such as [Wikipedia](/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolwikipedia/) and [SerpAPI](/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolserpapi/), n8n provides two especially powerful tools:
n8n provides tool sub-nodes that you can connect to your AI agent. As well as providing some popular tools, such as [Wikipedia](/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolwikipedia/) and [SerpAPI](/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolserpapi/), n8n provides three especially powerful tools:
* [Custom n8n Workflow Tool](/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolworkflow/): use this to load any n8n workflow as a tool.
* [Custom Code Tool](/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolcode/): write code that your agent can run.
* [HTTP Request Tool](/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolhttprequest/): make calls to fetch a website or data from an API.
The next three examples highlight the Custom n8n Workflow Tool:
- [Chat with Google Sheets](/advanced-ai/examples/data-google-sheets/)
- [Call an API to fetch data](/advanced-ai/examples/api-workflow-tool/)
- [Set up a human fallback](/advanced-ai/examples/human-fallback/)
- [Set up a human fallback](/advanced-ai/examples/human-fallback/)

View File

@ -0,0 +1,52 @@
---
title: What are vector databases?
description: Understand vector databases. Learn how n8n provides vector databases, along with the key components to work with them, including embeddings, retrievers, and document loaders.
contentType: explanation
---
# What are vector databases?
Vector databases store information as numbers:
> A vector database is a type of database that stores data as high-dimensional vectors, which are mathematical representations of features or attributes. ([source](https://learn.microsoft.com/en-us/semantic-kernel/memories/vector-db){:target=_blank .external-link})
This enables fast and accurate similarity searches. With a vector database, instead of using conventional database queries, you can search for relevant data based on semantic and contextual meaning.
## A simplified example
A vector database could store the sentence "n8n is a source-available automation tool that you can self-host", but instead of storing it as text, the vector database stores an array of dimensions (numbers between 0 and 1) that represent its features. This doesn't mean turning each letter in the sentence into a number. Instead, the vectors in the vector database describe the sentence.
Suppose that in a vector store `0.1` represents `automation tool`, `0.2` represents `source available`, and `0.3` represents `can be self-hosted`. You could end up with the following vectors:
| Sentence | Vector (array of dimensions) |
| -------- | ------ |
| n8n is a source-available automation tool that you can self-host | [0.1, 0.2, 0.3] |
| Zapier is an automation tool | [0.1] |
| Make is an automation tool | [0.1] |
| Confluence is a wiki tool that you can self-host | [0.3] |
/// note | This example is very simplified
In practice, vectors are far more complex. A vector can range in size from tens to thousands of dimensions. The dimensions don't have a one-to-one relationship to a single feature, so you can't translate individual dimensions directly into single concepts. This example gives an approximate mental model, not a true technical understanding.
///
## Demonstrating the power of similarity search
Qdrant provide [vector search demos](https://qdrant.tech/demo/){:target=_blank .external-link} to help users understand the power of vector databases. The [food discovery demo](https://food-discovery.qdrant.tech/){:target=_blank .external-link} shows how a vector store can help match pictures based on visual similarities.
> This demo uses data from Delivery Service. Users may like or dislike the photo of a dish, and the app will recommend more similar meals based on how they look. It's also possible to choose to view results from the restaurants within the delivery radius. ([source](https://qdrant.tech/demo/){:target=_blank .external-link})
For full technical details, refer to the [Qdrant demo-food-discovery GitHub repository](https://github.com/qdrant/demo-food-discovery){:target=_blank .external-link}.
## Embeddings, retrievers, text splitters, and document loaders
Vector databases require other tools to function:
- Document loaders and text splitters: document loaders pull in documents and data, and prepare them for embedding. Document loaders can use text splitters to break documents into chunks.
- Embeddings: these are the tools that turn the data (text, images, and so on) into vectors, and back into raw data. Note that n8n only supports text embeddings.
- Retrievers: retrievers fetch documents from vector databases. You need to pair them with an embedding to translate the vectors back into data.

View File

@ -0,0 +1,29 @@
---
contentType: howto
title: Populate a Pinecone vector database from a website
description: Scrape a website, load the data into Pinecone, then query it using a chat workflow.
workflowFile: advanced-ai/examples/populate_a_pinecone_vector_database_from_a_website.json
---
# Populate a Pinecone vector database from a website
Use n8n to scrape a website, load the data into Pinecone, then query it using a chat workflow. This workflow uses the [HTTP node](/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/) to get website data, extracts the relevant content using the [HTML node](/integrations/builtin/core-nodes/n8n-nodes-base.html/), then uses the [Pinecone Vector Store node](/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.vectorstorepinecone/) to send it to Pinecone.
<figure markdown>
!["Screenshot of the two workflows in this example"](/_images/advanced-ai/examples/vector-store-website.png)
<figcaption markdown>[Download the example workflow](/_workflows/[[ page.meta.workflowFile ]])</figcaption>
</figure>
## Key features
This workflow uses:
* [HTTP node](/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/): fetches website data.
* [HTML node](/integrations/builtin/core-nodes/n8n-nodes-base.html/): simplifies the data by extracting the main content from the page.
* [Pinecone Vector Store node](/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.vectorstorepinecone/) and [Embeddings OpenAI](/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.embeddingsopenai/): transform the data into vectors and store it in Pinecone.
* [Chat Trigger](/integrations/builtin/core-nodes/n8n-nodes-langchain.chattrigger/) and [Question and Answer Chain](/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.chainretrievalqa/) to query the vector database.
## Using the example
[[% include "_includes/examples-color-key.html" %]]

View File

@ -15,20 +15,20 @@ You can use Python in the Code node. It isn't available in expressions.
=== "JavaScript"
| Method | Description | Available in Code node? |
| ------ | ----------- | :-------------------------: |
| `$("<node-name>").all(branchIndex?, runIndex?)` | Returns all items from a given node. | :white_check_mark: |
| `$("<node-name>").first(branchIndex?, runIndex?)` | The first item output by the given node | :white_check_mark: |
| `$("<node-name>").last(branchIndex?, run Index?)` | The last item output by the given node. | :white_check_mark: |
| `$("<node-name>").all(branchIndex?, runIndex?)` | Returns all items from a given node. If `branchIndex` isn't given it will default to the output that connects `node-name` with the node where you use the expression or code. | :white_check_mark: |
| `$("<node-name>").first(branchIndex?, runIndex?)` | The first item output by the given node. If `branchIndex` isn't given it will default to the output that connects `node-name` with the node where you use the expression or code. | :white_check_mark: |
| `$("<node-name>").last(branchIndex?, runIndex?)` | The last item output by the given node. If `branchIndex` isn't given it will default to the output that connects `node-name` with the node where you use the expression or code. | :white_check_mark: |
| `$("<node-name>").item` | The linked item. This is the item in the specified node used to produce the current item. Refer to [Item linking](/data/data-mapping/data-item-linking/) for more information on item linking. | :x: |
| `$("<node-name>").params` | Object containing the query settings of the given node. This includes data such as the operation it ran, result limits, and so on. | :white_check_mark: |
| `$("<node-name>").context` | Boolean. Only available when working with the Loop Over Items node. Provides information about what's happening in the node. Use this to determine whether the node is still processing items. | :white_check_mark: |
| `$("<node-name>").itemMatching(currentNodeinputIndex)` | Use instead of `$("<node-name>").item` in the Code node if you need to trace back from an input item. | :white_check_mark: |
| `$("<node-name>").itemMatching(currentNodeInputIndex)` | Use instead of `$("<node-name>").item` in the Code node if you need to trace back from an input item. | :white_check_mark: |
=== "Python"
| Method | Description | Available in Code node? |
| ------ | ----------- | :-------------------------: |
| `_("<node-name>").all(branchIndex?, runIndex?)` | Returns all items from a given node. | :white_check_mark: |
| `_("<node-name>").first(branchIndex?, runIndex?)` | The first item output by the given node | :white_check_mark: |
| `_("<node-name>").last(branchIndex?, run Index?)` | The last item output by the given node. | :white_check_mark: |
| `_("<node-name>").all(branchIndex?, runIndex?)` | Returns all items from a given node. If `branchIndex` isn't given it will default to the output that connects`node-name` with the node where you use the expression or code. | :white_check_mark: |
| `_("<node-name>").first(branchIndex?, runIndex?)` | The first item output by the given node. If `branchIndex` isn't given it will default to the output that connects`node-name` with the node where you use the expression or code. | :white_check_mark: |
| `_("<node-name>").last(branchIndex?, runIndex?)` | The last item output by the given node. If `branchIndex` isn't given it will default to the output that connects`node-name` with the node where you use the expression or code. | :white_check_mark: |
| `_("<node-name>").item` | The linked item. This is the item in the specified node used to produce the current item. Refer to [Item linking](/data/data-mapping/data-item-linking/) for more information on item linking. | :x: |
| `_("<node-name>").params` | Object containing the query settings of the given node. This includes data such as the operation it ran, result limits, and so on. | :white_check_mark: |
| `_("<node-name>").context` | Boolean. Only available when working with the Loop Over Items node. Provides information about what's happening in the node. Use this to determine whether the node is still processing items. | :white_check_mark: |
| `_("<node-name>").itemMatching(currentNodeinputIndex)` | Use instead of `_("<node-name>").item` in the Code node if you need to trace back from an input item. Refer to [Retrieve linked items from earlier in the workflow](/code/cookbook/builtin/itemmatching/) for an example. | :white_check_mark: |
| `_("<node-name>").itemMatching(currentNodeInputIndex)` | Use instead of `_("<node-name>").item` in the Code node if you need to trace back from an input item. Refer to [Retrieve linked items from earlier in the workflow](/code/cookbook/builtin/itemmatching/) for an example. | :white_check_mark: |

View File

@ -63,7 +63,7 @@ An n8n node performs its action on each item of incoming data.
## Creating data sets with the Code node
Now that you are familiar with the n8n data structure, you can use it to create your own data sets or simulate node outputs. To do this, use the Code node to write JavaScript code defining your array of objects with the following structure:
Now that you are familiar with the n8n data structure, you can use it to create your own data sets or simulate node outputs. To do this, use the [Code node](/integrations/builtin/core-nodes/n8n-nodes-base.code/){:target="_blank"} to write JavaScript code defining your array of objects with the following structure:
```javascript
return [
@ -102,34 +102,34 @@ In a Code node, create an array of objects named `myContacts` that contains the
??? note "Show me the solution"
In the Code node, in the JavaScript Code field you have to write the following code:
In the **Code node**, in the JavaScript Code field you have to write the following code:
```js
var myContacts = [
{
json: {
name: 'Alice',
email: {
personal: 'alice@home.com',
work: 'alice@wonderland.org'
```javascript
var myContacts = [
{
json: {
name: 'Alice',
email: {
personal: 'alice@home.com',
work: 'alice@wonderland.org'
},
}
},
{
json: {
name: 'Bob',
email: {
personal: 'bob@mail.com',
work: 'contact@thebuilder.com'
},
}
},
{
json: {
name: 'Bob',
email: {
personal: 'bob@mail.com',
work: 'contact@thebuilder.com'
},
}
},
];
}
},
];
return myContacts;
return myContacts;
```
When you execute the Code node, the result should look like this:
When you execute the **Code node**, the result should look like this:
<figure><img src="/_images/courses/level-two/chapter-one/exercise_function.png" alt="" style="width:100%"><figcaption align = "center"><i>Result of Code node</i></figcaption></figure>
@ -137,7 +137,7 @@ In a Code node, create an array of objects named `myContacts` that contains the
## Referencing node data with the Code node
Just like you can use [expressions](/code/expressions/) to reference data from other nodes, you can also use some [methods and variables](/code/builtin/overview/) in the Code node.
Just like you can use [expressions](/code/expressions/) to reference data from other nodes, you can also use some [methods and variables](/code/builtin/overview/) in the **Code node**.
Please make sure you read these pages before continuing to the next exercise.
@ -146,15 +146,15 @@ Please make sure you read these pages before continuing to the next exercise.
Let's build on the previous exercise, in which you used the Code node to create a data set of two contacts with their names and emails. Now, connect a second Code node to the first one. In the new node, write code to create a new column named `workEmail` that references the work email of the first contact.
??? note "Show me the solution"
In the Code node, in the JavaScript Code field you have to write the following code:
In the **Code node**, in the JavaScript Code field you have to write the following code:
```javascript
let items = $input.all();
items[0].json.workEmail = items[0].json.email['work'];
return items;
```
let items = $input.all();
items[0].json.workEmail = items[0].json.email['work'];
return items;
When you execute the Code node, the result should look like this:
When you execute the **Code node**, the result should look like this:
<figure><img src="/_images/courses/level-two/chapter-one/exercise_function_reference.png" alt="" style="width:100%"><figcaption align = "center"><i>Code node reference</i></figcaption></figure>
@ -170,56 +170,61 @@ The two most common operations for data transformation are:
There are several ways to transform data for the purposes mentioned above:
- Using n8n's [data transformation nodes](/data/#data-transformation-nodes). This is the way to modify the structure of incoming data that contain lists (arrays), without needing to use JavaScript code in the Code node. Use [Split Out](/integrations/builtin/core-nodes/n8n-nodes-base.splitout/) to separate a single data item containing a list into multiple items, and [Aggregate](/integrations/builtin/core-nodes/n8n-nodes-base.aggregate/) to take separate items, or portions of them, and group them together into individual items.
- With the Code node, you can write JavaScript functions to modify the data structure of incoming data using the *Run Once for All Items* mode:
To create multiple items from a single item, you can use this JavaScript code:
```js
- Use n8n's [data transformation nodes](/data/#data-transformation-nodes). Use these nodes to modify the structure of incoming data that contain lists (arrays) without needing to use JavaScript code in the **Code node**:
- Use the [**Split Out node**](/integrations/builtin/core-nodes/n8n-nodes-base.splitout/) to separate a single data item containing a list into multiple items.
- Use the [**Aggregate node**](/integrations/builtin/core-nodes/n8n-nodes-base.aggregate/) to take separate items, or portions of them, and group them together into individual items.
- Use the **Code node** to write JavaScript functions to modify the data structure of incoming data using the **Run Once for All Items** mode:
- To create multiple items from a single item, you can use this JavaScript code:
```javascript
return $input.all().map(item => {
return {
json: item
}
});
```
To create a single item from multiple items, you can use this JavaScript code:
```js
return [
{
json: {
data_object: $input.all().map(item => item.json)
}
- To create a single item from multiple items, you can use this JavaScript code:
```javascript
return [
{
json: {
data_object: $input.all().map(item => item.json)
}
}
];
```
These JavaScript examples assume your entire input is what you want to transform. As in the exercise above, you can also execute either operation on a specific field by identifying that in the items list, for example, if our workEmail example had multiple emails in a single field, we could run some code like this:
```javascript
let items = $input.all();
return items[0].json.workEmail.map(item => {
return {
json: item
}
});
```
### Exercise
Use the HTTP Request node to make a GET request to the Quotable API `https://api.quotable.io/quotes`. Transform the data in the `results` field with the Split Out node and also with the Code node.
1. Use the **HTTP Request node** to make a GET request to the Quotable API `https://api.quotable.io/quotes`. (This API requires no authentication).
2. Transform the data in the `results` field with the **Split Out node**.
3. Transform the data in the `results` field with the **Code node**.
??? note "Show me the solution"
To get the quotes from the Quotable API, execute the *HTTP Request node* with the following parameters:
- Authentication: None
- Request Method: GET
- URL: https://api.quotable.io/quotes
To transform the data with the Code node, connect this node to the *HTTP Request node* and write the following code in the JavaScript Code field:
```js
1. To get the quotes from the Quotable API, execute the **HTTP Request node** with the following parameters:
- **Authentication**: None
- **Request Method**: GET
- **URL**: https://api.quotable.io/quotes
2. To transform the data with the **Split Out node**, connect this node to the **HTTP Request node** and set the following parameters:
- **Field To Split Out**: results
- **Include**: No Other Fields
3. To transform the data with the **Code node**, connect this node to the **HTTP Request node** and write the following code in the JavaScript Code field:
```javascript
let items = $input.all();
return items[0].json.results.map(item => {
return {
json: item
}
});
```
To transform the data with the Split Out node, connect this node to the *HTTP Request node* and set the following parameters:
- Operation: Split Out Items
- Field To Split Out: results
- Include: No Other Fields
```

View File

@ -14,60 +14,66 @@ You're most likely familiar with HTML and XML.
/// note | HTML vs. XML
HTML is a markup language used to describe the structure and semantics of a web page. XML looks similar to HTML, but the tag names are different, as they describe the kind of data they hold.
///
If you need to process HTML or XML data in your n8n workflows, use the [HTML node](/integrations/builtin/core-nodes/n8n-nodes-base.html/) or [XML node](/integrations/builtin/core-nodes/n8n-nodes-base.xml/).
If you need to process HTML or XML data in your n8n workflows, use the [**HTML node**](/integrations/builtin/core-nodes/n8n-nodes-base.html/) or the [**XML node**](/integrations/builtin/core-nodes/n8n-nodes-base.xml/).
Use the HTML node to extract HTML content of a webpage, by referencing CSS selectors. This is useful if you want to collect structured information from a website (web-scraping).
Use the **HTML node** to extract HTML content of a webpage by referencing CSS selectors. This is useful if you want to collect structured information from a website (web-scraping).
### Exercise
### HTML Exercise
Let's get the title of the latest n8n blog post. Use the HTTP Request node to make a GET request to the URL `https://blog.n8n.io/`. Then, connect an HTML node and configure it to extract the title of the first post on the page.
Let's get the title of the latest n8n blog post:
1. Use the **HTTP Request node** to make a GET request to the URL `https://blog.n8n.io/` (this endpoint requires no authentication).
2. Connect an **HTML node** and configure it to extract the title of the first blog post on the page.
- Hint: If you're not familiar with CSS selectors or reading HTML, the CSS selector `.item-title a` should help!
??? note "Show me the solution"
Configure the HTTP Request node with the following parameters:
- Authentication: None
- Request Method: GET
- URL: https://blog.n8n.io/
1. Configure the HTTP Request node with the following parameters:
- **Authentication**: None
- **Request Method**: GET
- **URL**: https://blog.n8n.io/
The result should look like this:
<figure><img src="/_images/courses/level-two/chapter-two/exercise_html_httprequestnode.png" alt="" style="width:100%"><figcaption align = "center"><i>Result of HTTP Request node</i></figcaption></figure>
<figure><img src="/_images/courses/level-two/chapter-two/exercise_html_httprequestnode.png" alt="Result of HTTP Request node" style="width:100%"><figcaption align = "center"><i>Result of HTTP Request node</i></figcaption></figure>
Connect an HTML node to the HTTP Request node and configure the former's parameters:
* Operation: Extract HTML Content
* Source Data: JSON
* JSON Property: data
* Extraction Values:
* Key: title
* CSS Selector: .item-title a
* Return Value: HTML
2. Connect an **HTML node** to the **HTTP Request node** and configure the former's parameters:
- **Operation**: Extract HTML Content
- **Source Data**: JSON
- **JSON Property**: data
- **Extraction Values**:
- **Key**: title
- **CSS Selector**: `.item-title a`
- **Return Value**: HTML
You can add more values to extract more data.
The result should look like this:
<figure><img src="/_images/courses/level-two/chapter-two/exercise_html_htmlextractnode.png" alt="" style="width:100%"><figcaption align = "center"><i>Result of HTML Extract node</i></figcaption></figure>
</details>
<figure><img src="/_images/courses/level-two/chapter-two/exercise_html_htmlextractnode.png" alt="Result of HTML Extract node" style="width:100%"><figcaption align = "center"><i>Result of HTML Extract node</i></figcaption></figure>
Use the XML node to convert XML to JSON and JSON to XML. This operation is useful if you work with different web services that use either XML or JSON, and need to get and submit data between them in the two formats.
Use the **XML node** to convert XML to JSON and JSON to XML. This operation is useful if you work with different web services that use either XML or JSON and need to get and submit data between them in the two formats.
### Exercise
### XML Exercise
In a previous exercise, you used an HTTP Request node to make a request to an API. Now, use the XML node to convert the JSON output to XML.
In the [final exercise of Chapter 1](/courses/level-two/chapter-1/#exercise_2), you used an **HTTP Request node** to make a request to the Quotable API. In this exercise, we'll return to that same API but we'll convert the output to XML:
1. Add an **HTTP Request node** that makes the same request to the Quotable API at `https://api.quotable.io/quotes`.
2. Use the XML node to convert the JSON output to XML.
??? note "Show me the solution"
Get data from the Quotable API using the HTTP Request node and connect an XML node to it with the following parameters:
- Mode: **JSON to XML**
- Property name: **data**
1. To get the quotes from the Quotable API, execute the **HTTP Request node** with the following parameters:
- **Authentication**: None
- **Request Method**: GET
- **URL**: https://api.quotable.io/quotes
2. Connect an **XML node** to it with the following parameters:
- **Mode**: JSON to XML
- **Property name**: data
The result should look like this:
<figure><img src="/_images/courses/level-two/chapter-two/exercise_html_xmlnode_table.png" alt="" style="width:100%"><figcaption align = "center"><i>XML node (JSON to XML) Table View</i></figcaption></figure>
<figure><img src="/_images/courses/level-two/chapter-two/exercise_html_xmlnode_table.png" alt="Table view of XML Node (JSON to XML)" style="width:100%"><figcaption align = "center"><i>XML node (JSON to XML) Table View</i></figcaption></figure>
To transform data the other way around, select the mode **XML to JSON**.
@ -82,129 +88,186 @@ Date and time data types include `DATE`, `TIME`, `DATETIME`, `TIMESTAMP`, and `Y
- `TIMESTAMP`: 1616108400 (Unix timestamp), 1616108400000 (Unix ms timestamp)
- `YEAR`: 2022, 22
<!-- vale on -->
If you need to convert date and time data to different formats, and calculate dates, use the [Date & Time node](/integrations/builtin/core-nodes/n8n-nodes-base.datetime/).
There are a few ways you can work with dates and times:
You can also schedule workflows to run at a specific time, interval, or duration, using the [Schedule Trigger](/integrations/builtin/core-nodes/n8n-nodes-base.scheduletrigger/) node.
- Use the [**Date & Time node**](/integrations/builtin/core-nodes/n8n-nodes-base.datetime/) to convert date and time data to different formats and calculate dates.
- Use [**Schedule Trigger node**](/integrations/builtin/core-nodes/n8n-nodes-base.scheduletrigger/) to schedule workflows to run at a specific time, interval, or duration.
Sometimes, you might need to pause the workflow execution. This might be necessary if you know that a service doesn't process the data instantly or it's slow to return all the results. In these cases, you don't want n8n to pass incomplete data to the next node.
If you run into situations like this, use the [**Wait node**](/integrations/builtin/core-nodes/n8n-nodes-base.wait/) after the node that you want to delay. The **Wait node** pauses the workflow execution and will resume execution:
- At a specific time.
- After a specified time interval.
- On a webhook call.
In some cases, you might need to pause the workflow execution. This might be necessary, for example, if you know that a service doesn't process the data instantly or it's generally slower, so you don't want the incomplete data to be passed to the next node. In this case, you can use the [Wait node](/integrations/builtin/core-nodes/n8n-nodes-base.wait/) after the node that you want to delay. The Wait node pauses the workflow execution and resumes it at a specific time, after a time interval, or on a webhook call.
### Exercise
### Date Exercise
Build a workflow that adds five days to an input date from the Customer Datastore node that you used before. Then, if the calculated date occurred after 1959, the workflow waits 1 minute before [setting](/integrations/builtin/core-nodes/n8n-nodes-base.set/) the calculated date as a value. The workflow should be triggered every 30 minutes.
To begin:
<!-- To do: need to figure out what the actual desired output is here since Date & Time options have changed and I'm unclear what the Set node should be doing-->
1. Add the **Customer Datastore (n8n training) node** with the **Get All People** action selected. Return All.
2. Add the **Date & Time node** to Round Up the created Date from the datastore to End of Month. Output this to field new-date. Include all input fields.
3. Add the **If node** to check if that new rounded date is after `1960-01-01 00:00:00`.
4. Add the **Wait node** to the True output of that node and set it to wait for one minute.
5. Add the **Edit Fields (Set) node** to set a new field called outputValue to a String containing new-date. Include all input fields.
6. Add the **Schedule Trigger node** at the beginning of the workflow to trigger it every 30 minutes. (You can keep the [Manual Trigger node](/integrations/builtin/core-nodes/n8n-nodes-base.manualworkflowtrigger/) for testing!)
??? note "Show me the solution"
You can build this workflow using the data from the *Customer Datastore node*, the three nodes for managing date and time, an *IF node* for conditional routing, and a *Set node* for setting the new calculated date. You can add a [Manual Trigger node](/integrations/builtin/core-nodes/n8n-nodes-base.manualworkflowtrigger/) too for easy testing during development. The workflow looks like this:
1. Add the **Customer Datastore (n8n training) node** with the **Get All People** action selected.
- Select the option to **Return All**.
2. Add a **Date & Time node** connected to the Customer Datastore node. Select the option to **Round a Date**.
- Add the `created` date as the **Date** to round.
- Select `Round Up` as the **Mode** and `End of Month` as the **To**.
- Set the **Output Field Name** as `new-date`.
- In **Options**, select **Add Option** and use the control to **Include Input Fields**
3. Add an **If node** connected to the **Date & Time node**.
- Add the new-date field as the first part of the condition.
- Set the comparison to **Date &Time > is after**
- Add `1960-01-01 00:00:00` as the second part of the expression. (This should produce 3 items in the True Branch and 2 items in the False Branch)
4. Add a **Wait node** to the True output of the **If node**.
- Set **Resume** to `After Time interval`.
- Set **Wait Amount** to `1.00`.
- Set **Wait Unit** to `Minutes`.
5. Add an **Edit Fields (Set) node** to the **Wait node**.
- Use either JSON or Manual Mapping **Mode**.
- Set a new field called `outputValue` to be the value of the new-date field.
- Select the option to **Include Other Input Fields** and include **All** fields.
6. Add a **Schedule Trigger node** at the beginning of the workflow.
- Set the **Trigger Interval** to use `Minutes`.
- Set the **Minutes Between Triggers** to 30.
- To test your schedule, be sure to activate the workflow.
- Be sure to connect this node to the **Customer Datastore (n8n training) node** you began with!
The workflow should look like this:
<figure><img src="/_images/courses/level-two/chapter-two/exercise_datetime.png" alt="" style="width:100%"><figcaption align = "center"><i>Workflow for transforming dates</i></figcaption></figure>
<figure><img src="/_images/courses/level-two/chapter-two/exercise_datetime.png" alt="Workflow for transforming dates" style="width:100%"><figcaption align = "center"><i>Workflow for transforming dates</i></figcaption></figure>
To check the configuration of each node, you can copy the JSON code of this workflow and paste it in your Editor UI.
To check the configuration of each node, you can copy the JSON code of this workflow and either paste it into the Editor UI or save it as a file and import from file into a new workflow. See [Export and import workflows](/workflows/export-import/) for more information.
```json
{
"meta": {
"templateCredsSetupCompleted": true,
"instanceId": "cb484ba7b742928a2048bf8829668bed5b5ad9787579adea888f05980292a4a7"
},
"name": "Course 2, Ch 2, Date exercise",
"nodes": [
{
"parameters": {},
"id": "c2c4509b-c4d4-4e95-bd7d-039734954b68",
"id": "6bf64d5c-4b00-43cf-8439-3cbf5e5f203b",
"name": "When clicking \"Test workflow\"",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
260,
2080
620,
280
]
},
{
"parameters": {
"action": "calculate",
"value": "={{$json[\"created\"]}}",
"duration": 5,
"dataPropertyName": "new-date",
"options": {}
},
"name": "Date & Time",
"type": "n8n-nodes-base.dateTime",
"typeVersion": 1,
"position": [
660,
2160
],
"id": "61b56e39-021f-4ad0-b72c-697978c4f384"
},
{
"parameters": {
"unit": "minutes"
},
"name": "Wait",
"type": "n8n-nodes-base.wait",
"typeVersion": 1,
"position": [
1040,
2160
],
"webhookId": "d17effb8-ad90-4a74-bb88-daa3d3d18583",
"id": "842b788f-c236-4c67-bad0-155de7ef1be4"
},
{
"parameters": {
"conditions": {
"dateTime": [
{
"value1": "={{$json[\"new-date\"]}}",
"value2": "1960-01-01T00:00:00"
}
]
}
},
"name": "IF",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
840,
2160
],
"id": "ce788b41-ba4c-41cd-85da-6bf23baa76aa"
},
{
"parameters": {
"values": {
"string": [
{
"name": "outputValue",
"value": "={{ $('IF').item.json['new-date'] }}"
}
]
},
"options": {}
},
"name": "Set",
"type": "n8n-nodes-base.set",
"typeVersion": 1,
"position": [
1220,
2160
],
"id": "df3e455c-5c5e-42af-ad5c-a9bb6869a921"
},
{
"parameters": {
"operation": "getAllPeople",
"returnAll": true
},
"name": "Customer Datastore",
"id": "a08a8157-99ee-4d50-8fe4-b6d7e16e858e",
"name": "Customer Datastore (n8n training)",
"type": "n8n-nodes-base.n8nTrainingCustomerDatastore",
"typeVersion": 1,
"position": [
480,
2160
840,
360
]
},
{
"parameters": {
"operation": "roundDate",
"date": "={{ $json.created }}",
"mode": "roundUp",
"outputFieldName": "new-date",
"options": {
"includeInputFields": true
}
},
"id": "f66a4356-2584-44b6-a4e9-1e3b5de53e71",
"name": "Date & Time",
"type": "n8n-nodes-base.dateTime",
"typeVersion": 2,
"position": [
1080,
360
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "7c82823a-e603-4166-8866-493f643ba354",
"leftValue": "={{ $json['new-date'] }}",
"rightValue": "1960-01-01T00:00:00",
"operator": {
"type": "dateTime",
"operation": "after"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "cea39877-6183-4ea0-9400-e80523636912",
"name": "If",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
1280,
360
]
},
{
"parameters": {
"amount": 1,
"unit": "minutes"
},
"id": "5aa860b7-c73c-4df0-ad63-215850166f13",
"name": "Wait",
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
1480,
260
],
"id": "1f3573f7-1586-4e9a-9cbf-9eb7c7475b27"
"webhookId": "be78732e-787d-463e-9210-2c7e8239761e"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "e058832a-2461-4c6d-b584-043ecc036427",
"name": "outputValue",
"value": "={{ $json['new-date'] }}",
"type": "string"
}
]
},
"includeOtherFields": true,
"options": {}
},
"id": "be034e9e-3cf1-4264-9d15-b6760ce28f91",
"name": "Edit Fields",
"type": "n8n-nodes-base.set",
"typeVersion": 3.3,
"position": [
1700,
260
]
},
{
"parameters": {
@ -217,62 +280,30 @@ Build a workflow that adds five days to an input date from the Customer Datastor
]
}
},
"id": "c3ce4d5e-524b-4806-9c25-43892113b5eb",
"id": "6e8e4308-d0e0-4d0d-bc29-5131b57cf061",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [
260,
2260
620,
480
]
}
],
"pinData": {},
"connections": {
"When clicking \"Test workflow\"": {
"main": [
[
{
"node": "Customer Datastore",
"node": "Customer Datastore (n8n training)",
"type": "main",
"index": 0
}
]
]
},
"Date & Time": {
"main": [
[
{
"node": "IF",
"type": "main",
"index": 0
}
]
]
},
"Wait": {
"main": [
[
{
"node": "Set",
"type": "main",
"index": 0
}
]
]
},
"IF": {
"main": [
[
{
"node": "Wait",
"type": "main",
"index": 0
}
]
]
},
"Customer Datastore": {
"Customer Datastore (n8n training)": {
"main": [
[
{
@ -283,26 +314,58 @@ Build a workflow that adds five days to an input date from the Customer Datastor
]
]
},
"Date & Time": {
"main": [
[
{
"node": "If",
"type": "main",
"index": 0
}
]
]
},
"If": {
"main": [
[
{
"node": "Wait",
"type": "main",
"index": 0
}
]
]
},
"Wait": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Customer Datastore",
"node": "Customer Datastore (n8n training)",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {}
}
}
```
## Binary data
Up to now, you have mainly worked with text data. But what if you want to process data that's not text? For example, images or PDF files. This is binary data, as it's represented in the binary numeral system. In this form, binary data doesn't offer you useful information, so it needs to be converted into a readable form.
Up to now, you have mainly worked with text data. But what if you want to process data that's not text, like images or PDF files? These types of files are represented in the binary numeral system, so they're considered binary data. In this form, binary data doesn't offer you useful information, so you'll need to convert it into a readable form.
In n8n, you can process binary data with the following nodes:
@ -315,7 +378,7 @@ In n8n, you can process binary data with the following nodes:
Reading and writing files to disk isn't available on n8n Cloud. You'll read and write to the machine where you installed n8n. If you run n8n in Docker, your command runs in the n8n container and not the Docker host. The Read/Write Files From Disk node looks for files relative to the n8n install path. n8n recommends using absolute file paths to prevent any errors.
///
To read or write a binary file, you need to write the path (location) of the file in the node's `File(s) Selector` parameter (for the Read operation), or in the node's `File Path and Name` parameter (for the Write operation).
To read or write a binary file, you need to write the path (location) of the file in the node's `File(s) Selector` parameter (for the Read operation) or in the node's `File Path and Name` parameter (for the Write operation).
/// warning | Naming the right path
The file path looks slightly different depending on how you are running n8n:
@ -326,21 +389,24 @@ The file path looks slightly different depending on how you are running n8n:
### Exercise
### Binary Exercise 1
Make an HTTP request to get this PDF file: `https://media.kaspersky.com/pdf/Kaspersky_Lab_Whitepaper_Anti_blocker.pdf.` Then, use the Extract From File node to convert the file from binary to JSON.
For our first binary exercise, let's convert a PDF file to JSON:
1. Make an HTTP request to get this PDF file: `https://media.kaspersky.com/pdf/Kaspersky_Lab_Whitepaper_Anti_blocker.pdf.`
2. Use the **Extract From File node** to convert the file from binary to JSON.
??? note "Show me the solution"
In the HTTP Request node, you should see the PDF file, like this:
In the **HTTP Request node**, you should see the PDF file, like this:
<figure><img src="/_images/courses/level-two/chapter-two/exercise_binarydata_httprequest_file.png" alt="" style="width:100%"><figcaption align = "center"><i>HTTP Request node to get PDF</i></figcaption></figure>
<figure><img src="/_images/courses/level-two/chapter-two/exercise_binarydata_httprequest_file.png" alt="HTTP Request node to get PDF" style="width:100%"><figcaption align = "center"><i>HTTP Request node to get PDF</i></figcaption></figure>
When you convert the PDF from binary to JSON Extract From File node, the result should look like this:
When you convert the PDF from binary to JSON using the **Extract From File node**, the result should look like this:
<figure><img src="/_images/courses/level-two/chapter-two/exercise_binarydata_movedata_btoj.png" alt="" style="width:100%"><figcaption align = "center"><i>Extract From File node</i></figcaption></figure>
<figure><img src="/_images/courses/level-two/chapter-two/exercise_binarydata_movedata_btoj.png" alt="Extract From File node" style="width:100%"><figcaption align = "center"><i>Extract From File node</i></figcaption></figure>
To check the configuration of the nodes, you can copy-paste the JSON code of the workflow:
To check the configuration of the nodes, you can copy the JSON workflow code below and paste it into your Editor UI:
```json
{
@ -416,17 +482,22 @@ Make an HTTP request to get this PDF file: `https://media.kaspersky.com/pdf/Kasp
### Exercise
### Binary Exercise 2
Make an HTTP request to the Poetry DB API `https://poetrydb.org/random/1` and convert the returned data from JSON to binary using the Convert to File node. Then, write the new binary file data to the machine where n8n is running. Finally, to check that it worked out, read the generated binary file from the machine referencing it with an expression in the node.
For our second binary exercise, let's convert some JSON data to binary:
1. Make an HTTP request to the Poetry DB API `https://poetrydb.org/random/1`.
2. Convert the returned data from JSON to binary using the **Convert to File node**.
3. Write the new binary file data to the machine where n8n is running using the **Read/Write Files From Disk node**.
4. To check that it worked out, use the **Read/Write Files From Disk node** to read the generated binary file.
??? note "Show me the solution"
The workflow for this exercise looks like this:
<figure><img src="/_images/courses/level-two/chapter-two/exercise_binarydata.png" alt="" style="width:100%"><figcaption align = "center"><i>Workflow for moving JSON to binary data</i></figcaption></figure>
<figure><img src="/_images/courses/level-two/chapter-two/exercise_binarydata.png" alt="Workflow for moving JSON to binary data" style="width:100%"><figcaption align = "center"><i>Workflow for moving JSON to binary data</i></figcaption></figure>
To check the configuration of the nodes, you can copy-paste the JSON code of the workflow:
To check the configuration of the nodes, you can copy the JSON workflow code below and paste it into your Editor UI:
```json
{

View File

@ -14,7 +14,7 @@ In some cases, you might need to merge (combine) and process data from different
Merging data can involve:
- Creating one data set from multiple sources.
- Synchronizing data between multiple systems. For example, removing duplicate data, or updating data in one system when it changes in another.
- Synchronizing data between multiple systems. This could include removing duplicate data or updating data in one system when it changes in another.
/// note | One-way vs. two-way sync
In a one-way sync, data is synchronized in one direction. One system serves as the single source of truth. When information changes in that main system, it automatically changes in the secondary system; but if information changes in the secondary system, the changes aren't reflected in the main system.
@ -25,44 +25,49 @@ In a two-way sync, data is synchronized in both directions (between both systems
///
In n8n, you can merge data from two different nodes using the [Merge node](/integrations/builtin/core-nodes/n8n-nodes-base.merge/){:target="_blank" .external}, which provides several merging modes:
In n8n, you can merge data from two different nodes using the [Merge node](/integrations/builtin/core-nodes/n8n-nodes-base.merge/){:target="_blank"}, which provides several merging options:
- Combine (Merge by Fields, Merge by Position and Multiplex)
- Append
- Choose Branch
- [Append](/integrations/builtin/core-nodes/n8n-nodes-base.merge/#append){:target="_blank"}
- [Combine](/integrations/builtin/core-nodes/n8n-nodes-base.merge/#combine){:target="_blank"}
- [Merge by Fields](/integrations/builtin/core-nodes/n8n-nodes-base.merge/#merge-by-fields){:target="_blank"}: requires input fields to match on
- [Merge by Position](/integrations/builtin/core-nodes/n8n-nodes-base.merge/#merge-by-position){:target="_blank"}
- [Multiplex](/integrations/builtin/core-nodes/n8n-nodes-base.merge/#multiplex){:target="_blank"}
- [Choose Branch](/integrations/builtin/core-nodes/n8n-nodes-base.merge/#choose-branch){:target="_blank"}
Notice that Combine/Merge by Fields mode requires a key. This key represents a common property between the two data sources, based on which the data can be merged. In the Merge node, they're called `Input 1 Field` and `Input 2 Field`.
Notice that Combine > Merge by Fields requires you enter input fields to match on. These fields should contain identical values between the data sources so n8n can properly match data together. In the **Merge node**, they're called `Input 1 Field` and `Input 2 Field`.
<figure><img src="/_images/courses/level-two/chapter-three/explanation_mergepropertyinput.png" alt="" style="width:100%"><figcaption align = "center"><i>Property Input fields in the Merge node</i></figcaption></figure>
<figure><img src="/_images/courses/level-two/chapter-three/explanation_mergepropertyinput.png" alt="Property Input fields in the Merge node" style="width:100%"><figcaption align = "center"><i>Property Input fields in the Merge node</i></figcaption></figure>
/// warning | Property Input in dot notation
If you want to reference nested values in the *Merge node* parameters `Input 1 Field` and `Input 2 Field`, you need to enter the property key in dot-notation format (as text, not as an expression).
If you want to reference nested values in the **Merge node** parameters `Input 1 Field` and `Input 2 Field`, you need to enter the property key in dot-notation format (as text, not as an expression).
///
/// note
You can also find the Merge node under the alias Join. This might be more intuitive if you're familiar with SQL joins.
You can also find the **Merge node** under the alias Join. This might be more intuitive if you're familiar with SQL joins.
///
### Exercise
### Merge Exercise
Build a workflow that merges data from the Customer Datastore node and Code node.
* Add a Merge node that takes Input 1 from a Customer Datastore node and Input 2 from a Code node.
* In the Customer Datastore node, run the operation Get All People.
* In the Code node, create an array of two objects with three properties: `name`, `language`, and `country`, where the property `country` has two sub-properties `code` and `name`. Fill out the values of these properties with the information of two characters from the Customer Database. For example, Jay Gatsby's language would be English and country name would be United States.
* In the Merge node, try out different merge modes.
1. Add a **Merge node** that takes `Input 1` from a **Customer Datastore node** and `Input 2` from a **Code node**.
2. In the **Customer Datastore node**, run the operation **Get All People**.
3. In the **Code node**, create an array of two objects with three properties: `name`, `language`, and `country`, where the property `country` has two sub-properties `code` and `name`.
- Fill out the values of these properties with the information of two characters from the Customer Database.
- For example, Jay Gatsby's language is English and country name is United States.
4. In the **Merge node**, try out different merge options.
??? note "Show me the solution"
The workflow for this exercise looks like this:
<figure><img src="/_images/courses/level-two/chapter-three/exercise_merge.png" alt="" style="width:100%"><figcaption align = "center"><i>Workflow exercise for merging data</i></figcaption></figure>
<figure><img src="/_images/courses/level-two/chapter-three/exercise_merge.png" alt="Workflow exercise for merging data" style="width:100%"><figcaption align = "center"><i>Workflow exercise for merging data</i></figcaption></figure>
If you merge data with the option *Keep Key Matches* using the country code as the common key, the result should look like this:
If you merge data with the option **Keep Matches** using the name as the input fields to match, the result should look like this (note this example only contains Jay Gatsby; yours might look different depending on which characters you selected):
<figure><img src="/_images/courses/level-two/chapter-three/exercise_merge_kkm.png" alt="" style="width:100%"><figcaption align = "center"><i>Output of Merge node with option to keep key matches</i></figcaption></figure>
<figure><img src="/_images/courses/level-two/chapter-three/exercise_merge_kkm.png" alt="Output of Merge node with option to keep matches" style="width:100%"><figcaption align = "center"><i>Output of Merge node with option to keep matches</i></figcaption></figure>
To check the configuration of the nodes, you can copy-paste the JSON code of the workflow:
To check the configuration of the nodes, you can copy the JSON workflow code below and paste it into your Editor UI:
```json
{
@ -178,36 +183,64 @@ Build a workflow that merges data from the Customer Datastore node and Code node
## Looping
In some cases, you might need to perform the same operation on each element of an array / each data item (for example sending a message to every contact in your address book). In technical terms, you need to iterate through the data (with loops).
In some cases, you might need to perform the same operation on each element of an array or each data item (for example sending a message to every contact in your address book). In technical terms, you need to iterate through the data (with loops).
n8n generally handles this repetitive processing automatically, as the nodes run once for each item, so you don't need to build loops into your workflows.
n8n handles this repetitive processing automatically, as the nodes run once for each item, so you don't need to build loops into your workflows. However, there are some [exceptions of nodes and operations](/flow-logic/looping/#node-exceptions){:target="_blank" .external} for which you need to build a loop into your workflow.
However, there are some [exceptions of nodes and operations](/flow-logic/looping/#node-exceptions){:target="_blank"} that will require you to build a loop into your workflow.
To [create a loop in an n8n workflow](/flow-logic/looping/#using-loops-in-n8n){:target="_blank" .external}, you need to connect the output of one node to the input of a previous node, and add an IF node to check when to stop the loop.
To [create a loop in an n8n workflow](/flow-logic/looping/#using-loops-in-n8n){:target="_blank"}, you need to connect the output of one node to the input of a previous node, and add an **If node** to check when to stop the loop.
## Splitting data in batches
If you need to process large incoming data, execute the Code node multiple times, or avoid API rate limits, it's best to split the data into batches (groups) and process these batches. You can do this with the [Loop Over Items node](/integrations/builtin/core-nodes/n8n-nodes-base.splitinbatches/){:target="_blank" .external}. This node splits input data into a specified batch size and, with each iteration, returns a predefined amount of data.
If you need to process large volumes of incoming data, execute the **Code node** multiple times, or avoid API rate limits, it's best to split the data into batches (groups) and process these batches.
For these processes, use the [**Loop Over Items node**](/integrations/builtin/core-nodes/n8n-nodes-base.splitinbatches/){:target="_blank"}. This node splits input data into a specified batch size and, with each iteration, returns a predefined amount of data.
/// warning | Execution of Loop Over Items node
The Loop Over Items node stops executing after all the incoming items get divided into batches and passed on to the next node in the workflow, so it's not necessary to add an IF node to stop the loop.
The **Loop Over Items node** stops executing after all the incoming items get divided into batches and passed on to the next node in the workflow, so it's not necessary to add an **If node** to stop the loop.
///
### Exercise
### Loop/Batch Exercise
Build a workflow that reads the RSS feed from Medium and dev.to. The workflow should consist of three nodes:
- A Code node that returns the URLs of the RSS feeds of Medium (`https://medium.com/feed/n8n-io`) and dev.to (`https://dev.to/feed/n8n`)
- A Loop Over Items node with `Batch Size: 1`, that takes in the inputs from the Code node and RSS node and iterates over the items.
- An RSS Read node that gets the URL of the Medium RSS feed, passed as an expression: `{{$node["SplitInBatches"].json["url"]}}`. The RSS Read node is one of the exception nodes which processes only the first item it receives, so the Loop Over Items node is necessary for iterating over multiple items.
1. A **Code node** that returns the URLs of the RSS feeds of Medium (`https://medium.com/feed/n8n-io`) and dev.to (`https://dev.to/feed/n8n`).
2. A **Loop Over Items node** with `Batch Size: 1`, that takes in the inputs from the **Code node** and **RSS Read node** and iterates over the items.
3. An **RSS Read node** that gets the URL of the Medium RSS feed, passed as an expression: `{{ $json.url }}`.
- The **RSS Read node** is one of the [exception nodes](/flow-logic/looping/#node-exceptions){:target="_blank"} which processes only the first item it receives, so the **Loop Over Items node** is necessary for iterating over multiple items.
??? note "Show me the solution"
1. Add a **Code Node**. You can format the code in several ways, one way is:
- Set **Mode** to `Run Once for All Items`.
- Set **Language** to `JavaScript`.
- Copy the code below and paste it into the JavaScript Code editor:
```javascript
let urls = [
{
json: {
url: 'https://medium.com/feed/n8n-io'
}
},
{
json: {
url: 'https://dev.to/feed/n8n'
}
}
]
return urls;
```
2. Add a **Loop Over Items node** connected to the **Code node**.
- Set **Batch Size** to `1`.
3. The **Loop Over Items node** automatically adds a node called "Replace Me". Replace that node with an **RSS Read node**.
- Set the **URL** to use the url from the Code Node: `{{ $json.url }}`.
The workflow for this exercise looks like this:
<figure><img src="/_images/courses/level-two/chapter-three/exercise_splitinbatches.png" alt="" style="width:100%"><figcaption align = "center"><i>Workflow for getting RSS feeds from two blogs</i></figcaption></figure>
<figure><img src="/_images/courses/level-two/chapter-three/exercise_splitinbatches.png" alt="Workflow for getting RSS feeds from two blogs" style="width:100%"><figcaption align = "center"><i>Workflow for getting RSS feeds from two blogs</i></figcaption></figure>
To check the configuration of the nodes, you can copy-paste the JSON code of the workflow:
To check the configuration of the nodes, you can copy the JSON workflow code below and paste it into your Editor UI:
```json
{

View File

@ -4,44 +4,55 @@ contentType: tutorial
# Dealing with errors in workflows
Sometimes it can happen that you're building a nice workflow, but when you try to execute it, it fails. There are many reasons why workflows executions may fail (some more or less mysterious), for example when a node isn't configured correctly or a third-party service that you're trying to connect to isn't working properly.
Sometimes you build a nice workflow, but it fails when you try to execute it. Workflow executions may fail for a variety of reasons, ranging from straightforward problems with incorrectly configuring a node or a failure in a third-party service to more mysterious errors.
But don't panic. We will show you some ways in which you can troubleshoot the issue, so you can get your workflow up and running as soon as possible.
But don't panic. In this lesson, you'll learn how you can troubleshoot errors so you can get your workflow up and running as soon as possible.
## Checking failed workflows
When one of your workflows fails, it's helpful to check the execution log by clicking on [**Executions**](/editor-ui/#executions){:target="_blank" .external} in the left-side panel. The executions log shows you a list of the latest execution time, status, mode, and running time of your saved workflows.
n8n tracks executions of your workflows.
To investigate a specific failed execution from the list, click on the name or 'view' button on the row of the respective execution.
When one of your workflows fails, you can check the Executions log to see what went wrong. The Executions log shows you a list of the latest execution time, status, mode, and running time of your saved workflows.
<figure><img src="/_images/courses/level-two/chapter-four/explanation_workflowexecutions.png" alt="" style="width:100%"><figcaption align = "center"><i>Workflow Executions window</i></figcaption></figure>
Open the Executions log by selecting [**Executions**](/editor-ui/#executions) in the left-side panel.
To investigate a specific failed execution from the list, select the name or the **View** button that appears when you hover over the row of the respective execution.
<figure><img src="/_images/courses/level-two/chapter-four/explanation_workflowexecutions.png" alt="Executions log" style="width:100%"><figcaption align = "center"><i>Executions log</i></figcaption></figure>
This will open the workflow in read-only mode, where you can see the execution of each node. This representation can help you identify at what point the workflow ran into issues.
To toggle between viewing the execution and the editor, click the **Editor | Executions** button at the top of the page.
To toggle between viewing the execution and the editor, select the **Editor | Executions** button at the top of the page.
<figure><img src="/_images/courses/level-two/chapter-four/explanation_workflowexecutions_readonly.png" alt="" style="width:100%"><figcaption align = "center"><i>Workflow execution view</i></figcaption></figure>
<figure><img src="/_images/courses/level-two/chapter-four/explanation_workflowexecutions_readonly.png" alt="Workflow execution view" style="width:100%"><figcaption align = "center"><i>Workflow execution view</i></figcaption></figure>
## Catching erroring workflows
To catch failed workflows, create a separate [Error Workflow](/flow-logic/error-handling/error-workflows/) with the [Error Trigger node](/integrations/builtin/core-nodes/n8n-nodes-base.errortrigger/), which gets executed if the main execution fails.
To catch failed workflows, create a separate [**Error Workflow**](/flow-logic/error-handling/error-workflows/) with the [**Error Trigger node**](/integrations/builtin/core-nodes/n8n-nodes-base.errortrigger/). This workflow will only execute if the main workflow execution fails.
Then, you can take further actions by connecting other nodes, for example sending notifications using email or Slack about the failed workflow and its errors. To receive error messages for a failed workflow, you need to select the option `Error Workflow` in the [Workflow Settings](/courses/level-one/chapter-5/chapter-5.8/) of the respective workflow.
Use additional nodes in your **Error Workflow** that make sense, like sending notifications about the failed workflow and its errors using email or Slack.
The only difference between a regular workflow and an Error Workflow is that the latter contains an Error Trigger node. Make sure to create this node before you set a workflow as Error Workflow.
To receive error messages for a failed workflow, set the **Error Workflow** in the [Workflow Settings](/workflows/settings/) to an Error Workflow that uses an **Error Trigger node**.
The only difference between a regular workflow and an Error Workflow is that the latter contains an **Error Trigger node**. Make sure to create this node before you set this as another workflow's designated Error Workflow.
/// note | Error workflows
- You don't need to activate workflows that use the Error Workflow node.
- A workflow that uses the *Error Trigger node* uses itself as the error workflow.
- The Error Trigger node is designed to get triggered only when the monitored workflow gets executed automatically. This means you can't test this (to see the result of) an error workflow while executing the monitored workflow manually.
- If a workflow uses the Error trigger node, you don't have to activate the workflow.
- If a workflow contains the Error trigger node, by default, the workflow uses itself as the error workflow.
- You can't test error workflows when running workflows manually. The Error trigger only runs when an automatic workflow errors.
- You can set the same Error Workflow for multiple workflows.
///
### Exercise
In the previous chapters, you've built several small workflows. Now, pick one of them that you want to monitor. Create an Error Workflow that sends a message to a communication platform (for example, Slack, Discord, Telegram, or even email) if that workflow fails. Don't forget to set this Error Workflow in the settings of the monitored workflow.
In the previous chapters, you've built several small workflows. Now, pick one of them that you want to monitor and create an Error Workflow for it:
1. Create a new Error Workflow.
2. Add the **Error trigger node**.
3. Connect a node for the communication platform of your choice to the Error trigger node, like [Slack](/integrations/builtin/app-nodes/n8n-nodes-base.slack/), [Discord](/integrations/builtin/app-nodes/n8n-nodes-base.discord/), [Telegram](/integrations/builtin/app-nodes/n8n-nodes-base.telegram/), or even [Gmail](/integrations/builtin/app-nodes/n8n-nodes-base.gmail/) or a more generic [Send Email](/integrations/builtin/core-nodes/n8n-nodes-base.sendemail/).
4. In the workflow you want to monitor, open the [Workflow Settings](/workflows/settings/) and select the new Error Workflow you just created. Note that this workflow needs to run automatically to trigger the error workflow.
??? note "Show me the solution"
@ -49,7 +60,7 @@ In the previous chapters, you've built several small workflows. Now, pick one of
<figure><img src="/_images/courses/level-two/chapter-four/exercise_errors_errortriggernode_workflow.png" alt="" style="width:100%"><figcaption align = "center"><i>Error workflow</i></figcaption></figure>
To check the configuration of the nodes, you can copy-paste the JSON code of the workflow:
To check the configuration of the nodes, you can copy the JSON workflow code below and paste it into your Editor UI:
```json
{
@ -106,17 +117,25 @@ In the previous chapters, you've built several small workflows. Now, pick one of
## Throwing exceptions in workflows
Another way of troubleshooting workflows is to include a [Stop and Error node](/integrations/builtin/core-nodes/n8n-nodes-base.stopanderror/){:target="_blank" .external} in your workflow. This node throws an error, which can be set to one of two error types: an error message or an error object. The error message returns a custom message about the error, while the error object returns the type of error.
Another way of troubleshooting workflows is to include a [**Stop and Error node**](/integrations/builtin/core-nodes/n8n-nodes-base.stopanderror/) in your workflow. This node throws an error. You can specify the error type:
The Stop and Error node can only be added as the last node in a workflow.
- **Error Message**: returns a custom message about the error
- **Error Object**: returns the type of error
You can only use the **Stop and Error node** as the last node in a workflow.
/// note | When to throw errors
Throwing exceptions with the Stop and Error node is useful for verifying the data (or assumptions about the data) from a node and returning custom error messages.
Throwing exceptions with the **Stop and Error node** is useful for verifying the data (or assumptions about the data) from a node and returning custom error messages.
If you are working with data from a third-party service, you may come across problems such as: wrongly formatted JSON output, data with the wrong type (for example, numeric data that has a non-numeric value), missing values, or errors from remote servers.
If you are working with data from a third-party service, you may come across problems such as:
- Wrongly formatted JSON output
- Data with the wrong type (for example, numeric data that has a non-numeric value)
- Missing values
- Errors from remote servers
Though this kind of invalid data might not cause the workflow to fail right away, it could cause problems later on, and then it can become difficult to track the source error. This is why it's better to throw an error at the time you know there might be a problem.
<figure><img src="/_images/courses/level-two/chapter-four/exercise_errors_stopanderror.png" alt="" style="width:100%"><figcaption align = "center"><i>Stop and Error node with error message</i></figcaption></figure>
<figure><img src="/_images/courses/level-two/chapter-four/exercise_errors_stopanderror.png" alt="Stop and Error node with error message" style="width:100%"><figcaption align = "center"><i>Stop and Error node with error message</i></figcaption></figure>
///

View File

@ -4,12 +4,12 @@ contentType: tutorial
# Automating a business workflow
Remember [our friend Nathan](/courses/level-one/chapter-3){:target="_blank" .external}?
Remember [our friend Nathan](/courses/level-one/chapter-3)?
**Nathan 🙋:** Hello, it's me again. My manager was so impressed with my first workflow automation solution, that she entrusted me with more responsibility.<br/>
**Nathan 🙋:** Hello, it's me again. My manager was so impressed with my first workflow automation solution that she entrusted me with more responsibility.<br/>
**You 👩‍🔧:** More work and responsibility. Congratulations, I guess. What do you need to do now?<br/>
**Nathan 🙋:** I got access to all sales data and am responsible for creating two reports: one for regional sales and one for orders prices. They're based on data from different sources and come in different formats.<br/>
**You 👩‍🔧:** Sounds like a lot of manual workbut the kind that can be automated. Let's do it!
**Nathan 🙋:** I got access to all our sales data and I'm now responsible for creating two reports: one for regional sales and one for orders prices. They're based on data from different sources and come in different formats.<br/>
**You 👩‍🔧:** Sounds like a lot of manual work, but the kind that can be automated. Let's do it!
## Workflow design
@ -21,7 +21,7 @@ Now that we know what Nathan wants to automate, let's list the steps he needs to
3. Write binary files.
4. Send notifications using email and Discord.
n8n provides core nodes for all these steps. This use case is somewhat complex and it will be made up of three separate workflows:
n8n provides [core nodes](/integrations/builtin/node-types/#core-nodes) for all these steps. This use case is somewhat complex. We should build it from three separate workflows:
1. A workflow that merges the company data with external information.
2. A workflow that generates the reports.
@ -31,8 +31,8 @@ n8n provides core nodes for all these steps. This use case is somewhat complex a
To build the workflows, you will need the following:
* An [Airtable](https://airtable.com/){:target="_blank" .external} account and [credentials](/integrations/builtin/credentials/airtable/){:target="_blank" .external}.
* A [Google](https://www.google.com/account/about/){:target="_blank" .external} account and [credentials](/integrations/builtin/credentials/google/){:target="_blank" .external} to access Gmail.
* An [Airtable](https://airtable.com/){:target="_blank" .external-link} account and [credentials](/integrations/builtin/credentials/airtable/).
* A [Google](https://www.google.com/account/about/){:target="_blank" .external-link} account and [credentials](/integrations/builtin/credentials/google/) to access Gmail.
* A [Discord](https://discord.com/){:target="_blank" .external-link} account and webhook URL (you receive this using email when you sign up for this course).
Next, you will build these three workflows with step-by-step instructions.

View File

@ -4,27 +4,27 @@ contentType: tutorial
# Workflow 1: Merging data
The company's customer data is stored in Airtable. It contains information about the customers' ID, country, email, and join date, but lacks data about their respective region and subregion. You need to fill in these last two fields in order to create the reports for regional sales.
Nathan's company stores its customer data in Airtable. This data contains information about the customers' ID, country, email, and join date, but lacks data about their respective region and subregion. You need to fill in these last two fields in order to create the reports for regional sales.
To accomplish this task, you first need to make a copy of this table in your Airtable account:
<iframe class="airtable-embed" src="https://airtable.com/embed/shrNX9tjPkVLABbNz?backgroundColor=orange&viewControls=on" frameborder="0" onmousewheel="" width="100%" height="533" style="background: transparent; border: 1px solid #ccc;"></iframe>
Next, you have to build a small workflow that merges data from Airtable and a REST API.
Next, build a small workflow that merges data from Airtable and a REST Countries API:
1. Use the [Airtable node](/integrations/builtin/app-nodes/n8n-nodes-base.airtable/){:target="_blank" .external} to list the data in the Airtable table named `customers`.
2. use the [HTTP Request node](/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/){:target="_blank" .external} to get data from the REST Countries API: `https://restcountries.com/v3.1/all`. This will return data about world countries, split out into separate items.
3. Use the [Merge node](/integrations/builtin/core-nodes/n8n-nodes-base.merge/){:target="_blank" .external} to merge data from Airtable and the Countries API by country name (the common key), represented as `customerCountry` in Airtable and `name.common` in the Countries API, respectively.
4. Use the Airtable node to update the fields `region` and `subregion` in Airtable with the data from the Countries API.
1. Use the [**Airtable node**](/integrations/builtin/app-nodes/n8n-nodes-base.airtable/) to list the data in the Airtable table named `customers`.
2. Use the [**HTTP Request node**](/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/) to get data from the REST Countries API: `https://restcountries.com/v3.1/all`. This will return data about world countries, split out into separate items.
3. Use the [**Merge node**](/integrations/builtin/core-nodes/n8n-nodes-base.merge/) to merge data from Airtable and the Countries API by country name, represented as `customerCountry` in Airtable and `name.common` in the Countries API, respectively.
4. Use another Airtable node to update the fields `region` and `subregion` in Airtable with the data from the Countries API.
The workflow should look like this:
<figure><img src="/_images/courses/level-two/chapter-five/workflow1.png" alt="" style="width:100%"><figcaption align = "center"><i>Workflow 1 for merging data from Airtable and the Countries API</i></figcaption></figure>
<figure><img src="/_images/courses/level-two/chapter-five/workflow1.png" alt="Workflow 1 for merging data from Airtable and the Countries API" style="width:100%"><figcaption align = "center"><i>Workflow 1 for merging data from Airtable and the Countries API</i></figcaption></figure>
/// question | Quiz questions
* How many items does the HTTP Request node return?
* How many items does the Merge node return?
* How many items does the **HTTP Request node** return?
* How many items does the **Merge node** return?
* How many unique regions are assigned in the customers table?
* What's the subregion assigned to the customerID 10?
///

View File

@ -6,7 +6,7 @@ contentType: tutorial
In this workflow, you will merge data from different sources, transform binary data, generate files, and send notifications about them. The final workflow should look like this:
<figure><img src="/_images/courses/level-two/chapter-five/workflow2.png" alt="" style="width:100%"><figcaption align = "center"><i>Workflow 2 for aggregating data and generating files</i></figcaption></figure>
<figure><img src="/_images/courses/level-two/chapter-five/workflow2.png" alt="Workflow 2 for aggregating data and generating files" style="width:100%"><figcaption align = "center"><i>Workflow 2 for aggregating data and generating files</i></figcaption></figure>
To make things easier, let's split the workflow into three parts.
@ -14,21 +14,23 @@ To make things easier, let's split the workflow into three parts.
The first part of the workflow consists of five nodes:
<figure><img src="/_images/courses/level-two/chapter-five/workflow2_1.png" alt="" style="width:100%"><figcaption align = "center"><i>Workflow 1 Getting data from different sources</i></figcaption></figure>
<figure><img src="/_images/courses/level-two/chapter-five/workflow2_1.png" alt="Workflow 1: Getting data from different sources" style="width:100%"><figcaption align = "center"><i>Workflow 1: Getting data from different sources</i></figcaption></figure>
1. Use the [HTTP Request node](/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/){:target="_blank" .external} to get data from the API endpoint that stores company data. Configure the following node parameters:
1. Use the [**HTTP Request node**](/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/) to get data from the API endpoint that stores company data. Configure the following node parameters:
* **Authentication**: Header Auth
* **Credentials for Header Auth**: The Header Auth name and Header Auth value you received in the email when you signed up for this course.
* **URL**: The Dataset URL you received in the email when you signed up for this course.
* **Options** > **Add Option** > **Split Into Items**: toggle to true.
* **Headers** > **Add Header**:
* **Name**: `unique_id`
* **Value**: The unique ID you received in the email when you signed up for this course.
- **Method**: Get
- **URL**: The **Dataset URL** you received in the email when you signed up for this course.
- **Authentication**: Generic Credential Type
- **Generic Auth Type**: Header Auth
- **Credentials for Header Auth**: The Header Auth name and Header Auth value you received in the email when you signed up for this course.
- **Send Headers**: Toggle to true
- **Specify Headers**: Select `Using Fields Below`
- **Name**: `unique_id`
- **Value**: The unique ID you received in the email when you signed up for this course.
2. Use the [Airtable node](/integrations/builtin/app-nodes/n8n-nodes-base.airtable/){:target="_blank" .external} to list data from the `customers` table (where you updated the fields `region` and `subregion`).
3. Use the [Merge node](/integrations/builtin/core-nodes/n8n-nodes-base.merge/){:target="_blank" .external} to merge data from the Airtable and HTTP Request node, based on the common key `customer ID`.
4. Use the [Sort](/integrations/builtin/core-nodes/n8n-nodes-base.sort/) node to sort data by `orderPrice` in descending order.
2. Use the [**Airtable node**](/integrations/builtin/app-nodes/n8n-nodes-base.airtable/) to list data from the `customers` table (where you updated the fields `region` and `subregion`).
3. Use the [**Merge node**](/integrations/builtin/core-nodes/n8n-nodes-base.merge/) to merge data from the Airtable and HTTP Request node, based on matching the input fields for `customerID`.
4. Use the [**Sort node**](/integrations/builtin/core-nodes/n8n-nodes-base.sort/) to sort data by `orderPrice` in descending order.
/// question | Quiz questions
* What's the name of the employee assigned to customer 1?
@ -38,46 +40,47 @@ The first part of the workflow consists of five nodes:
## Part 2: Generating file for regional sales
The second part of the workflow consists of five nodes:
The second part of the workflow consists of four nodes:
<figure><img src="/_images/courses/level-two/chapter-five/workflow2_2.png" alt="" style="width:100%"><figcaption align = "center"><i>Workflow 2 Generating file for regional sales</i></figcaption></figure>
<figure><img src="/_images/courses/level-two/chapter-five/workflow2_2.png" alt="Workflow 2: Generating file for regional sales" style="width:100%"><figcaption align = "center"><i>Workflow 2: Generating file for regional sales</i></figcaption></figure>
1. Use the [IF node](/integrations/builtin/core-nodes/n8n-nodes-base.if/){:target="_blank" .external} to filter order from the region Americas.
2. Use the [Convert to File](/integrations/builtin/core-nodes/n8n-nodes-base.converttofile/){:target="_blank" .external} to transform the incoming data from JSON to binary format. Convert each item to a file.
3. Use the [Gmail node](/integrations/builtin/app-nodes/n8n-nodes-base.gmail/){:target="_blank" .external} (or another email node) to send the files using email to an address you have access to. Note that you need to add an attachment with the data property.
4. Use the [Discord node](/integrations/builtin/app-nodes/n8n-nodes-base.discord/){:target="_blank" .external} to send a message in the n8n Discord channel `#course-level-two`. In the node, configure the following parameters:
* Webhook URL: The webhook URL you received in the email when you signed up for this course.
* Text: "I sent the file using email with the label ID `{label ID}`. My ID: " followed by your ID. <br/> Note that you need to replace the text in curly braces `{}` with expressions that reference the data from the nodes.
1. Use the [**If node**](/integrations/builtin/core-nodes/n8n-nodes-base.if/) to filter to only display orders from the region `Americas`.
2. Use the [**Convert to File**](/integrations/builtin/core-nodes/n8n-nodes-base.converttofile/) to transform the incoming data from JSON to binary format. Convert each item to a separate file. (Bonus points if you can figure out how to name each report based on the orderID!)
3. Use the [**Gmail node**](/integrations/builtin/app-nodes/n8n-nodes-base.gmail/) (or another email node) to send the files using email to an address you have access to. Note that you need to add an attachment with the data property.
4. Use the [**Discord node**](/integrations/builtin/app-nodes/n8n-nodes-base.discord/) to send a message in the n8n Discord channel `#course-level-two`. In the node, configure the following parameters:
* **Webhook URL**: The Discord URL you received in the email when you signed up for this course.
* **Text**: "I sent the file using email with the label ID `{label ID}`. My ID: " followed by the unique ID emailed to you when you registered for this course. <br/> Note that you need to replace the text in curly braces `{}` with expressions that reference the data from the nodes.
/// question | Quiz questions
* How many orders are assigned to the region Americas?
* What's the total price of the orders in the region Americas?
* How many items are returned by the *Write Binary File node*?
* How many orders are assigned to the `Americas` region?
* What's the total price of the orders in the `Americas` region?
* How many items does the **Write Binary File node** return?
///
## Part 3: Generating files for total sales
The third part of the workflow consists of seven nodes:
The third part of the workflow consists of five nodes:
<figure><img src="/_images/courses/level-two/chapter-five/workflow2_3.png" alt="" style="width:100%"><figcaption align = "center"><i>Workflow 3 Generating files for total sales</i></figcaption></figure>
<figure><img src="/_images/courses/level-two/chapter-five/workflow2_3.png" alt="Workflow 3: Generating files for total sales" style="width:100%"><figcaption align = "center"><i>Workflow 3: Generating files for total sales</i></figcaption></figure>
1. Use the [Loop Over Items node](/integrations/builtin/core-nodes/n8n-nodes-base.splitinbatches/){:target="_blank" .external} to split data from the Item Lists node into batches of 5.
2. Use the [Set node](/integrations/builtin/core-nodes/n8n-nodes-base.set/){:target="_blank" .external} to set four values, referenced with expressions from the previous node: `customerEmail`, `customerRegion`, `customerSince`, and `orderPrice`.
3. Use the [Date & Time node](/integrations/builtin/core-nodes/n8n-nodes-base.datetime/){:target="_blank" .external} to change the date format of the field `customerSince` to the format MM/DD/YYYY. Set the 'Include Input Fields' option to keep all the data together.
4. Use the [Convert to File node](/integrations/builtin/core-nodes/n8n-nodes-base.converttofile/){:target="_blank" .external} to create a CSV spreadsheet with the file name set as the expression: `{{$runIndex > 0 ? 'file_low_orders':'file_high_orders'}}`.
5. Use the [Discord node](/integrations/builtin/app-nodes/n8n-nodes-base.discord/){:target="_blank" .external} to send a message in the n8n Discord channel `#course-level-two`. In the node, configure the following parameters:
* Webhook URL: The webhook URL you received in the email when you signed up for this course.
* Text: "I created the spreadsheet `{file name}`. My ID:" followed by your ID. <br/> The `{file name}` should be an expression that references data from the Spreadsheet File node.<br/>
1. Use the [**Loop Over Items node**](/integrations/builtin/core-nodes/n8n-nodes-base.splitinbatches/) to split data from the Item Lists node into batches of 5.
2. Use the [**Set node**](/integrations/builtin/core-nodes/n8n-nodes-base.set/) to set four values, referenced with expressions from the previous node: `customerEmail`, `customerRegion`, `customerSince`, and `orderPrice`.
3. Use the [**Date & Time node**](/integrations/builtin/core-nodes/n8n-nodes-base.datetime/) to change the date format of the field `customerSince` to the format MM/DD/YYYY.
- Set the **Include Input Fields** option to keep all the data together.
4. Use the [**Convert to File node**](/integrations/builtin/core-nodes/n8n-nodes-base.converttofile/) to create a CSV spreadsheet with the file name set as the expression: `{{$runIndex > 0 ? 'file_low_orders':'file_high_orders'}}`.
5. Use the [**Discord node**](/integrations/builtin/app-nodes/n8n-nodes-base.discord/) to send a message in the n8n Discord channel `#course-level-two`. In the node, configure the following parameters:
* **Webhook URL**: The Discord URL you received in the email when you signed up for this course.
* **Text**: "I created the spreadsheet `{file name}`. My ID:" followed by the unique ID emailed to you when you registered for this course. <br/> Note that you need to replace `{file name}` with an expression that references data from the previous **Convert to File node**.<br/>
/// question | Quiz questions
* What's the lowest order price in the first batch of items?
* What's the formatted date of customer 7?
* How many items are returned by the *Convert to File node*?
* How many items does the **Convert to File node** return?
///
??? note "Show me the solution"
To check the configuration of the nodes, you can copy-paste the JSON code of the workflow:
To check the configuration of the nodes, you can copy the JSON workflow code below and paste it into your Editor UI:
```json
{

View File

@ -4,26 +4,29 @@ contentType: tutorial
# Workflow 3: Monitoring workflow errors
To accomplish this task, you have to create an Error workflow that monitors the main workflow.
Last but not least, let's help Nathan know if there are any errors running the workflow.
1. Add an Error Trigger node (and execute it as a test).
2. To the Error Trigger node, connect a Discord node and configure the fields:<br/>
To accomplish this task, create an Error workflow that monitors the main workflow:
* Webhook URL: The URL that you received in the email from n8n when you signed up for this course.
* Text: The workflow `{workflow name}` failed, with the error message: `{execution error message}`. Last node executed: `{name of the last executed node}`. Check this workflow execution here: `{execution URL}` My Unique ID: `{your ID from the course signup email}`
1. Create a new workflow.
2. Add an **Error Trigger node** (and execute it as a test).
3. Connect a **Discord node** to the **Error Trigger node** and configure these fields:<br/>
* **Webhook URL**: The Discord URL that you received in the email from n8n when you signed up for this course.
* **Text**: "The workflow `{workflow name}` failed, with the error message: `{execution error message}`. Last node executed: `{name of the last executed node}`. Check this workflow execution here: `{execution URL}` My Unique ID: " followed by the unique ID emailed to you when you registered for this course.
Note that you need to replace the text in curly brackets `{}` with expressions that take the respective information from the Error Trigger node.<br/>
3. Execute the Discord node.
4. Set the newly created workflow as Error Workflow for the main workflow.
4. Execute the Discord node.
5. Set the newly created workflow as the **Error Workflow** for the main workflow you created in the previous lesson.
The workflow should look like this:
<figure><img src="/_images/courses/level-two/chapter-five/workflow3.png" alt="" style="width:100%"><figcaption align = "center"><i>Workflow 3 for monitoring workflow errors</i></figcaption></figure>
<figure><img src="/_images/courses/level-two/chapter-five/workflow3.png" alt="Workflow 3 for monitoring workflow errors" style="width:100%"><figcaption align = "center"><i>Workflow 3 for monitoring workflow errors</i></figcaption></figure>
/// question | Quiz questions
* What fields does the Error Trigger node return?
* What information about the execution does the Error Trigger node return?
* What information about the workflow does the Error Trigger node return?
* What fields does the **Error Trigger node** return?
* What information about the execution does the **Error Trigger node** return?
* What information about the workflow does the **Error Trigger node** return?
* What's the expression to reference the workflow name?
///

View File

@ -21,4 +21,4 @@ You can test your knowledge by taking a **quiz**, which consists of questions ab
## What's next?
- Create new workflows for your work or personal use and share them with us. Don't have any ideas? Find inspiration on the [workflows page](https://n8n.io/workflows){:target="_blank" .external-link} and on our [blog](https://n8n.io/blog/){:target="_blank" .external-link}.
- Dive deeper into n8n's features by reading the [docs](/){:target="_blank" .external}.
- Dive deeper into n8n's features by reading the [docs](/).

View File

@ -24,20 +24,20 @@ The focus in this course is on working with data. You will learn how to:
- Use functions and JavaScript code in the [Code node](/integrations/builtin/core-nodes/n8n-nodes-base.code).
- Deal with error workflows and workflow errors.
You will learn all this by completing short practical exercises after the theoretical explanations, and building a business workflow following instructions.
You will learn all this by completing short practical exercises after the theoretical explanations and building a business workflow following instructions.
## What do I need to get started?
To follow along this course (at a comfortable pace) you will need the following:
- **n8n set up**: You can use the [self-hosted version](/hosting/installation/npm/) or [n8n Cloud](/manage-cloud/overview/).
- **A user ID**: [Sign up here](https://n8n-community.typeform.com/to/HQoQ7nXg) to get your unique ID and other credentials you will need in the course.
- **Basic n8n skills**. We strongly recommend taking the [Level 1 course](/courses/level-one/) prior to this one.
- **Basic JavaScript understanding**.
- **A user ID**: [Sign up here](https://n8n-community.typeform.com/to/HQoQ7nXg){:target="_blank" .external-link} to get your unique ID and other credentials you will need in the course.
- **Basic n8n skills**: We strongly recommend taking the [Level 1 course](/courses/level-one/) before this one.
- **Basic JavaScript understanding**
## How long does the course take?
Completing the course should take around **two hours**. You don't have to complete it in one go, feel free to take breaks and resume whenever you are ready.
Completing the course should take around **two hours**. You don't have to complete it in one go; feel free to take breaks and resume whenever you are ready.
## How do I complete the course?
@ -46,6 +46,6 @@ There are two milestones in this course that test your knowledge of what you hav
- [x] Building the [main workflow](/courses/level-two/chapter-5/chapter-5.0/)
- [x] Passing the [quiz](https://n8n-community.typeform.com/to/r9hDbytg){:target="_blank" .external} at the end of the course
You can always **check your progress** throughout the course by entering your unique ID [here](https://internal.users.n8n.cloud/webhook/course-level-2/verify).
You can always **check your progress** throughout the course by entering your unique ID [here](https://internal.users.n8n.cloud/webhook/course-level-2/verify){:target="_blank" .external-link}.
If you successfully complete the milestones above, you will get [**a badge and an avatar**](https://community.n8n.io/badges/105/completed-n8n-course-level-2){:target="_blank" .external} in your forum profile. You can then share your profile and course verification ID to showcase your n8n skills to others.

View File

@ -55,8 +55,6 @@ The repository for the docs is [here](https://github.com/n8n-io/n8n-docs){:targe
You can write an article for the [n8n blog](https://n8n.io/blog/){:target=_blank class=.external-link}. Your article can be, for example, a [workflow tutorial](https://n8n.io/blog/tag/tutorial/){:target=_blank class=.external-link}, an opinion piece on automation, or some domain-specific [automation ideas](https://n8n.io/blog/tag/ideas/){:target=_blank class=.external-link}.
[This board](https://github.com/orgs/n8n-io/projects/3){:target=_blank .external-link} lists the most in-demand topics.
### Process to submit a post
n8n appreciates all contributions. Publishing a tutorial on your own site that supports the community is a great contribution. However, if you want n8n to highlight your post on our blog, you need to go through this process.

View File

@ -19,8 +19,9 @@ This page lists the deployment configuration options for your self-hosted n8n in
| :------- | :---- | :------- | :---------- |
| `N8N_EDITOR_BASE_URL` | String | - | Public URL where users can access the editor. Also used for emails sent from n8n. |
| `N8N_CONFIG_FILES` | String | - | Use to provide the path to any JSON [configuration file](/hosting/configuration/configuration-methods/). |
| `N8N_DISABLE_UI` | Boolean | `false` | Disable the UI (true) or not (false). |
| `N8N_TEMPLATES_ENABLED` | Boolean | `true` | Enable workflow templates (true) or disable (false). |
| `N8N_DISABLE_UI` | Boolean | `false` | Set to `true` to disable the UI. |
| `N8N_PREVIEW_MODE` | Boolean | `false` | Set to `true` to run in preview mode. |
| `N8N_TEMPLATES_ENABLED` | Boolean | `false` | Enables workflow templates (true) or disable (false). |
| `N8N_TEMPLATES_HOST` | String | `https://api.n8n.io` | Change this if creating your own workflow template library. Note that to use your own workflow templates library, your API must provide the same endpoints and response structure as n8n's. Refer to [Workflow templates](/workflows/templates/) for more information. |
| `N8N_ENCRYPTION_KEY` | String | Random key generated by n8n | Provide a custom key used to encrypt credentials in the n8n database. By default n8n generates a random key on first launch. |
| `N8N_USER_FOLDER` | String | `user-folder` | Provide the path where n8n will create the `.n8n` folder. This directory stores user-specific data, such as database file and encryption key. |
@ -34,15 +35,17 @@ This page lists the deployment configuration options for your self-hosted n8n in
| `N8N_PERSONALIZATION_ENABLED` | Boolean | `true` | Whether to ask users personalisation questions and then customise n8n accordingly. |
| `N8N_VERSION_NOTIFICATIONS_ENABLED` | Boolean | `true` | When enabled, n8n sends notifications of new versions and security updates. |
| `N8N_VERSION_NOTIFICATIONS_ENDPOINT` | String | `https://api.n8n.io/versions/` | The endpoint to retrieve where version information. |
| `N8N_VERSION_NOTIFICATIONS_INFO_URL` | String | `https://docs.n8n.io/getting-started/installation/updating.html` | The URL displayed in the New Versions panel for additional information. |
| `N8N_VERSION_NOTIFICATIONS_INFO_URL` | String | `https://docs.n8n.io/getting-started/installation/updating.html` | The URL displayed in the New Versions panel for more information. |
| `N8N_DIAGNOSTICS_ENABLED` | Boolean | `true` | Whether to share selected, anonymous [telemetry](/privacy-security/privacy/) with n8n. Note that if you set this to `false`, you can't enable Ask AI in the Code node. |
| `N8N_DIAGNOSTICS_CONFIG_FRONTEND` | String | `1zPn9bgWPzlQc0p8Gj1uiK6DOTn;https://telemetry.n8n.io` | Telemetry configuration for the frontend. |
| `N8N_DIAGNOSTICS_CONFIG_BACKEND` | String | `1zPn7YoGC3ZXE9zLeTKLuQCB4F6;https://telemetry.n8n.io/v1/batch` | Telemetry configuration for the backend. |
| `N8N_PUSH_BACKEND` | String | `websocket` | Choose whether the n8n backend uses server-sent events (`sse`) or WebSockets (`websocket`) to send changes to the UI. |
| `VUE_APP_URL_BASE_API` | String | `http://localhost:5678/` | Used when building the `n8n-editor-ui` package manually to set how the frontend can reach the backend API. Refer to [Configure the Base URL](/hosting/configuration/configuration-examples/base-url/).
|
| `VUE_APP_URL_BASE_API` | String | `http://localhost:5678/` | Used when building the `n8n-editor-ui` package manually to set how the frontend can reach the backend API. Refer to [Configure the Base URL](/hosting/configuration/configuration-examples/base-url/). |
| `N8N_HIRING_BANNER_ENABLED` | Boolean | `true` | Whether to show the n8n hiring banner in the console (true) or not (false). |
| `N8N_PUBLIC_API_SWAGGERUI_DISABLED` | Boolean | `false` | Whether the Swagger UI (API playground) is disabled (true) or not (false). |
| `N8N_PUBLIC_API_DISABLED` | Boolean | `false` | Whether to disable the public API (true) or not (false). |
| `N8N_PUBLIC_API_ENDPOINT` | String | `api` | Path for the public API endpoints. |
| `N8N_GRACEFUL_SHUTDOWN_TIMEOUT` | Number | `30` | How long should the n8n process wait (in seconds) for components to shut down before exiting the process. |
| `N8N_DEV_RELOAD` | Boolean | `false` | When working on the n8n source code, set this to `true` to automatically reload or restart the application when changes occur in the source code files. |
| `N8N_REINSTALL_MISSING_PACKAGES` | Boolean | `false` | If set to `true`, n8n will automatically attempt to reinstall any missing packages. |
| `N8N_TUNNEL_SUBDOMAIN` | String | - | Specifies the subdomain for the n8n tunnel. If not set, n8n generates a random subdomain.|

View File

@ -30,3 +30,4 @@ This page lists environment variables to configure workflow execution settings.
| `EXECUTIONS_DATA_HARD_DELETE_BUFFER` | Number | `1` | How old (hours) the finished execution data has to be to get hard-deleted. By default, this buffer excludes recent executions as the user may need them while building a workflow. |
| `EXECUTIONS_DATA_PRUNE_HARD_DELETE_INTERVAL` | Number | `15` | How often (minutes) execution data should be hard-deleted. |
| `EXECUTIONS_DATA_PRUNE_SOFT_DELETE_INTERVAL` | Number | `60` | How often (minutes) execution data should be soft-deleted. |
| `N8N_CONCURRENCY_PRODUCTION_LIMIT` | Number | `-1` | Max production executions allowed to run concurrently, in both regular and scaling modes. `-1` to disable in regular mode. |

View File

@ -17,4 +17,5 @@ You can define external hooks that n8n executes whenever a specific operation ru
| Variable | Type | Description |
| :------- | :---- | :---------- |
| `EXTERNAL_HOOK_FILES` | String | Files containing external hooks. Provide multiple files as a colon-separated list ("`:`"). |
| `EXTERNAL_HOOK_FILES` | String | Files containing backend external hooks. Provide multiple files as a colon-separated list ("`:`"). |
| `EXTERNAL_FRONTEND_HOOKS_URLS` | String | URLs to files containing frontend external hooks. Provide multiple URLs as a colon-separated list ("`:`"). |

View File

@ -28,6 +28,7 @@ This page lists environment variables to set up logging for debugging. Refer to
| `DB_LOGGING_ENABLED` | Boolean | `false` | Whether to enable database-specific logging. |
| `DB_LOGGING_OPTIONS` | Enum string: `query`, `error`, `schema`, `warn`, `info`, `log` | `error` | Database log output level. To enable all logging, specify `all`. Refer to [TypeORM logging options](https://orkhan.gitbook.io/typeorm/docs/logging#logging-options){:target=_blank .external-link} |
| `DB_LOGGING_MAX_EXECUTION_TIME` | Number | `1000` | Maximum execution time (in milliseconds) before n8n logs a warning. Set to `0` to disable long running query warning. |
| `CODE_ENABLE_STDOUT` | Boolean | `false` | Set to`true` to send Code node logs to process's stdout for debugging, monitoring, or logging purposes. |
## Log streaming

View File

@ -16,3 +16,7 @@ hide:
| Variable | Type | Default | Description |
| :------- | :---- | :------- | :---------- |
| `N8N_BLOCK_ENV_ACCESS_IN_NODE` | Boolean | `false` | Whether to allow users to access environment variables in expressions and the Code node (false) or not (true). |
| `N8N_RESTRICT_FILE_ACCESS_TO` | String | | Limits access to files in these directories. Provide multiple files as a colon-separated list ("`:`"). |
| `N8N_BLOCK_FILE_ACCESS_TO_N8N_FILES` | Boolean | `true` | Set to `true` to block access to all files in the `.n8n` directory and user defined configuration files. |
| `N8N_SECURITY_AUDIT_DAYS_ABANDONED_WORKFLOW` | Number | 90 | Number of days to consider a workflow abandoned if it's not executed. |
| `N8N_SECURE_COOKIE` | Boolean | `true` | Ensures that cookies are only sent over HTTPS, enhancing security.|

View File

@ -0,0 +1,31 @@
---
contentType: explanation
---
# Concurrency control
In regular mode, n8n doesn't limit how many production executions may run at the same time. This can lead to a scenario where too many concurrent executions thrash the event loop, causing performance degradation and unresponsiveness.
To prevent this, you can set a concurrency limit for production executions in regular mode. Use this to control how many production executions run concurrently, and queue up any concurrent production executions over the limit. These executions remain in the queue until concurrency capacity frees up, and are then processed in FIFO order.
Concurrency control is disabled by default. To enable it:
```sh
export N8N_CONCURRENCY_PRODUCTION_LIMIT=20
```
Keep in mind:
- Concurrency control applies only to production executions: those started from a webhook or trigger node. It doesn't apply to any other kinds, such as manual executions, sub-workflow executions, error executions, or started from CLI.
- You can't retry queued executions. Cancelling or deleting a queued execution also removes it from the queue.
- On instance startup, n8n resumes queued executions up to the concurrency limit and re-enqueues the rest.
<!-- vale off -->
- To monitor concurrency control, watch logs for executions being added to the queue and released. In a future version, n8n will show concurrency control in the UI.
<!-- vale on -->
## Comparison to scaling mode
In scaling mode, you can control how many jobs a worker may run concurrently using the [`--concurrency` flag](/hosting/scaling/queue-mode/#configure-worker-concurrency).
Concurrency control in scaling mode is a separate mechanism from concurrency control in regular mode, but the environment variable `N8N_CONCURRENCY_PRODUCTION_LIMIT` controls both of them. In scaling mode, n8n takes the limit from this variable if set to a value other than `-1`, falling back to the `--concurrency` flag or its default.

View File

@ -10,6 +10,9 @@ Use the Autopilot node to automate work in Autopilot, and integrate Autopilot wi
On this page, you'll find a list of operations the Autopilot node supports and links to more resources.
/// warning | Autopilot branding change
Autopilot has become Ortto. The Autopilot credentials and nodes are only compatible with Autopilot, not the new Ortto API.
///
/// note | Credentials
Refer to [Autopilot credentials](/integrations/builtin/credentials/autopilot/) for guidance on setting up authentication.
///
@ -28,12 +31,12 @@ For usage examples and templates to help you get started, take a look at n8n's [
* Contact Journey
* Add contact to list
* Contact List
* Add contact to list.
* Check if contact is on list.
* Get all contacts on list.
* Remove a contact from a list.
* Add contact to list
* Check if contact is on list
* Get all contacts on list
* Remove a contact from a list
* List
* Create a list.
* Create a list
* Get all lists

View File

@ -6,7 +6,13 @@ contentType: integration
# S3
Use the S3 node to automate work in S3, and integrate S3 with other applications. n8n has built-in support for a wide range of S3 features, including creating, deleting, and getting buckets, files, and folders.
Use the S3 node to automate work in non-AWS S3 storage and integrate S3 with other applications. n8n has built-in support for a wide range of S3 features, including creating, deleting, and getting buckets, files, and folders. For AWS S3, use [AWS S3](/integrations/builtin/app-nodes/n8n-nodes-base.awss3/).
Use the S3 node for non-AWS S3 solutions like:
* [MinIO](https://min.io/){:target="_blank" .external-link}
* [Wasabi](https://wasabi.com/){:target="_blank" .external-link}
* [Digital Ocean spaces](https://www.digitalocean.com/products/spaces){:target="_blank" .external-link}
On this page, you'll find a list of operations the S3 node supports and links to more resources.
@ -30,19 +36,21 @@ For usage examples and templates to help you get started, take a look at n8n's [
* Download a file
* Get all files
* Upload a file
/// note | Attach file for upload
To attach a file for upload, use another node to pass the file as a data property. Nodes like the [Read/Write Files from Disk](/integrations/builtin/core-nodes/n8n-nodes-base.filesreadwrite/) node or the [HTTP Request](/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/) work well.
///
* Folder
* Create a folder
* Delete a folder
* Get all folders
**Note:** To attach a file for upload, you will need to use an additional node such as the [Read/Write Files from Disk](/integrations/builtin/core-nodes/n8n-nodes-base.filesreadwrite/) node or the [HTTP Request](/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/) node to pass the file as a data property.
## Node reference
### Setting file permissions in Wasabi
When uploading files to [Wasabi](https://wasabi.com/), permissions for the files must be set using the **ACL** dropdown and not the toggles.
When uploading files to [Wasabi](https://wasabi.com/){:target="_blank" .external-link}, you must set permissions for the files using the **ACL** dropdown and not the toggles.
![File permissions when using the S3 node with Wasabi](/_images/integrations/builtin/app-nodes/s3/acl_dropdown.png)

View File

@ -1,20 +1,20 @@
---
title: Twitter
description: Documentation for the Twitter node in n8n, a workflow automation platform. Includes details of operations and configuration, and links to examples and credentials information.
title: X
description: Documentation for the X node in n8n, a workflow automation platform. Includes details of operations and configuration, and links to examples and credentials information.
contentType: integration
---
# Twitter
# X
Use the Twitter node to automate work in Twitter, and integrate Twitter with other applications. n8n has built-in support for a wide range of Twitter features, including creating direct messages, and deleting, searching, liking and retweeting a tweet.
Use the X node to automate work in X and integrate X with other applications. n8n has built-in support for a wide range of X features, including creating direct messages and deleting, searching, liking, and retweeting a tweet.
On this page, you'll find a list of operations the Twitter node supports and links to more resources.
On this page, you'll find a list of operations the X node supports and links to more resources.
/// note | Credentials
Refer to [Twitter credentials](/integrations/builtin/credentials/twitter/) for guidance on setting up authentication.
Refer to [X credentials](/integrations/builtin/credentials/twitter/) for guidance on setting up authentication.
///
/// note | Examples and templates
For usage examples and templates to help you get started, take a look at n8n's [Twitter integrations](https://n8n.io/integrations/twitter/){:target="_blank" .external-link} list.
For usage examples and templates to help you get started, take a look at n8n's [X integrations](https://n8n.io/integrations/twitter/){:target="_blank" .external-link} list.
///
## Basic Operations

View File

@ -1,20 +1,20 @@
---
title: VERO
description: Documentation for the VERO node in n8n, a workflow automation platform. Includes details of operations and configuration, and links to examples and credentials information.
title: Vero
description: Documentation for the Vero node in n8n, a workflow automation platform. Includes details of operations and configuration, and links to examples and credentials information.
contentType: integration
---
# VERO
# Vero
Use the VERO node to automate work in VERO, and integrate VERO with other applications. n8n has built-in support for a wide range of VERO features, including creating and deleting users.
Use the Vero node to automate work in Vero and integrate Vero with other applications. n8n has built-in support for a wide range of Vero features, including creating and deleting users.
On this page, you'll find a list of operations the VERO node supports and links to more resources.
On this page, you'll find a list of operations the Vero node supports and links to more resources.
/// note | Credentials
Refer to [VERO credentials](/integrations/builtin/credentials/vero/) for guidance on setting up authentication.
Refer to [Vero credentials](/integrations/builtin/credentials/vero/) for guidance on setting up authentication.
///
/// note | Examples and templates
For usage examples and templates to help you get started, take a look at n8n's [VERO integrations](https://n8n.io/integrations/vero/){:target="_blank" .external-link} list.
For usage examples and templates to help you get started, take a look at n8n's [Vero integrations](https://n8n.io/integrations/vero/){:target="_blank" .external-link} list.
///
## Basic Operations

View File

@ -31,4 +31,10 @@ View [example workflows and related content](https://n8n.io/integrations/window-
Refer to [LangChain's Buffer Window Memory documentation](https://js.langchain.com/docs/modules/memory/types/buffer_window){:target=_blank .external-link} for more information about the service.
--8<-- "_snippets/integrations/builtin/cluster-nodes/langchain-overview-link.md"
## Single memory instance
[[% include "_includes/integrations/cluster-nodes/memory-shared.html" %]]
--8<-- "_glossary/ai-glossary.md"

View File

@ -7,6 +7,8 @@ description: Documentation for the Chat Memory Manager node in n8n, a workflow a
The Chat Memory Manager node manages chat message memories within your workflows. Use this node to load, insert, and delete chat messages in an in-memory vector store.
--8<-- "_snippets/integrations/builtin/cluster-nodes/langchain-sub-nodes/chat-memory-manager-purpose.md"
On this page, you'll find a list of operations that the Chat Memory Manager node supports, along with links to more resources.
/// note | Examples and templates
@ -20,8 +22,14 @@ For usage examples and templates to help you get started, refer to n8n's [Chat M
* **Operation Mode**: choose between **Get Many Messages**, **Insert Messages**, and **Delete Messages** operations.
* **Insert Mode**: available in **Insert Messages** mode. Choose between **Insert Messages** to add alongside existing messages or **Override All Messages** to replace current memory.
* **Delete Mode**: available in **Delete Messages** mode. Select either **Last N** to delete the last N messages or **All Messages** to clear all messages from memory.
* **Chat Messages**: available in **Insert Messages** mode. Define the chat messages to insert into the memory, including message type (AI, System, User), message content, and visibility in UI.
* **Messages Count**: available in **Delete Messages** mode and when **Last N** is selected. Specify the number of latest messages to delete.
* **Chat Messages**: available in **Insert Messages** mode. Define the chat messages to insert into the memory, including:
* **Type Name or ID**: set the message type. Select one of:
* **AI**: use this for messages from the AI.
* **System**: add a message containing instructions for the AI.
* **User**: use this for messages from the user. This message type is sometimes called the 'human' message in other AI tools and guides.
* **Message**: the message contents.
* **Hide Message in Chat**: whether n8n should display the message to the user in the chat UI.
* **Messages Count**: available in **Delete Messages** mode and when you select **Last N**. Specify the number of latest messages to delete.
* **Simplify Output**: available in **Get Many Messages** mode. Toggle to simplify the output to include only the sender (AI, user, or system) and the text.
## Related resources

View File

@ -31,4 +31,9 @@ View [example workflows and related content](https://n8n.io/integrations/motorhe
Refer to [LangChain's Motorhead documentation](https://js.langchain.com/docs/modules/memory/integrations/motorhead_memory){:target=_blank .external-link} for more information about the service.
--8<-- "_snippets/integrations/builtin/cluster-nodes/langchain-overview-link.md"
## Single memory instance
[[% include "_includes/integrations/cluster-nodes/memory-shared.html" %]]
--8<-- "_glossary/ai-glossary.md"

View File

@ -31,4 +31,9 @@ View [example workflows and related content](https://n8n.io/integrations/redis-c
Refer to [LangChain's Redis Chat Memory documentation](https://js.langchain.com/docs/modules/memory/integrations/redis){:target=_blank .external-link} for more information about the service.
--8<-- "_snippets/integrations/builtin/cluster-nodes/langchain-overview-link.md"
## Single memory instance
[[% include "_includes/integrations/cluster-nodes/memory-shared.html" %]]
--8<-- "_glossary/ai-glossary.md"

View File

@ -31,4 +31,9 @@ View [example workflows and related content](https://n8n.io/integrations/xata/){
Refer to [LangChain's Xata documentation](https://js.langchain.com/docs/modules/memory/integrations/xata){:target=_blank .external-link} for more information about the service.
--8<-- "_snippets/integrations/builtin/cluster-nodes/langchain-overview-link.md"
## Single memory instance
[[% include "_includes/integrations/cluster-nodes/memory-shared.html" %]]
--8<-- "_glossary/ai-glossary.md"

View File

@ -30,4 +30,9 @@ View [example workflows and related content](https://n8n.io/integrations/zep/){:
Refer to [LangChain's Zep documentation](https://js.langchain.com/docs/modules/memory/integrations/zep_memory){:target=_blank .external-link} for more information about the service.
--8<-- "_snippets/integrations/builtin/cluster-nodes/langchain-overview-link.md"
## Single memory instance
[[% include "_includes/integrations/cluster-nodes/memory-shared.html" %]]
--8<-- "_glossary/ai-glossary.md"

View File

@ -0,0 +1,25 @@
---
title: HTTP Request
description: Documentation for the HTTP Request node in n8n, a workflow automation platform. Includes details of operations and configuration, and links to examples and credentials information.
contentType: integration
---
# HTTP Request
The HTTP Request tool works just like the [HTTP Request](/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/) node but it allows you to use it with an AI agent as a tool to collect information from a website or API.
On this page, you'll find a list of operations the HTTP Request node supports, and links to more resources.
/// note | Credentials
Refer to [HTTP Request credentials](/integrations/builtin/credentials/httprequest/) for guidance on setting up authentication.
///
--8<-- "_snippets/integrations/builtin/cluster-nodes/sub-node-expression-resolution.md"
## Related resources
--8<-- "_snippets/integrations/builtin/cluster-nodes/tools-link.md"
--8<-- "_snippets/integrations/builtin/cluster-nodes/langchain-overview-link.md"
--8<-- "_glossary/ai-glossary.md"

View File

@ -6,7 +6,7 @@ contentType: integration
# Acuity Scheduling credentials
You can use these credentials to authenticate the following nodes with Acuity Scheduling.
You can use these credentials to authenticate the following nodes:
- [Acuity Scheduling Trigger](/integrations/builtin/trigger-nodes/n8n-nodes-base.acuityschedulingtrigger/)

View File

@ -6,7 +6,7 @@ contentType: integration
# Adalo credentials
You can use these credentials to authenticate the following nodes with Adalo:
You can use these credentials to authenticate the following nodes:
- [Adalo node](/integrations/builtin/app-nodes/n8n-nodes-base.adalo/)

View File

@ -6,7 +6,7 @@ contentType: integration
# Affinity credentials
You can use these credentials to authenticate the following nodes with Affinity.
You can use these credentials to authenticate the following nodes:
- [Affinity](/integrations/builtin/app-nodes/n8n-nodes-base.affinity/)
- [Affinity Trigger](/integrations/builtin/trigger-nodes/n8n-nodes-base.affinitytrigger/)

View File

@ -6,7 +6,7 @@ contentType: integration
# Agile CRM credentials
You can use these credentials to authenticate the following nodes with Agile CRM.
You can use these credentials to authenticate the following nodes:
- [Agile CRM](/integrations/builtin/app-nodes/n8n-nodes-base.agilecrm/)

View File

@ -6,7 +6,7 @@ contentType: integration
# Airtable credentials
You can use these credentials to authenticate the following nodes with Airtable.
You can use these credentials to authenticate the following nodes:
- [Airtable](/integrations/builtin/app-nodes/n8n-nodes-base.airtable/)
- [Airtable Trigger](/integrations/builtin/trigger-nodes/n8n-nodes-base.airtabletrigger/)

View File

@ -5,7 +5,7 @@ description: Documentation for the AlienVault credentials. Use these credentials
# AlienVault credentials
You can use these credentials to authenticate when using the [HTTP Request node](/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/) to make a [Custom API call](/integrations/custom-operations/).
--8<-- "_snippets/integrations/builtin/credentials/cred-only-statement.md"
## Prerequisites

View File

@ -6,18 +6,35 @@ contentType: integration
# AMQP credentials
You can use these credentials to authenticate the following nodes with AMQP.
You can use these credentials to authenticate the following nodes:
- [AMQP Sender](/integrations/builtin/app-nodes/n8n-nodes-base.amqp/)
- [AMQP Trigger](/integrations/builtin/trigger-nodes/n8n-nodes-base.amqptrigger/)
## Prerequisites
You need to have a AMQP 1.0 compatible message broker installed.
Install an AMQP 1.0-compatible message broker like [ActiveMQ](https://activemq.apache.org/){:target=_blank .external-link}. Refer to [AMQP Products](https://www.amqp.org/about/examples){:target=_blank .external-link} for a list of options.
## Using ActiveMQ connection
## Supported authentication methods
Use your Hostname, Port, User, and Password as the AMQP Sender credential data in n8n.
- AMQP connection
**Note:** The default username for ActiveMQ is `admin` and the default password is `admin`.
## Related resources
Advanced Message Queuing Protocol (AMQP) is an open standard application layer protocol for message-oriented middleware. The defining features of AMQP are message orientation, queuing, routing, reliability and security. Refer to the [OASIS AMQP Version 1.0 Standard](http://docs.oasis-open.org/amqp/core/v1.0/amqp-core-overview-v1.0.html){:target=_blank .external-link} for more information.
Refer to your provider's documentation for more information about the service. Refer to [ActiveMQ's API documentation](https://activemq.apache.org/components/classic/documentation/rest){:target=_blank .external-link} as one example.
## Using AMQP connection
To configure this credential, you'll need:
- A **Hostname**: Enter the hostname of your AMQP message broker.
- A **Port**: Enter the port number the connection should use.
- A **User**: Enter the name of the user to establish the connection as.
- For example, the default username in ActiveMQ is `admin`.
- A **Password**: Enter the user's password.
- For example, the default password in ActiveMQ is `admin`.
- _Optional:_ **Transport Type**: Enter either `tcp` or `tls`.
Refer to your provider's documentation for more detailed instructions.

View File

@ -5,7 +5,7 @@ description: Documentation for the Auth0 Management credentials. Use these crede
# Auth0 Management credentials
You can use these credentials to authenticate when using the [HTTP Request node](/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/) to make a [Custom API call](/integrations/custom-operations/).
--8<-- "_snippets/integrations/builtin/credentials/cred-only-statement.md"
## Prerequisites

View File

@ -24,5 +24,7 @@ Refer to [Automizy's API documentation](https://developers.automizy.com/automizy
## Using API token
Create new or access existing API tokens from your [Automizy dashboard](https://app.automizy.com/dashboard){:target=_blank .external-link} by selecting **Settings** > **API Token**.
To configure this credential, you'll need:
- An **API Token**: Create new or access existing API tokens from your [**Automizy dashboard**](https://app.automizy.com/dashboard){:target=_blank .external-link} **> Settings > API Token**.

View File

@ -6,29 +6,30 @@ contentType: integration
# Autopilot credentials
You can use these credentials to authenticate the following nodes with Autopilot.
You can use these credentials to authenticate the following nodes:
- [Autopilot](/integrations/builtin/app-nodes/n8n-nodes-base.autopilot/)
- [Autopilot Trigger](/integrations/builtin/trigger-nodes/n8n-nodes-base.autopilottrigger/)
/// warning | Autopilot branding change
Autopilot has become Ortto. The Autopilot credentials and nodes are only compatible with Autopilot, not the new Ortto API.
///
## Prerequisites
Create an [Autopilot](https://app.autopilothq.com) account.
Create an [Autopilot](https://app.autopilothq.com){:target=_blank .external-link} account.
## Using API Key
## Supported authentication methods
1. Open your Autopilot [dashboard](https://app.autopilothq.com).
2. Click on the gears icon on the left sidebar to open the ***Settings*** menu.
3. Click on ***Autopilot API***.
4. Click on the ***Generate*** button to create the API key.
5. Copy the displayed API key.
6. Enter a name for your credentials in the ***Credentials Name*** field in the 'Autopilot API' credentials in n8n.
7. Paste the API key in the ***API Key*** field in the 'Autopilot API' credentials in n8n.
8. Click on the ***Create*** button to create the credentials.
- API key
The following video demonstrates the steps mentioned above.
## Related resources
<div class="video-container">
<iframe width="840" height="472.5" src="https://www.youtube.com/embed/zy8uVHpwVHM" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
Refer to [Autopilot's API documentation](https://autopilot.docs.apiary.io/#){:target=_blank .external-link} for more information about the service.
## Using API key
To configure this credential, you'll need:
- An **API Key**: Generate an API key in **Settings > Autopilot API**. Refer to [Autopilot API authentication](https://autopilot.docs.apiary.io/#reference/authentication){:target=_blank .external-link} for more information.

View File

@ -6,7 +6,7 @@ contentType: integration
# Bitbucket credentials
You can use these credentials to authenticate the following nodes with Bitbucket.
You can use these credentials to authenticate the following nodes:
- [Bitbucket Trigger](/integrations/builtin/trigger-nodes/n8n-nodes-base.bitbuckettrigger/)

View File

@ -6,7 +6,7 @@ contentType: integration
# Cal credentials
You can use these credentials to authenticate the following nodes with Cal.
You can use these credentials to authenticate the following nodes:
- [Cal Trigger](/integrations/builtin/trigger-nodes/n8n-nodes-base.caltrigger/)

View File

@ -6,7 +6,7 @@ contentType: integration
# Calendly credentials
You can use these credentials to authenticate the following nodes with Calendly.
You can use these credentials to authenticate the following nodes:
- [Calendly Trigger](/integrations/builtin/trigger-nodes/n8n-nodes-base.calendlytrigger/)

View File

@ -5,7 +5,7 @@ description: Documentation for the Carbon Black credentials. Use these credentia
# Carbon Black credentials
You can use these credentials to authenticate when using the [HTTP Request node](/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/) to make a [Custom API call](/integrations/custom-operations/).
--8<-- "_snippets/integrations/builtin/credentials/cred-only-statement.md"
## Prerequisites

View File

@ -6,7 +6,7 @@ contentType: integration
# Chargebee credentials
You can use these credentials to authenticate the following nodes with Chargebee.
You can use these credentials to authenticate the following nodes:
- [Chargebee](/integrations/builtin/app-nodes/n8n-nodes-base.chargebee/)
- [Chargebee Trigger](/integrations/builtin/trigger-nodes/n8n-nodes-base.chargebeetrigger/)

View File

@ -6,7 +6,7 @@ contentType: integration
# CircleCI credentials
You can use these credentials to authenticate the following nodes with CircleCI.
You can use these credentials to authenticate the following nodes:
- [CircleCI](/integrations/builtin/app-nodes/n8n-nodes-base.circleci/)

View File

@ -5,7 +5,7 @@ description: Documentation for the Cisco Meraki credentials. Use these credentia
# Cisco Meraki credentials
You can use these credentials to authenticate when using the [HTTP Request node](/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/) to make a [Custom API call](/integrations/custom-operations/).
--8<-- "_snippets/integrations/builtin/credentials/cred-only-statement.md"
## Prerequisites

View File

@ -5,7 +5,7 @@ description: Documentation for the Cisco Secure Endpoint credentials. Use these
# Cisco Secure Endpoint credentials
You can use these credentials to authenticate when using the [HTTP Request node](/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/) to make a [Custom API call](/integrations/custom-operations/).
--8<-- "_snippets/integrations/builtin/credentials/cred-only-statement.md"
## Prerequisites

Some files were not shown because too many files have changed in this diff Show More