Add new Agents (#14883)

Still experimenting

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
This commit is contained in:
Félix Malfait
2025-10-04 06:45:13 +02:00
committed by GitHub
parent d3a7241b6f
commit 888bf45422
14 changed files with 372 additions and 77 deletions
@@ -19,7 +19,6 @@ import {
import { WorkspaceAgentComparator } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-agent.comparator';
import { StandardAgentFactory } from 'src/engine/workspace-manager/workspace-sync-metadata/factories/standard-agent.factory';
import { standardAgentDefinitions } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-agents';
import { WORKFLOW_CREATION_AGENT } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-agents/agents/workflow-creation-agent';
@Injectable()
export class WorkspaceSyncAgentService {
@@ -110,14 +109,6 @@ export class WorkspaceSyncAgentService {
throw error;
}
}
if (createdAgent.standardId === WORKFLOW_CREATION_AGENT.standardId) {
await this.createAgentHandoffToWorkflowCreationAgent(
createdAgent.id,
context.workspaceId,
manager,
);
}
break;
}
@@ -180,10 +171,12 @@ export class WorkspaceSyncAgentService {
}
}
}
// Create handoffs for standard agents that require them
await this.createStandardAgentHandoffs(context.workspaceId, manager);
}
private async createAgentHandoffToWorkflowCreationAgent(
workflowCreationAgentId: string,
private async createStandardAgentHandoffs(
workspaceId: string,
manager: EntityManager,
): Promise<void> {
@@ -216,43 +209,86 @@ export class WorkspaceSyncAgentService {
if (!defaultAgent) {
this.logger.warn(
`Default agent not found for workspace ${workspaceId}. Agent handoff will not be created.`,
`Default agent not found for workspace ${workspaceId}. Agent handoffs will not be created.`,
);
return;
}
const agentsRequiringHandoffs = standardAgentDefinitions.filter(
(def) => def.createHandoffFromDefaultAgent,
);
for (const agentDefinition of agentsRequiringHandoffs) {
const targetAgent = await agentRepository.findOne({
where: {
standardId: agentDefinition.standardId,
workspaceId,
},
});
if (!targetAgent) {
this.logger.warn(
`Agent ${agentDefinition.name} not found for workspace ${workspaceId}. Skipping handoff creation.`,
);
continue;
}
await this.createAgentHandoff(
defaultAgent.id,
targetAgent.id,
agentDefinition.name,
agentDefinition.description,
workspaceId,
manager,
);
}
} catch (error) {
this.logger.error(
`Failed to create standard agent handoffs: ${error.message}`,
);
}
}
private async createAgentHandoff(
fromAgentId: string,
toAgentId: string,
toAgentName: string,
toAgentDescription: string,
workspaceId: string,
manager: EntityManager,
): Promise<void> {
try {
const agentHandoffRepository = manager.getRepository('agentHandoff');
const existingHandoff = await agentHandoffRepository.findOne({
where: {
fromAgentId: defaultAgent.id,
toAgentId: workflowCreationAgentId,
fromAgentId,
toAgentId,
workspaceId,
},
});
if (existingHandoff) {
this.logger.log(
`Agent handoff from default agent to workflow creation agent already exists for workspace ${workspaceId}`,
`Agent handoff from default agent to ${toAgentName} already exists for workspace ${workspaceId}`,
);
return;
}
await agentHandoffRepository.save({
fromAgentId: defaultAgent.id,
toAgentId: workflowCreationAgentId,
fromAgentId,
toAgentId,
workspaceId,
description:
'Handoff from default agent to workflow creation agent for processing workflow creation requests',
description: `Handoff from default agent to ${toAgentName}: ${toAgentDescription}`,
});
this.logger.log(
`Successfully created agent handoff from default agent to workflow creation agent for workspace ${workspaceId}`,
`Successfully created agent handoff from default agent to ${toAgentName} for workspace ${workspaceId}`,
);
} catch (error) {
this.logger.error(
`Failed to create agent handoff to workflow creation agent: ${error.message}`,
`Failed to create agent handoff to ${toAgentName}: ${error.message}`,
);
}
}
@@ -0,0 +1,59 @@
import { type StandardAgentDefinition } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-agents/types/standard-agent-definition.interface';
import { DATA_MANIPULATOR_ROLE } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-roles/roles/data-manipulator-role';
export const DATA_MANIPULATOR_AGENT: StandardAgentDefinition = {
standardId: '20202020-0002-0001-0001-000000000003',
name: 'data-manipulator',
label: 'Data Manipulator',
description:
'AI agent specialized in creating, updating, and managing data across all objects',
icon: 'IconEdit',
applicationId: null,
createHandoffFromDefaultAgent: true,
prompt: `You are a Data Manipulator Agent specialized in helping users create, update, and manage data in Twenty.
Your capabilities include:
- Creating new records across all standard and custom objects
- Updating existing records based on user requirements
- Managing relationships between records (linking companies to people, etc.)
- Bulk operations on multiple records
- Data cleanup and organization tasks
## Important Constraints:
- You have READ and WRITE access to all object records
- You CANNOT delete records (soft delete or hard delete)
- You CANNOT access workflow-related objects (workflows, workflow versions, workflow runs, etc.)
- You CANNOT modify workspace settings or permissions
## Best Practices:
- Always confirm destructive or bulk operations before executing
- Ask clarifying questions to ensure you understand the user's intent
- Validate data before creating or updating records
- Maintain data consistency and referential integrity
- Provide clear feedback about what operations were performed
## When Creating Records:
- Ask about required fields if not provided
- Suggest appropriate values based on existing data patterns
- Handle relationships correctly (use proper IDs for linked records)
- Validate data types and formats
## When Updating Records:
- Confirm which records should be affected
- Explain what changes will be made before executing
- Handle edge cases gracefully
- Preserve data that isn't being modified
## Data Quality:
- Point out potential data quality issues
- Suggest improvements for data consistency
- Help standardize data formats across records
- Recommend best practices for data entry
Be helpful, careful, and always prioritize data integrity while executing user requests efficiently.`,
modelId: 'auto',
responseFormat: {},
isCustom: false,
standardRoleId: DATA_MANIPULATOR_ROLE.standardId,
modelConfiguration: {},
};
@@ -0,0 +1,47 @@
import { type StandardAgentDefinition } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-agents/types/standard-agent-definition.interface';
import { DATA_NAVIGATOR_ROLE } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-roles/roles/data-navigator-role';
export const DATA_NAVIGATOR_AGENT: StandardAgentDefinition = {
standardId: '20202020-0002-0001-0001-000000000002',
name: 'data-navigator',
label: 'Data Navigator',
description:
'AI agent specialized in exploring and reading data across all objects',
icon: 'IconSearch',
applicationId: null,
createHandoffFromDefaultAgent: true,
prompt: `You are a Data Navigator Agent specialized in helping users explore and understand their data in Twenty.
Your capabilities include:
- Searching and filtering records across all standard and custom objects
- Explaining relationships between different records and objects
- Providing insights about data patterns and trends
- Helping users find specific information quickly
- Answering questions about data structure and relationships
## Important Constraints:
- You have READ-ONLY access to data
- You CANNOT create, update, or delete any records
- You CANNOT access workflow-related objects (workflows, workflow versions, workflow runs, etc.)
- When users request modifications, politely explain your read-only limitations
## Best Practices:
- Ask clarifying questions to understand what data the user is looking for
- Provide clear, structured information when presenting data
- Explain the context and relationships between records
- Suggest useful filters or queries to refine searches
- Help users understand their data schema and available fields
## When Helping Users:
- Be proactive in suggesting related data that might be useful
- Explain any patterns or anomalies you notice in the data
- Provide context about record counts, date ranges, and relationships
- Guide users on how to effectively navigate their workspace data
Be helpful, thorough, and always prioritize helping users understand and navigate their data effectively.`,
modelId: 'auto',
responseFormat: {},
isCustom: false,
standardRoleId: DATA_NAVIGATOR_ROLE.standardId,
modelConfiguration: {},
};
@@ -0,0 +1,52 @@
import { type StandardAgentDefinition } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-agents/types/standard-agent-definition.interface';
import { WORKFLOW_MANAGER_ROLE } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-roles/roles/workflow-manager-role';
export const WORKFLOW_BUILDER_AGENT: StandardAgentDefinition = {
standardId: '20202020-0002-0001-0001-000000000001',
name: 'workflow-builder',
label: 'Workflow Builder',
description: 'AI agent specialized in creating and managing workflows',
icon: 'IconSettingsAutomation',
applicationId: null,
createHandoffFromDefaultAgent: true,
prompt: `You are a Workflow Builder Agent specialized in helping users create, modify, and manage workflows in Twenty.
Your capabilities include:
- Creating new workflows from scratch based on user requirements
- Modifying existing workflows by adding, removing, or updating steps
- Explaining workflow structures and how they work
- Suggesting workflow improvements and optimizations
- Helping users understand workflow actions and their configurations
## IMPORTANT: Rely on Schema Definitions
- The workflow creation tool provides comprehensive schema definitions with detailed descriptions and examples
- Always refer to the tool's schema for field requirements, data types, and examples
- The schema includes common patterns, field structures, and validation rules
- Use the schema descriptions to understand how to properly reference data between workflow steps
## Key Workflow Concepts:
- **Triggers**: Start workflows (DATABASE_EVENT, MANUAL, CRON, WEBHOOK)
- **Steps**: Actions that execute in sequence (CREATE_RECORD, SEND_EMAIL, CODE, etc.)
- **Data Flow**: Use {{stepId.fieldName}} to reference data from previous steps
- **Relationships**: Use nested objects for related records (e.g., "company": {"id": "{{reference}}"})
When creating workflows:
- Always ask clarifying questions to understand the user's needs
- Suggest appropriate workflow actions based on the use case
- Explain each step and why it's needed
- Provide clear, actionable guidance
- Follow the schema definitions exactly for field names, types, and structures
When modifying workflows:
- Understand the current workflow structure first
- Suggest specific changes that address the user's requirements
- Ensure workflow logic remains coherent and functional
- Maintain proper data references between steps
Be helpful, thorough, and always prioritize user understanding and workflow effectiveness.`,
modelId: 'auto',
responseFormat: {},
isCustom: false,
standardRoleId: WORKFLOW_MANAGER_ROLE.standardId,
modelConfiguration: {},
};
@@ -1,10 +1,10 @@
import { type StandardAgentDefinition } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-agents/types/standard-agent-definition.interface';
import { WORKFLOW_MANAGER_ROLE } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-roles/roles/workflow-manager-role';
export const WORKFLOW_CREATION_AGENT: StandardAgentDefinition = {
export const WORKFLOW_BUILDER_AGENT: StandardAgentDefinition = {
standardId: '20202020-0002-0001-0001-000000000001',
name: 'workflow-creation-agent',
label: 'Workflow Creation Agent',
name: 'workflow-builder',
label: 'Workflow Builder',
description: 'AI agent specialized in creating and managing workflows',
icon: 'IconSettingsAutomation',
applicationId: null,
@@ -1,6 +1,10 @@
import { WORKFLOW_CREATION_AGENT } from './agents/workflow-creation-agent';
import { DATA_MANIPULATOR_AGENT } from './agents/data-manipulator-agent';
import { DATA_NAVIGATOR_AGENT } from './agents/data-navigator-agent';
import { WORKFLOW_BUILDER_AGENT } from './agents/workflow-builder-agent';
import { type StandardAgentDefinition } from './types/standard-agent-definition.interface';
export const standardAgentDefinitions = [
WORKFLOW_CREATION_AGENT,
WORKFLOW_BUILDER_AGENT,
DATA_NAVIGATOR_AGENT,
DATA_MANIPULATOR_AGENT,
] as const satisfies StandardAgentDefinition[];
@@ -6,4 +6,6 @@ export type StandardAgentDefinition = Omit<
> & {
standardId: string;
standardRoleId?: string;
// If true, creates a handoff from the default agent to this agent
createHandoffFromDefaultAgent?: boolean;
};
@@ -1,8 +1,12 @@
import { ADMIN_ROLE } from './roles/admin-role';
import { DATA_MANIPULATOR_ROLE } from './roles/data-manipulator-role';
import { DATA_NAVIGATOR_ROLE } from './roles/data-navigator-role';
import { WORKFLOW_MANAGER_ROLE } from './roles/workflow-manager-role';
import { type StandardRoleDefinition } from './types/standard-role-definition.interface';
export const standardRoleDefinitions = [
ADMIN_ROLE,
WORKFLOW_MANAGER_ROLE,
DATA_NAVIGATOR_ROLE,
DATA_MANIPULATOR_ROLE,
] as const satisfies StandardRoleDefinition[];
@@ -0,0 +1,18 @@
import { type StandardRoleDefinition } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-roles/types/standard-role-definition.interface';
export const DATA_MANIPULATOR_ROLE: StandardRoleDefinition = {
standardId: '20202020-0001-0001-0001-000000000004',
label: 'Data Manipulator',
description: 'Read and write access to all object records',
icon: 'IconEdit',
isEditable: false,
canUpdateAllSettings: false,
canAccessAllTools: false,
canReadAllObjectRecords: true,
canUpdateAllObjectRecords: true,
canSoftDeleteAllObjectRecords: false,
canDestroyAllObjectRecords: false,
canBeAssignedToUsers: false,
canBeAssignedToAgents: true,
canBeAssignedToApiKeys: false,
};
@@ -0,0 +1,18 @@
import { type StandardRoleDefinition } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-roles/types/standard-role-definition.interface';
export const DATA_NAVIGATOR_ROLE: StandardRoleDefinition = {
standardId: '20202020-0001-0001-0001-000000000003',
label: 'Data Navigator',
description: 'Read-only access to all object records',
icon: 'IconSearch',
isEditable: false,
canUpdateAllSettings: false,
canAccessAllTools: false,
canReadAllObjectRecords: true,
canUpdateAllObjectRecords: false,
canSoftDeleteAllObjectRecords: false,
canDestroyAllObjectRecords: false,
canBeAssignedToUsers: false,
canBeAssignedToAgents: true,
canBeAssignedToApiKeys: false,
};