Decouple http node from workflows (#13272)
- Added a generic HTTP request tool, allowing agents and workflows to make HTTP requests to external APIs with configurable method, headers, and body. - Decoupled HTTP request workflow nodes from workflow-specific types and factories, introducing a generic tool interface. - Updated agent system prompts to include explicit guidance for the HTTP request tool, including when and how to use it, and how to communicate limitations. ### Demo https://github.com/user-attachments/assets/129bc445-a277-4a19-95ab-09f890f8f051
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
import { ToolType } from 'src/engine/core-modules/tool/enums/tool-type.enum';
|
||||
import { HttpTool } from 'src/engine/core-modules/tool/tools/http-tool/http-tool';
|
||||
import { Tool } from 'src/engine/core-modules/tool/types/tool.type';
|
||||
|
||||
export const TOOLS: Map<ToolType, Tool> = new Map([
|
||||
[ToolType.HTTP_REQUEST, new HttpTool()],
|
||||
]);
|
||||
@@ -0,0 +1,3 @@
|
||||
export enum ToolType {
|
||||
HTTP_REQUEST = 'HTTP_REQUEST',
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const HttpRequestInputZodSchema = z.object({
|
||||
url: z.string().describe('The URL to make the request to'),
|
||||
method: z
|
||||
.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE'])
|
||||
.describe('The HTTP method to use'),
|
||||
headers: z
|
||||
.record(z.string())
|
||||
.optional()
|
||||
.describe('HTTP headers to include in the request'),
|
||||
body: z
|
||||
.any()
|
||||
.optional()
|
||||
.describe('Request body for POST, PUT, PATCH requests'),
|
||||
});
|
||||
|
||||
export const HttpToolParametersZodSchema = z.object({
|
||||
toolDescription: z
|
||||
.string()
|
||||
.describe(
|
||||
"A clear, human-readable status message describing the HTTP request being made. This will be shown to the user while the tool is being called, so phrase it as a present-tense status update (e.g., 'Making a GET request to ...'). Explain what endpoint you are calling and with what parameters in natural language.",
|
||||
),
|
||||
input: HttpRequestInputZodSchema,
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import axios, { AxiosRequestConfig } from 'axios';
|
||||
|
||||
import { HttpToolParametersZodSchema } from 'src/engine/core-modules/tool/tools/http-tool/http-tool.schema';
|
||||
import { HttpRequestInput } from 'src/engine/core-modules/tool/tools/http-tool/types/http-request-input.type';
|
||||
import { ToolInput } from 'src/engine/core-modules/tool/types/tool-input.type';
|
||||
import { ToolOutput } from 'src/engine/core-modules/tool/types/tool-output.type';
|
||||
import { Tool } from 'src/engine/core-modules/tool/types/tool.type';
|
||||
|
||||
@Injectable()
|
||||
export class HttpTool implements Tool {
|
||||
description =
|
||||
'Make an HTTP request to any URL with configurable method, headers, and body.';
|
||||
parameters = HttpToolParametersZodSchema;
|
||||
|
||||
async execute(parameters: ToolInput): Promise<ToolOutput> {
|
||||
const { url, method, headers, body } = parameters as HttpRequestInput;
|
||||
|
||||
try {
|
||||
const axiosConfig: AxiosRequestConfig = {
|
||||
url,
|
||||
method: method,
|
||||
headers,
|
||||
};
|
||||
|
||||
if (['POST', 'PUT', 'PATCH'].includes(method) && body) {
|
||||
axiosConfig.data = body;
|
||||
}
|
||||
|
||||
const response = await axios(axiosConfig);
|
||||
|
||||
return { result: response.data };
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
return {
|
||||
error: error.response?.data || error.message || 'HTTP request failed',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
error: error instanceof Error ? error.message : 'HTTP request failed',
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { HttpRequestInputZodSchema } from 'src/engine/core-modules/tool/tools/http-tool/http-tool.schema';
|
||||
|
||||
export type HttpRequestInput = z.infer<typeof HttpRequestInputZodSchema>;
|
||||
@@ -0,0 +1,6 @@
|
||||
export type ToolContext = {
|
||||
workspaceId: string;
|
||||
userId?: string;
|
||||
roleId?: string;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export type ToolInput = Record<string, unknown>;
|
||||
@@ -0,0 +1,4 @@
|
||||
export type ToolOutput = {
|
||||
result?: unknown;
|
||||
error?: string;
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
import { JSONSchema7 } from 'json-schema';
|
||||
import { ZodType } from 'zod';
|
||||
|
||||
import { ToolInput } from 'src/engine/core-modules/tool/types/tool-input.type';
|
||||
import { ToolOutput } from 'src/engine/core-modules/tool/types/tool-output.type';
|
||||
|
||||
export type Tool = {
|
||||
description: string;
|
||||
parameters: JSONSchema7 | ZodType;
|
||||
execute(input: ToolInput): Promise<ToolOutput>;
|
||||
};
|
||||
Reference in New Issue
Block a user