This workflow follows the Agent → Airtabletool recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Log Agent Outputs",
"nodes": [
{
"parameters": {
"model": "openai/gpt-4.1-mini",
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
"typeVersion": 1,
"position": [
40,
240
],
"id": "d94afe23-8e36-4624-9e89-aa152b29f328",
"name": "4.1-mini",
"credentials": {
"openRouterApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"sendTo": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('To', ``, 'string') }}",
"subject": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Subject', ``, 'string') }}",
"message": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Message', ``, 'string') }}",
"options": {
"appendAttribution": true
}
},
"type": "n8n-nodes-base.gmailTool",
"typeVersion": 2.1,
"position": [
220,
240
],
"id": "a7572331-dc94-4b31-9310-03b82e9be783",
"name": "Send Email",
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "search",
"base": {
"__rl": true,
"value": "appK0rbtvf9e7vt6w",
"mode": "list",
"cachedResultName": "Contacts",
"cachedResultUrl": "https://airtable.com/appK0rbtvf9e7vt6w"
},
"table": {
"__rl": true,
"value": "tbl08JGCfUK1RhXsG",
"mode": "list",
"cachedResultName": "Contacts",
"cachedResultUrl": "https://airtable.com/appK0rbtvf9e7vt6w/tbl08JGCfUK1RhXsG"
},
"options": {}
},
"type": "n8n-nodes-base.airtableTool",
"typeVersion": 2.1,
"position": [
320,
240
],
"id": "74f29af7-905a-490c-bb2a-fcc96c2af060",
"name": "Get Contacts",
"credentials": {
"airtableTokenApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "append",
"documentId": {
"__rl": true,
"value": "144h5vN3d_SsZMNkZncQAKMrwJ3wkceUEq47dO7FwLyA",
"mode": "list",
"cachedResultName": "Agent Logs",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/144h5vN3d_SsZMNkZncQAKMrwJ3wkceUEq47dO7FwLyA/edit?usp=drivesdk"
},
"sheetName": {
"__rl": true,
"value": "gid=0",
"mode": "list",
"cachedResultName": "Sheet1",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/144h5vN3d_SsZMNkZncQAKMrwJ3wkceUEq47dO7FwLyA/edit#gid=0"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"Timestamp": "={{ $now.format('D hh:mm a') }}",
"Workflow": "={{ $workflow.name }}",
"Input": "={{ $('Telegram Trigger').item.json.message.text }}",
"Output": "={{ $('AI Agent').item.json.output }}",
"Actions": "={{ JSON.stringify($json.steps, null, 2) }}",
"Tokens": "={{ JSON.stringify($json.tokens, null, 2) }}",
"Total Cost": "={{ $json.total_cost }}"
},
"matchingColumns": [],
"schema": [
{
"id": "Timestamp",
"displayName": "Timestamp",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Workflow",
"displayName": "Workflow",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Input",
"displayName": "Input",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Output",
"displayName": "Output",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Error Message",
"displayName": "Error Message",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": true
},
{
"id": "Actions",
"displayName": "Actions",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Tokens",
"displayName": "Tokens",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "Total Cost",
"displayName": "Total Cost",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
760,
-20
],
"id": "e86e0eff-a2aa-45b7-a666-ac4fee4de3e0",
"name": "Log",
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"calendar": {
"__rl": true,
"value": "nateherk88@gmail.com",
"mode": "list",
"cachedResultName": "nateherk88@gmail.com"
},
"start": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Start', ``, 'string') }}",
"end": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('End', ``, 'string') }}",
"additionalFields": {
"summary": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Summary', ``, 'string') }}"
}
},
"type": "n8n-nodes-base.googleCalendarTool",
"typeVersion": 1.3,
"position": [
420,
240
],
"id": "50448561-db40-43ee-bf28-b6d328ed4cfa",
"name": "Create Event",
"credentials": {
"googleCalendarOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "// Initialize the output arrays\nconst steps = [];\nconst tokens = [];\nlet totalCost = 0; // Add this to track the total cost\n\n// Process each item in the input\nfor (const item of $input.all()) {\n let data = item.json;\n \n // Check if the data is an array itself (like your example JSON)\n if (Array.isArray(data)) {\n // Process each object in the array\n for (const obj of data) {\n // Extract steps information\n if (obj.intermediateSteps && Array.isArray(obj.intermediateSteps)) {\n for (const step of obj.intermediateSteps) {\n if (step.action) {\n steps.push({\n tool: step.action.tool,\n toolInput: step.action.toolInput,\n observation: step.observation\n });\n }\n }\n }\n \n // Extract token and cost information\n if (obj.intermediateSteps && Array.isArray(obj.intermediateSteps)) {\n for (const step of obj.intermediateSteps) {\n if (step.action && step.action.messageLog && Array.isArray(step.action.messageLog)) {\n for (const message of step.action.messageLog) {\n if (message.kwargs && message.kwargs.response_metadata && message.kwargs.response_metadata.usage) {\n const usage = message.kwargs.response_metadata.usage;\n tokens.push({\n prompt_tokens: usage.prompt_tokens,\n completion_tokens: usage.completion_tokens,\n total_tokens: usage.total_tokens,\n cost: usage.cost,\n model_name: message.kwargs.response_metadata.model_name\n });\n \n // Add the cost to our running total\n if (typeof usage.cost === 'number') {\n totalCost += usage.cost;\n }\n }\n }\n }\n }\n }\n }\n } else {\n // If data is not an array, process it as a single object\n // Extract steps information\n if (data.intermediateSteps && Array.isArray(data.intermediateSteps)) {\n for (const step of data.intermediateSteps) {\n if (step.action) {\n steps.push({\n tool: step.action.tool,\n toolInput: step.action.toolInput,\n observation: step.observation\n });\n }\n }\n }\n \n // Extract token and cost information\n if (data.intermediateSteps && Array.isArray(data.intermediateSteps)) {\n for (const step of data.intermediateSteps) {\n if (step.action && step.action.messageLog && Array.isArray(step.action.messageLog)) {\n for (const message of step.action.messageLog) {\n if (message.kwargs && message.kwargs.response_metadata && message.kwargs.response_metadata.usage) {\n const usage = message.kwargs.response_metadata.usage;\n tokens.push({\n prompt_tokens: usage.prompt_tokens,\n completion_tokens: usage.completion_tokens,\n total_tokens: usage.total_tokens,\n cost: usage.cost,\n model_name: message.kwargs.response_metadata.model_name\n });\n \n // Add the cost to our running total\n if (typeof usage.cost === 'number') {\n totalCost += usage.cost;\n }\n }\n }\n }\n }\n }\n }\n}\n\n// Return the processed data with total_cost included\nreturn [{\n json: {\n steps: steps,\n tokens: tokens,\n total_cost: totalCost\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
620,
-20
],
"id": "00ac40ff-ea45-463f-b5bd-2b337486fba8",
"name": "Clean Up"
},
{
"parameters": {
"operation": "append",
"documentId": {
"__rl": true,
"value": "144h5vN3d_SsZMNkZncQAKMrwJ3wkceUEq47dO7FwLyA",
"mode": "list",
"cachedResultName": "Agent Logs",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/144h5vN3d_SsZMNkZncQAKMrwJ3wkceUEq47dO7FwLyA/edit?usp=drivesdk"
},
"sheetName": {
"__rl": true,
"value": "gid=0",
"mode": "list",
"cachedResultName": "Sheet1",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/144h5vN3d_SsZMNkZncQAKMrwJ3wkceUEq47dO7FwLyA/edit#gid=0"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"Timestamp": "={{ $now.format('D hh:mm a') }}",
"Workflow": "={{ $workflow.name }}",
"Output": "ERROR",
"Input": "={{ $('Telegram Trigger').item.json.message.text }}",
"Total Cost": "={{ $json.total_cost }}",
"Tokens": "={{ JSON.stringify($json.tokens, null, 2) }}",
"Actions": "={{ JSON.stringify($json.steps, null, 2) }}",
"Error Message": "={{ $('AI Agent').item.json.error }}"
},
"matchingColumns": [],
"schema": [
{
"id": "Timestamp",
"displayName": "Timestamp",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Workflow",
"displayName": "Workflow",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Input",
"displayName": "Input",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Output",
"displayName": "Output",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Error Message",
"displayName": "Error Message",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Actions",
"displayName": "Actions",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Tokens",
"displayName": "Tokens",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Total Cost",
"displayName": "Total Cost",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
760,
240
],
"id": "bbc28e22-4148-476b-9307-2b0f73ea417f",
"name": "Errors",
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"updates": [
"message"
],
"additionalFields": {}
},
"type": "n8n-nodes-base.telegramTrigger",
"typeVersion": 1.2,
"position": [
0,
0
],
"id": "31887bf6-10d1-4d2d-a7a8-127c21e4807c",
"name": "Telegram Trigger",
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"chatId": "={{ $('Telegram Trigger').item.json.message.from.id }}",
"text": "=Error: {{ $('AI Agent').item.json.error }}",
"additionalFields": {
"appendAttribution": false
}
},
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
980,
240
],
"id": "02bea6a4-6b4f-42b0-971f-112736d8319a",
"name": "Error Response",
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"chatId": "={{ $('Telegram Trigger').item.json.message.from.id }}",
"text": "={{ $('AI Agent').item.json.output }}",
"additionalFields": {
"appendAttribution": false
}
},
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
980,
-20
],
"id": "89a37553-39ff-4b72-8de0-4165bce7d0eb",
"name": "Response",
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"content": "## Trigger",
"height": 240,
"width": 220,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-60,
-80
],
"id": "d98a8e4b-f93f-4715-a0c1-9ca0ac4aabf1",
"name": "Sticky Note"
},
{
"parameters": {
"content": "## AI Agent\n",
"height": 240,
"width": 340,
"color": 5
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
180,
-80
],
"id": "8383ef01-005e-4d89-9578-2e5ed9cd7fa3",
"name": "Sticky Note1"
},
{
"parameters": {
"content": "## Chat Model",
"height": 200,
"width": 200,
"color": 2
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-20,
180
],
"id": "eac4405a-f4e6-40e1-9871-4c987ef4938e",
"name": "Sticky Note2"
},
{
"parameters": {
"content": "## Tools",
"height": 200,
"width": 320,
"color": 6
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
200,
180
],
"id": "8d3a1500-2b1e-4b0e-b849-2324856841c3",
"name": "Sticky Note3"
},
{
"parameters": {
"content": "## Log Actions & Cost",
"height": 240,
"width": 380,
"color": 4
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
540,
-100
],
"id": "e8ed3e1f-b09d-4ad7-8eba-bf3ea2930994",
"name": "Sticky Note4"
},
{
"parameters": {
"content": "## Log Error Actions & Cost",
"height": 240,
"width": 380,
"color": 3
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
540,
160
],
"id": "8a7a07fc-55a2-4794-8196-f88d34f9f72b",
"name": "Sticky Note5"
},
{
"parameters": {
"jsCode": "// Initialize the output arrays\nconst steps = [];\nconst tokens = [];\nlet totalCost = 0; // Add this to track the total cost\n\n// Process each item in the input\nfor (const item of $input.all()) {\n let data = item.json;\n \n // Check if the data is an array itself (like your example JSON)\n if (Array.isArray(data)) {\n // Process each object in the array\n for (const obj of data) {\n // Extract steps information\n if (obj.intermediateSteps && Array.isArray(obj.intermediateSteps)) {\n for (const step of obj.intermediateSteps) {\n if (step.action) {\n steps.push({\n tool: step.action.tool,\n toolInput: step.action.toolInput,\n observation: step.observation\n });\n }\n }\n }\n \n // Extract token and cost information\n if (obj.intermediateSteps && Array.isArray(obj.intermediateSteps)) {\n for (const step of obj.intermediateSteps) {\n if (step.action && step.action.messageLog && Array.isArray(step.action.messageLog)) {\n for (const message of step.action.messageLog) {\n if (message.kwargs && message.kwargs.response_metadata && message.kwargs.response_metadata.usage) {\n const usage = message.kwargs.response_metadata.usage;\n tokens.push({\n prompt_tokens: usage.prompt_tokens,\n completion_tokens: usage.completion_tokens,\n total_tokens: usage.total_tokens,\n cost: usage.cost,\n model_name: message.kwargs.response_metadata.model_name\n });\n \n // Add the cost to our running total\n if (typeof usage.cost === 'number') {\n totalCost += usage.cost;\n }\n }\n }\n }\n }\n }\n }\n } else {\n // If data is not an array, process it as a single object\n // Extract steps information\n if (data.intermediateSteps && Array.isArray(data.intermediateSteps)) {\n for (const step of data.intermediateSteps) {\n if (step.action) {\n steps.push({\n tool: step.action.tool,\n toolInput: step.action.toolInput,\n observation: step.observation\n });\n }\n }\n }\n \n // Extract token and cost information\n if (data.intermediateSteps && Array.isArray(data.intermediateSteps)) {\n for (const step of data.intermediateSteps) {\n if (step.action && step.action.messageLog && Array.isArray(step.action.messageLog)) {\n for (const message of step.action.messageLog) {\n if (message.kwargs && message.kwargs.response_metadata && message.kwargs.response_metadata.usage) {\n const usage = message.kwargs.response_metadata.usage;\n tokens.push({\n prompt_tokens: usage.prompt_tokens,\n completion_tokens: usage.completion_tokens,\n total_tokens: usage.total_tokens,\n cost: usage.cost,\n model_name: message.kwargs.response_metadata.model_name\n });\n \n // Add the cost to our running total\n if (typeof usage.cost === 'number') {\n totalCost += usage.cost;\n }\n }\n }\n }\n }\n }\n }\n}\n\n// Return the processed data with total_cost included\nreturn [{\n json: {\n steps: steps,\n tokens: tokens,\n total_cost: totalCost\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
620,
240
],
"id": "e4300814-01f2-4c98-b1bb-51ddf49b8405",
"name": "Clean_Up"
},
{
"parameters": {
"content": "## Reponse",
"height": 240,
"width": 200,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
940,
-100
],
"id": "6b02e42b-f9e6-4bce-97a3-08a027bf6e58",
"name": "Sticky Note6"
},
{
"parameters": {
"content": "## Reponse",
"height": 240,
"width": 200,
"color": 7
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
940,
160
],
"id": "af52b476-dc6f-44bf-b6a2-e7cf82f0c058",
"name": "Sticky Note7"
},
{
"parameters": {
"promptType": "define",
"text": "={{ $json.message.text }}",
"options": {
"returnIntermediateSteps": true
}
},
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 1.9,
"position": [
220,
0
],
"id": "a3d81b58-528b-4bfc-b0f0-416db8303eb8",
"name": "AI Agent",
"onError": "continueErrorOutput"
},
{
"parameters": {
"content": "# \ud83d\udee0\ufe0f Setup Guide \n**Author:** [Nate Herk](https://www.youtube.com/@nateherk)\n\nTo get this workflow up and running, follow these steps:\n\n1. **Connect your [OpenRouter API key](https://openrouter.ai/)** \n Make sure you\u2019ve added it under Credentials in n8n.\n\n2. **Connect your Telegram account** \n Set up your Telegram Bot credentials and ensure it's authorized.\n\n3. **Connect any tool credentials** \n Link the tools you want this workflow to interact with \u2014 this may include CRMs, email platforms, etc.\n\n4. **Connect the Google Sheet template** \n Use [this template](https://docs.google.com/spreadsheets/d/1ImjPm2JF-uhxa9ZZ12yO3Pq7q9PakYobrdAk57c9z8c/edit?usp=sharing) and link it to the Google Sheets node in your workflow.\n\nOnce all connections are set up, you're good to go!\n",
"height": 540,
"width": 520
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-600,
-80
],
"id": "173a7f5e-1dd2-41c8-8d57-1fdf12158d91",
"name": "Sticky Note8"
}
],
"connections": {
"4.1-mini": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Send Email": {
"ai_tool": [
[
{
"node": "AI Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Get Contacts": {
"ai_tool": [
[
{
"node": "AI Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Create Event": {
"ai_tool": [
[
{
"node": "AI Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Clean Up": {
"main": [
[
{
"node": "Log",
"type": "main",
"index": 0
}
]
]
},
"Telegram Trigger": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"Errors": {
"main": [
[
{
"node": "Error Response",
"type": "main",
"index": 0
}
]
]
},
"Log": {
"main": [
[
{
"node": "Response",
"type": "main",
"index": 0
}
]
]
},
"Clean_Up": {
"main": [
[
{
"node": "Errors",
"type": "main",
"index": 0
}
]
]
},
"AI Agent": {
"main": [
[
{
"node": "Clean Up",
"type": "main",
"index": 0
}
],
[
{
"node": "Clean_Up",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "af9b7b0b-241b-4183-9987-c7ede3190c73",
"meta": {
"templateCredsSetupCompleted": true
},
"id": "iTVv4EMeEzvP6ODO",
"tags": []
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
airtableTokenApigmailOAuth2googleCalendarOAuth2ApigoogleSheetsOAuth2ApiopenRouterApitelegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
How this works
This workflow captures and organises outputs from AI agents into structured logs, saving you hours of manual tracking and ensuring critical insights from conversations or tasks are never lost. It's ideal for teams using AI tools like lmChatOpenRouter for customer support, research, or automation, where you need to review agent interactions alongside related actions such as sending emails via Gmail or updating records in Airtable. The key step involves the AI node processing inputs to generate responses, followed by a logging mechanism that appends details to Google Sheets for easy analysis and auditing.
Use this workflow when your AI agents handle dynamic tasks like querying databases or scheduling events, and you require a reliable audit trail integrated with tools like Google Calendar. Avoid it for simple, one-off AI queries without ongoing logging needs, or if your volume is too low to justify the 21-node setup. Common variations include adding Slack notifications for real-time alerts or customising the cleanup code node to filter logs by priority.
About this workflow
Log Agent Outputs. Uses lmChatOpenRouter, gmailTool, airtableTool, googleSheets. Event-driven trigger; 21 nodes.
Source: https://github.com/Zie619/n8n-workflows — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Telegram Trigger receives incoming messages (text, voice, photo, document). Switch routes by message type to appropriate processors: Text → forwarded as-is. Voice → downloaded and sent to Transcribe a
Transform your Telegram messenger into a powerful, multi-modal personal or team assistant. This n8n workflow creates an intelligent agent that can understand text, voice, images, and documents, and ta
Personal Assistant. Uses memoryBufferWindow, agent, agentTool, httpRequestTool. Event-driven trigger; 77 nodes.
Inbox Guardian. Uses gmailTrigger, lmChatOpenAi, agent, textClassifier. Event-driven trigger; 66 nodes.
Multi Agent System Benefits. Uses gmailTool, lmChatOpenAi, agent, googleCalendarTool. Event-driven trigger; 46 nodes.