mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 10:02:05 +00:00
feat(core): Expose $agentInfo variable for easy AI workflow (no-changelog) (#14445)
Co-authored-by: Mutasem Aldmour <mutasem@n8n.io>
This commit is contained in:
@@ -6,29 +6,30 @@ import * as jmespath from 'jmespath';
|
|||||||
import { DateTime, Duration, Interval, Settings } from 'luxon';
|
import { DateTime, Duration, Interval, Settings } from 'luxon';
|
||||||
|
|
||||||
import { augmentArray, augmentObject } from './AugmentObject';
|
import { augmentArray, augmentObject } from './AugmentObject';
|
||||||
import { SCRIPTING_NODE_TYPES } from './Constants';
|
import { AGENT_LANGCHAIN_NODE_TYPE, SCRIPTING_NODE_TYPES } from './Constants';
|
||||||
import { ApplicationError } from './errors/application.error';
|
import { ApplicationError } from './errors/application.error';
|
||||||
import { ExpressionError, type ExpressionErrorOptions } from './errors/expression.error';
|
import { ExpressionError, type ExpressionErrorOptions } from './errors/expression.error';
|
||||||
import { getGlobalState } from './GlobalState';
|
import { getGlobalState } from './GlobalState';
|
||||||
import {
|
import { NodeConnectionTypes } from './Interfaces';
|
||||||
type IDataObject,
|
import type {
|
||||||
type IExecuteData,
|
IDataObject,
|
||||||
type INodeExecutionData,
|
IExecuteData,
|
||||||
type INodeParameters,
|
INodeExecutionData,
|
||||||
type IPairedItemData,
|
INodeParameters,
|
||||||
type IRunExecutionData,
|
IPairedItemData,
|
||||||
type ISourceData,
|
IRunExecutionData,
|
||||||
type ITaskData,
|
ISourceData,
|
||||||
type IWorkflowDataProxyAdditionalKeys,
|
ITaskData,
|
||||||
type IWorkflowDataProxyData,
|
IWorkflowDataProxyAdditionalKeys,
|
||||||
type INodeParameterResourceLocator,
|
IWorkflowDataProxyData,
|
||||||
type NodeParameterValueType,
|
INodeParameterResourceLocator,
|
||||||
type WorkflowExecuteMode,
|
NodeParameterValueType,
|
||||||
type ProxyInput,
|
WorkflowExecuteMode,
|
||||||
NodeConnectionTypes,
|
ProxyInput,
|
||||||
|
INode,
|
||||||
} from './Interfaces';
|
} from './Interfaces';
|
||||||
import * as NodeHelpers from './NodeHelpers';
|
import * as NodeHelpers from './NodeHelpers';
|
||||||
import { deepCopy } from './utils';
|
import { deepCopy, isObjectEmpty } from './utils';
|
||||||
import type { Workflow } from './Workflow';
|
import type { Workflow } from './Workflow';
|
||||||
import type { EnvProviderState } from './WorkflowDataProxyEnvProvider';
|
import type { EnvProviderState } from './WorkflowDataProxyEnvProvider';
|
||||||
import { createEnvProvider, createEnvProviderState } from './WorkflowDataProxyEnvProvider';
|
import { createEnvProvider, createEnvProviderState } from './WorkflowDataProxyEnvProvider';
|
||||||
@@ -159,6 +160,89 @@ export class WorkflowDataProxy {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private buildAgentToolInfo(node: INode) {
|
||||||
|
const nodeType = this.workflow.nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
|
||||||
|
const type = nodeType.description.displayName;
|
||||||
|
const params = NodeHelpers.getNodeParameters(
|
||||||
|
nodeType.description.properties,
|
||||||
|
node.parameters,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
node,
|
||||||
|
nodeType.description,
|
||||||
|
);
|
||||||
|
const resourceKey = params?.resource;
|
||||||
|
const operationKey = params?.operation;
|
||||||
|
|
||||||
|
const resource =
|
||||||
|
nodeType.description.properties
|
||||||
|
.find((nodeProperties) => nodeProperties.name === 'resource')
|
||||||
|
?.options?.find((option) => 'value' in option && option.value === resourceKey)?.name ??
|
||||||
|
null;
|
||||||
|
|
||||||
|
const operation =
|
||||||
|
nodeType.description.properties
|
||||||
|
.find(
|
||||||
|
(nodeProperty) =>
|
||||||
|
nodeProperty.name === 'operation' &&
|
||||||
|
nodeProperty.displayOptions?.show?.resource?.some((y) => y === resourceKey),
|
||||||
|
)
|
||||||
|
?.options?.find((y) => 'value' in y && y.value === operationKey)?.name ?? null;
|
||||||
|
|
||||||
|
const hasCredentials = !isObjectEmpty(node.credentials ?? {});
|
||||||
|
|
||||||
|
const hasValidCalendar = nodeType.description.name.includes('googleCalendar')
|
||||||
|
? isResourceLocatorValue(node.parameters.calendar) && node.parameters.calendar.value !== ''
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
const aiDefinedFields = Object.entries(node.parameters)
|
||||||
|
.map(([key, value]) => [key, isResourceLocatorValue(value) ? value.value : value] as const)
|
||||||
|
.filter(([_, value]) => value?.toString().toLowerCase().includes('$fromai'))
|
||||||
|
.map(
|
||||||
|
([key]) =>
|
||||||
|
nodeType.description.properties.find((property) => property.name === key)?.displayName,
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: node.name,
|
||||||
|
type,
|
||||||
|
resource,
|
||||||
|
operation,
|
||||||
|
hasCredentials,
|
||||||
|
hasValidCalendar,
|
||||||
|
aiDefinedFields,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private agentInfo() {
|
||||||
|
const agentNode = this.workflow.getNode(this.activeNodeName);
|
||||||
|
if (!agentNode || agentNode.type !== AGENT_LANGCHAIN_NODE_TYPE) return undefined;
|
||||||
|
const connectedTools = this.workflow
|
||||||
|
.getParentNodes(this.activeNodeName, NodeConnectionTypes.AiTool)
|
||||||
|
.map((nodeName) => this.workflow.getNode(nodeName))
|
||||||
|
.filter((node) => node) as INode[];
|
||||||
|
const memoryConnectedToAgent =
|
||||||
|
this.workflow.getParentNodes(this.activeNodeName, NodeConnectionTypes.AiMemory).length > 0;
|
||||||
|
const allTools = this.workflow.queryNodes((nodeType) => {
|
||||||
|
return nodeType.description.name.toLowerCase().includes('tool');
|
||||||
|
});
|
||||||
|
|
||||||
|
const unconnectedTools = allTools
|
||||||
|
.filter(
|
||||||
|
(node) =>
|
||||||
|
this.workflow.getChildNodes(node.name, NodeConnectionTypes.AiTool, 1).length === 0,
|
||||||
|
)
|
||||||
|
.filter((node) => !connectedTools.includes(node));
|
||||||
|
|
||||||
|
return {
|
||||||
|
memoryConnectedToAgent,
|
||||||
|
tools: [
|
||||||
|
...connectedTools.map((node) => ({ connected: true, ...this.buildAgentToolInfo(node) })),
|
||||||
|
...unconnectedTools.map((node) => ({ connected: false, ...this.buildAgentToolInfo(node) })),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a proxy which allows to query parameter data of a given node
|
* Returns a proxy which allows to query parameter data of a given node
|
||||||
*
|
*
|
||||||
@@ -1394,6 +1478,7 @@ export class WorkflowDataProxy {
|
|||||||
$thisRunIndex: this.runIndex,
|
$thisRunIndex: this.runIndex,
|
||||||
$nodeVersion: that.workflow.getNode(that.activeNodeName)?.typeVersion,
|
$nodeVersion: that.workflow.getNode(that.activeNodeName)?.typeVersion,
|
||||||
$nodeId: that.workflow.getNode(that.activeNodeName)?.id,
|
$nodeId: that.workflow.getNode(that.activeNodeName)?.id,
|
||||||
|
$agentInfo: this.agentInfo(),
|
||||||
$webhookId: that.workflow.getNode(that.activeNodeName)?.webhookId,
|
$webhookId: that.workflow.getNode(that.activeNodeName)?.webhookId,
|
||||||
};
|
};
|
||||||
const throwOnMissingExecutionData = opts?.throwOnMissingExecutionData ?? true;
|
const throwOnMissingExecutionData = opts?.throwOnMissingExecutionData ?? true;
|
||||||
|
|||||||
@@ -828,6 +828,179 @@ const executeWorkflowNode: LoadedClass<INodeType> = {
|
|||||||
sourcePath: '',
|
sourcePath: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const aiAgentNode: LoadedClass<INodeType> = {
|
||||||
|
sourcePath: '',
|
||||||
|
type: {
|
||||||
|
description: {
|
||||||
|
displayName: 'AI Agent',
|
||||||
|
name: '@n8n/n8n-nodes-langchain.agent',
|
||||||
|
icon: 'fa:robot',
|
||||||
|
iconColor: 'black',
|
||||||
|
group: ['transform'],
|
||||||
|
version: [1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8],
|
||||||
|
description: 'Generates an action plan and executes it. Can use external tools.',
|
||||||
|
defaults: {
|
||||||
|
name: 'AI Agent',
|
||||||
|
color: '#404040',
|
||||||
|
},
|
||||||
|
inputs: [
|
||||||
|
NodeConnectionTypes.Main,
|
||||||
|
NodeConnectionTypes.AiLanguageModel,
|
||||||
|
NodeConnectionTypes.AiTool,
|
||||||
|
NodeConnectionTypes.AiMemory,
|
||||||
|
],
|
||||||
|
outputs: [NodeConnectionTypes.Main],
|
||||||
|
properties: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const wikipediaTool: LoadedClass<INodeType> = {
|
||||||
|
sourcePath: '',
|
||||||
|
type: {
|
||||||
|
description: {
|
||||||
|
displayName: 'Wikipedia',
|
||||||
|
name: '@n8n/n8n-nodes-langchain.toolWikipedia',
|
||||||
|
icon: 'file:wikipedia.svg',
|
||||||
|
group: ['transform'],
|
||||||
|
version: 1,
|
||||||
|
description: 'Search in Wikipedia',
|
||||||
|
defaults: {
|
||||||
|
name: 'Wikipedia',
|
||||||
|
},
|
||||||
|
inputs: [],
|
||||||
|
outputs: [NodeConnectionTypes.AiTool],
|
||||||
|
properties: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const calculatorTool: LoadedClass<INodeType> = {
|
||||||
|
sourcePath: '',
|
||||||
|
type: {
|
||||||
|
description: {
|
||||||
|
displayName: 'Calculator',
|
||||||
|
name: '@n8n/n8n-nodes-langchain.toolCalculator',
|
||||||
|
icon: 'fa:calculator',
|
||||||
|
iconColor: 'black',
|
||||||
|
group: ['transform'],
|
||||||
|
version: 1,
|
||||||
|
description: 'Make it easier for AI agents to perform arithmetic',
|
||||||
|
defaults: {
|
||||||
|
name: 'Calculator',
|
||||||
|
},
|
||||||
|
inputs: [],
|
||||||
|
outputs: [NodeConnectionTypes.AiTool],
|
||||||
|
properties: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const googleCalendarTool: LoadedClass<INodeType> = {
|
||||||
|
sourcePath: '',
|
||||||
|
type: {
|
||||||
|
description: {
|
||||||
|
displayName: 'Google Calendar',
|
||||||
|
name: 'n8n-nodes-base.googleCalendarTool',
|
||||||
|
icon: 'file:googleCalendar.svg',
|
||||||
|
group: ['input'],
|
||||||
|
version: [1, 1.1, 1.2, 1.3],
|
||||||
|
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||||
|
description: 'Consume Google Calendar API',
|
||||||
|
defaults: {
|
||||||
|
name: 'Google Calendar',
|
||||||
|
},
|
||||||
|
inputs: [NodeConnectionTypes.Main],
|
||||||
|
outputs: [NodeConnectionTypes.Main],
|
||||||
|
usableAsTool: true,
|
||||||
|
properties: [
|
||||||
|
{ name: 'start', type: 'dateTime', displayName: 'Start', default: '' },
|
||||||
|
{
|
||||||
|
displayName: 'Operation',
|
||||||
|
name: 'operation',
|
||||||
|
type: 'options',
|
||||||
|
noDataExpression: true,
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: ['calendar'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Availability',
|
||||||
|
value: 'availability',
|
||||||
|
description: 'If a time-slot is available in a calendar',
|
||||||
|
action: 'Get availability in a calendar',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: 'availability',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Operation',
|
||||||
|
name: 'operation',
|
||||||
|
type: 'options',
|
||||||
|
noDataExpression: true,
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
resource: ['event'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Create',
|
||||||
|
value: 'create',
|
||||||
|
description: 'Add a event to calendar',
|
||||||
|
action: 'Create an event',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Delete',
|
||||||
|
value: 'delete',
|
||||||
|
description: 'Delete an event',
|
||||||
|
action: 'Delete an event',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Get',
|
||||||
|
value: 'get',
|
||||||
|
description: 'Retrieve an event',
|
||||||
|
action: 'Get an event',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Get Many',
|
||||||
|
value: 'getAll',
|
||||||
|
description: 'Retrieve many events from a calendar',
|
||||||
|
action: 'Get many events',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Update',
|
||||||
|
value: 'update',
|
||||||
|
description: 'Update an event',
|
||||||
|
action: 'Update an event',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: 'create',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Resource',
|
||||||
|
name: 'resource',
|
||||||
|
type: 'options',
|
||||||
|
noDataExpression: true,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Calendar',
|
||||||
|
value: 'calendar',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Event',
|
||||||
|
value: 'event',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: 'event',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export class NodeTypes implements INodeTypes {
|
export class NodeTypes implements INodeTypes {
|
||||||
nodeTypes: INodeTypeData = {
|
nodeTypes: INodeTypeData = {
|
||||||
'n8n-nodes-base.stickyNote': stickyNode,
|
'n8n-nodes-base.stickyNote': stickyNode,
|
||||||
@@ -887,6 +1060,10 @@ export class NodeTypes implements INodeTypes {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
'n8n-nodes-base.manualTrigger': manualTriggerNode,
|
'n8n-nodes-base.manualTrigger': manualTriggerNode,
|
||||||
|
'@n8n/n8n-nodes-langchain.agent': aiAgentNode,
|
||||||
|
'n8n-nodes-base.googleCalendarTool': googleCalendarTool,
|
||||||
|
'@n8n/n8n-nodes-langchain.toolCalculator': calculatorTool,
|
||||||
|
'@n8n/n8n-nodes-langchain.toolWikipedia': wikipediaTool,
|
||||||
};
|
};
|
||||||
|
|
||||||
getByName(nodeType: string): INodeType | IVersionedNodeType {
|
getByName(nodeType: string): INodeType | IVersionedNodeType {
|
||||||
@@ -900,6 +1077,7 @@ export class NodeTypes implements INodeTypes {
|
|||||||
return mock<INodeType>({
|
return mock<INodeType>({
|
||||||
description: {
|
description: {
|
||||||
properties: [],
|
properties: [],
|
||||||
|
name: nodeType,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -787,4 +787,52 @@ describe('WorkflowDataProxy', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('$agentInfo', () => {
|
||||||
|
const fixture = loadFixture('agentInfo');
|
||||||
|
const proxy = getProxyFromFixture(fixture.workflow, fixture.run, 'AI Agent');
|
||||||
|
|
||||||
|
test('$agentInfo should return undefined for non-agent nodes', () => {
|
||||||
|
const nonAgentProxy = getProxyFromFixture(fixture.workflow, fixture.run, 'Calculator');
|
||||||
|
expect(nonAgentProxy.$agentInfo).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('$agentInfo should return memoryConnectedToAgent as true if memory is connected', () => {
|
||||||
|
expect(proxy.$agentInfo.memoryConnectedToAgent).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('$agentInfo should return memoryConnectedToAgent as false if no memory is connected', () => {
|
||||||
|
const noMemoryProxy = getProxyFromFixture(fixture.workflow, fixture.run, 'Another Agent');
|
||||||
|
expect(noMemoryProxy.$agentInfo.memoryConnectedToAgent).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('$agentInfo.tools should include connected tools with correct details', () => {
|
||||||
|
const tools = proxy.$agentInfo.tools;
|
||||||
|
// don't show tool connected to other agent
|
||||||
|
expect(tools.length).toEqual(2);
|
||||||
|
expect(tools[0]).toMatchObject({
|
||||||
|
connected: true,
|
||||||
|
name: 'Google Calendar',
|
||||||
|
type: 'Google Calendar',
|
||||||
|
resource: 'Event',
|
||||||
|
operation: 'Create',
|
||||||
|
hasCredentials: false,
|
||||||
|
});
|
||||||
|
expect(tools[1]).toMatchObject({
|
||||||
|
connected: false,
|
||||||
|
name: 'Calculator',
|
||||||
|
type: 'Calculator',
|
||||||
|
resource: null,
|
||||||
|
operation: null,
|
||||||
|
hasCredentials: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('$agentInfo.tools should correctly identify AI-defined fields', () => {
|
||||||
|
const tools = proxy.$agentInfo.tools;
|
||||||
|
expect(tools[0].name).toBe('Google Calendar');
|
||||||
|
expect(tools[0].aiDefinedFields.length).toBe(1);
|
||||||
|
expect(tools[0].aiDefinedFields).toEqual(['Start']);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
7
packages/workflow/test/fixtures/WorkflowDataProxy/agentInfo_run.json
vendored
Normal file
7
packages/workflow/test/fixtures/WorkflowDataProxy/agentInfo_run.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"resultData": {
|
||||||
|
"runData": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
130
packages/workflow/test/fixtures/WorkflowDataProxy/agentInfo_workflow.json
vendored
Normal file
130
packages/workflow/test/fixtures/WorkflowDataProxy/agentInfo_workflow.json
vendored
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "@n8n/n8n-nodes-langchain.agent",
|
||||||
|
"typeVersion": 1.8,
|
||||||
|
"position": [280, -160],
|
||||||
|
"id": "48d38b5e-d75f-4245-9f6b-c9ab623b1a7a",
|
||||||
|
"name": "AI Agent"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [0, 0],
|
||||||
|
"id": "914a83be-5bd5-46f9-8b39-1456d12f9429",
|
||||||
|
"name": "When clicking ‘Test workflow’"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "@n8n/n8n-nodes-langchain.toolCalculator",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [780, 60],
|
||||||
|
"id": "d939bfce-6fbd-4f13-8ba2-91d605bdb81b",
|
||||||
|
"name": "Calculator"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "@n8n/n8n-nodes-langchain.toolWikipedia",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [680, 500],
|
||||||
|
"id": "efdb00f3-cf60-4c3a-9b18-2523d2fc3177",
|
||||||
|
"name": "Wikipedia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"calendar": {
|
||||||
|
"__rl": true,
|
||||||
|
"mode": "list",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"start": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Start', ``, 'string') }}",
|
||||||
|
"additionalFields": {}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.googleCalendarTool",
|
||||||
|
"typeVersion": 1.3,
|
||||||
|
"position": [440, 60],
|
||||||
|
"id": "a76e6696-1e19-4aa4-b5d4-c43b332c8bc8",
|
||||||
|
"name": "Google Calendar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "@n8n/n8n-nodes-langchain.agent",
|
||||||
|
"typeVersion": 1.8,
|
||||||
|
"position": [280, 280],
|
||||||
|
"id": "18a77a68-10dc-486d-b179-6d787371878c",
|
||||||
|
"name": "Another Agent"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
|
||||||
|
"typeVersion": 1.3,
|
||||||
|
"position": [300, 80],
|
||||||
|
"id": "a0f31ee2-14b1-4ce7-97eb-a070346db0d3",
|
||||||
|
"name": "Simple Memory"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking ‘Test workflow’": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "AI Agent",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"node": "Another Agent",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Calculator": {
|
||||||
|
"ai_tool": [[]]
|
||||||
|
},
|
||||||
|
"Wikipedia": {
|
||||||
|
"ai_tool": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Another Agent",
|
||||||
|
"type": "ai_tool",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Google Calendar": {
|
||||||
|
"ai_tool": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "AI Agent",
|
||||||
|
"type": "ai_tool",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Simple Memory": {
|
||||||
|
"ai_memory": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "AI Agent",
|
||||||
|
"type": "ai_memory",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {},
|
||||||
|
"meta": {
|
||||||
|
"instanceId": "866ca65bee13401b1e2b632cdf2767d28ec3301d61bdb4ceabc832d1fe22a83e"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user