feat: Add AI Agent workflow action node (#12650)

https://github.com/user-attachments/assets/8593e488-cb00-4fd2-b903-5ba5766e0254

---------

Co-authored-by: Antoine Moreaux <moreaux.antoine@gmail.com>
Co-authored-by: martmull <martmull@hotmail.fr>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Baptiste Devessier <baptiste@devessier.fr>
Co-authored-by: Joseph Chiang <josephj6802@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Guillim <guillim@users.noreply.github.com>
Co-authored-by: Raphaël Bosi <71827178+bosiraphael@users.noreply.github.com>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
Co-authored-by: Marie <51697796+ijreilly@users.noreply.github.com>
Co-authored-by: Naifer <161821705+omarNaifer12@users.noreply.github.com>
Co-authored-by: prastoin <paul@twenty.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@twenty.com>
Co-authored-by: Thomas Trompette <thomas.trompette@sfr.fr>
Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
Co-authored-by: Ajay A Adsule <103304466+AjayAdsule@users.noreply.github.com>
Co-authored-by: bosiraphael <raphael.bosi@gmail.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
Co-authored-by: Marty <91310557+real-marty@users.noreply.github.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Paul Rastoin <45004772+prastoin@users.noreply.github.com>
Co-authored-by: Weiko <corentin@twenty.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: nitin <142569587+ehconitin@users.noreply.github.com>
This commit is contained in:
Abdul Rahman
2025-06-23 01:12:04 +05:30
committed by GitHub
parent 22e126869c
commit 65df511179
75 changed files with 2268 additions and 30 deletions

View File

@ -5,6 +5,7 @@ export type Leaf = {
type?: InputSchemaPropertyType;
icon?: string;
label?: string;
description?: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: any;
};
@ -14,6 +15,7 @@ export type Node = {
type?: InputSchemaPropertyType;
icon?: string;
label?: string;
description?: string;
value: OutputSchema;
};

View File

@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
import { AgentModule } from 'src/engine/metadata-modules/agent/agent.module';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module';
import { WorkflowSchemaModule } from 'src/modules/workflow/workflow-builder/workflow-schema/workflow-schema.module';
@ -11,6 +12,7 @@ import { WorkflowRunnerModule } from 'src/modules/workflow/workflow-runner/workf
@Module({
imports: [
AgentModule,
WorkflowSchemaModule,
ServerlessFunctionModule,
WorkflowRunnerModule,

View File

@ -8,6 +8,7 @@ import { v4 } from 'uuid';
import { BASE_TYPESCRIPT_PROJECT_INPUT_SCHEMA } from 'src/engine/core-modules/serverless/drivers/constants/base-typescript-project-input-schema';
import { CreateWorkflowVersionStepInput } from 'src/engine/core-modules/workflow/dtos/create-workflow-version-step-input.dto';
import { WorkflowActionDTO } from 'src/engine/core-modules/workflow/dtos/workflow-step.dto';
import { AgentService } from 'src/engine/metadata-modules/agent/agent.service';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { ServerlessFunctionService } from 'src/engine/metadata-modules/serverless-function/serverless-function.service';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
@ -50,6 +51,7 @@ export class WorkflowVersionStepWorkspaceService {
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
private readonly workflowSchemaWorkspaceService: WorkflowSchemaWorkspaceService,
private readonly serverlessFunctionService: ServerlessFunctionService,
private readonly agentService: AgentService,
@InjectRepository(ObjectMetadataEntity, 'core')
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
private readonly workflowRunWorkspaceService: WorkflowRunWorkspaceService,
@ -350,11 +352,13 @@ export class WorkflowVersionStepWorkspaceService {
}): Promise<WorkflowAction> {
// We don't enrich on the fly for code and HTTP request workflow actions.
// For code actions, OutputSchema is computed and updated when testing the serverless function.
// For HTTP requests, OutputSchema is determined by the expamle response input
// For HTTP requests and AI agent, OutputSchema is determined by the expamle response input
if (
[WorkflowActionType.CODE, WorkflowActionType.HTTP_REQUEST].includes(
step.type,
)
[
WorkflowActionType.CODE,
WorkflowActionType.HTTP_REQUEST,
WorkflowActionType.AI_AGENT,
].includes(step.type)
) {
return step;
}
@ -396,6 +400,17 @@ export class WorkflowVersionStepWorkspaceService {
}
break;
}
case WorkflowActionType.AI_AGENT: {
const agent = await this.agentService.findOneAgent(
step.settings.input.agentId,
workspaceId,
);
if (agent) {
await this.agentService.deleteOneAgent(agent.id, workspaceId);
}
break;
}
}
}
@ -578,6 +593,37 @@ export class WorkflowVersionStepWorkspaceService {
},
};
}
case WorkflowActionType.AI_AGENT: {
const newAgent = await this.agentService.createOneAgent(
{
name: 'AI Agent Workflow Step',
description: 'Created automatically for workflow step',
prompt: '',
modelId: 'gpt-4o',
},
workspaceId,
);
if (!isDefined(newAgent)) {
throw new WorkflowVersionStepException(
'Failed to create AI Agent Step',
WorkflowVersionStepExceptionCode.FAILURE,
);
}
return {
id: newStepId,
name: 'AI Agent',
type: WorkflowActionType.AI_AGENT,
valid: false,
settings: {
...BASE_STEP_DEFINITION,
input: {
agentId: newAgent.id,
},
},
};
}
default:
throw new WorkflowVersionStepException(
`WorkflowActionType '${type}' unknown`,