n8n/packages/@n8n/nodes-langchain/utils/agent-execution/executeEngineAction.ts
Arvin A e9920b62d5
fix(langchain agent Node): Resolve sub-agent tool calls inline when nested (#31072)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 13:38:52 +00:00

61 lines
1.8 KiB
TypeScript

import type { DynamicStructuredTool, Tool } from '@langchain/classic/tools';
import omit from 'lodash/omit';
import type { EngineRequest, ExecuteNodeResult, IDataObject, INode, ITaskData } from 'n8n-workflow';
import { NodeOperationError } from 'n8n-workflow';
import type { RequestResponseMetadata } from './types';
type ConnectedTool = DynamicStructuredTool | Tool;
type Action = EngineRequest<RequestResponseMetadata>['actions'][number];
const EMPTY_TASK_DATA_SHELL: Pick<
ITaskData,
'executionTime' | 'startTime' | 'executionIndex' | 'source'
> = { executionTime: 0, startTime: 0, executionIndex: 0, source: [] };
/** Inverse of createEngineRequests: invokes a tool for one action, returns the ActionResponse the agent loop expects. */
export async function executeEngineAction(
node: INode,
action: Action,
tools: ConnectedTool[],
): Promise<ExecuteNodeResult<RequestResponseMetadata>> {
const tool = tools.find((t) => t.name === action.metadata?.toolName);
if (!tool) {
return errorResult(
node,
action,
`Sub-agent could not find a connected tool for node "${action.nodeName}".`,
);
}
try {
// `input.tool` is a toolkit-dispatch marker added by createEngineRequests; strip before invoking.
const output = await tool.invoke(omit(action.input, 'tool'));
return {
action,
data: {
...EMPTY_TASK_DATA_SHELL,
executionStatus: 'success',
data: { ai_tool: [[{ json: { output } as IDataObject }]] },
},
};
} catch (error) {
return errorResult(node, action, error instanceof Error ? error.message : String(error));
}
}
function errorResult(
node: INode,
action: Action,
message: string,
): ExecuteNodeResult<RequestResponseMetadata> {
return {
action,
data: {
...EMPTY_TASK_DATA_SHELL,
executionStatus: 'error',
error: new NodeOperationError(node, message),
},
};
}