fix(AI Agent Node): Fix tool calling when tools run in a loop (#15250)

Co-authored-by: JP van Oosten <jp@n8n.io>
Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ <aditya@netroy.in>
This commit is contained in:
Yiorgis Gozadinos
2025-05-13 14:40:07 +02:00
committed by GitHub
parent 52f27a76ac
commit cd1d6c9dfc
8 changed files with 113 additions and 15 deletions

View File

@@ -39,6 +39,7 @@ export class ToolWorkflowV2 implements INodeType {
const description = this.getNodeParameter('description', itemIndex) as string;
const tool = await workflowToolService.createTool({
ctx: this,
name,
description,
itemIndex,

View File

@@ -13,6 +13,10 @@ import { WorkflowToolService } from './utils/WorkflowToolService';
// Mock ISupplyDataFunctions interface
function createMockContext(overrides?: Partial<ISupplyDataFunctions>): ISupplyDataFunctions {
let runIndex = 0;
const getNextRunIndex = jest.fn(() => {
return runIndex++;
});
return {
runIndex: 0,
getNodeParameter: jest.fn(),
@@ -26,6 +30,7 @@ function createMockContext(overrides?: Partial<ISupplyDataFunctions>): ISupplyDa
getInputData: jest.fn(),
getMode: jest.fn(),
getRestApiUrl: jest.fn(),
getNextRunIndex,
getTimezone: jest.fn(),
getWorkflow: jest.fn(),
getWorkflowStaticData: jest.fn(),
@@ -56,6 +61,7 @@ describe('WorkflowTool::WorkflowToolService', () => {
describe('createTool', () => {
it('should create a basic dynamic tool when schema is not used', async () => {
const toolParams = {
ctx: context,
name: 'TestTool',
description: 'Test Description',
itemIndex: 0,
@@ -70,6 +76,7 @@ describe('WorkflowTool::WorkflowToolService', () => {
it('should create a tool that can handle successful execution', async () => {
const toolParams = {
ctx: context,
name: 'TestTool',
description: 'Test Description',
itemIndex: 0,
@@ -112,6 +119,7 @@ describe('WorkflowTool::WorkflowToolService', () => {
it('should handle errors during tool execution', async () => {
const toolParams = {
ctx: context,
name: 'TestTool',
description: 'Test Description',
itemIndex: 0,

View File

@@ -60,17 +60,21 @@ export class WorkflowToolService {
// Creates the tool based on the provided parameters
async createTool({
ctx,
name,
description,
itemIndex,
}: {
ctx: ISupplyDataFunctions;
name: string;
description: string;
itemIndex: number;
}): Promise<DynamicTool | DynamicStructuredTool> {
let runIndex = 0;
// Handler for the tool execution, will be called when the tool is executed
// This function will execute the sub-workflow and return the response
// We get the runIndex from the context to handle multiple executions
// of the same tool when the tool is used in a loop or in a parallel execution.
let runIndex: number = ctx.getNextRunIndex();
const toolHandler = async (
query: string | IDataObject,
runManager?: CallbackManagerForToolRun,