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:
Abdul Rahman
2025-07-18 20:17:19 +05:30
committed by GitHub
parent 45655a39b0
commit dd24fbe4ee
20 changed files with 259 additions and 113 deletions

View File

@ -63,13 +63,14 @@ describe('AgentToolService Integration', () => {
);
expect(tools).toBeDefined();
expect(Object.keys(tools)).toHaveLength(6);
expect(Object.keys(tools)).toHaveLength(7);
expect(Object.keys(tools)).toContain('create_testObject');
expect(Object.keys(tools)).toContain('update_testObject');
expect(Object.keys(tools)).toContain('find_testObject');
expect(Object.keys(tools)).toContain('find_one_testObject');
expect(Object.keys(tools)).toContain('soft_delete_testObject');
expect(Object.keys(tools)).toContain('soft_delete_many_testObject');
expect(Object.keys(tools)).toContain('http_request');
});
it('should generate read-only tools for agent with read permissions only', async () => {
@ -108,14 +109,14 @@ describe('AgentToolService Integration', () => {
);
expect(tools).toBeDefined();
expect(Object.keys(tools)).toHaveLength(2);
expect(Object.keys(tools)).toHaveLength(3);
expect(Object.keys(tools)).toContain('find_testObject');
expect(Object.keys(tools)).toContain('find_one_testObject');
expect(Object.keys(tools)).not.toContain('create_testObject');
expect(Object.keys(tools)).not.toContain('update_testObject');
});
it('should return empty tools for agent without role', async () => {
it('should return only http request tool for agent without role', async () => {
const agentWithoutRole = { ...context.testAgent, roleId: null };
jest
@ -127,7 +128,8 @@ describe('AgentToolService Integration', () => {
context.testWorkspaceId,
);
expect(tools).toEqual({});
expect(Object.keys(tools)).toHaveLength(1);
expect(Object.keys(tools)).toContain('http_request');
});
it('should return empty tools when role does not exist', async () => {
@ -185,7 +187,7 @@ describe('AgentToolService Integration', () => {
context.testWorkspaceId,
);
expect(tools).toEqual({});
expect(Object.keys(tools)).toHaveLength(1);
});
});
@ -801,7 +803,7 @@ describe('AgentToolService Integration', () => {
);
expect(tools).toBeDefined();
expect(Object.keys(tools)).toHaveLength(8);
expect(Object.keys(tools)).toHaveLength(9);
expect(Object.keys(tools)).toContain('create_testObject');
expect(Object.keys(tools)).toContain('update_testObject');
expect(Object.keys(tools)).toContain('find_testObject');

View File

@ -3,6 +3,7 @@ import { getRepositoryToken } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { ToolAdapterService } from 'src/engine/core-modules/ai/services/tool-adapter.service';
import { ToolService } from 'src/engine/core-modules/ai/services/tool.service';
import { AgentToolService } from 'src/engine/metadata-modules/agent/agent-tool.service';
import { AgentEntity } from 'src/engine/metadata-modules/agent/agent.entity';
@ -73,6 +74,10 @@ export const createAgentToolTestModule =
provide: ToolService,
useClass: ToolService,
},
{
provide: ToolAdapterService,
useClass: ToolAdapterService,
},
],
}).compile();