a281f2a773
## Summary
This PR adds configurable response format support for AI agents,
allowing them to return either plain text or structured JSON data based
on a defined schema.
## Key Features
### 1. Agent Response Format Configuration
- Added `AgentResponseFormat` type supporting:
- `text`: Returns plain text responses (default)
- `json`: Returns structured JSON based on defined schema
- New `AgentResponseSchema` type moved to `twenty-shared/ai` for sharing
between frontend/backend
### 2. Settings UI
- New `SettingsAgentResponseFormat` component for configuring response
format
- Visual schema builder for defining JSON output structure
- Real-time validation and preview
- Integrated into agent settings tab
### 3. Workflow Integration
- AI Agent workflow action automatically uses agent's configured
response format
- Output schema dynamically generated from agent's response format
- Workflow variable picker shows structured fields for JSON responses
- Backward compatible with existing text-only agents
### 4. Backend Implementation
- Added `convertAgentSchemaToZod` utility to validate JSON responses
- Agent executor service handles both text and JSON generation
- Automatic agent creation/cloning when adding AI agent steps to
workflows
- Unique agent naming with conflict resolution
### 5. Database Migration
- Migration `1763622159656-update-agent-response-format.ts`
- Sets default `responseFormat` to `{"type":"text"}` for existing agents
- Updated all standard agents with proper response format
## Changes by Module
### Frontend (`twenty-front`)
- 🆕 `AgentResponseFormat` type
- 🆕 `SettingsAgentResponseFormat` component
- ✏️ Updated `WorkflowEditActionAiAgent` to support response format
configuration
- 🗑️ Removed deprecated `useAiAgentOutputSchema` hook and
`AiAgentOutputSchema` type
### Backend (`twenty-server`)
- 🆕 `AgentResponseFormat` type in agent entity
- 🆕 `convertAgentSchemaToZod` utility for schema validation
- ✏️ Updated `AiAgentExecutorService` to handle both text and JSON
generation
- ✏️ Updated `WorkflowSchemaWorkspaceService` to generate output schema
from agent config
- ✏️ Enhanced `WorkflowVersionStepOperationsWorkspaceService` with agent
creation/cloning
- 🆕 Agent naming constants for conflict resolution
### Shared (`twenty-shared`)
- 🆕 `AgentResponseSchema` type
- 🆕 `ModelConfiguration` type moved to shared package
- Updated exports in `ai/index.ts`
## Code Quality
- Removed useless comments following code style guidelines
- All linter checks passed
- Type-safe implementation with proper TypeScript types
## Testing
- ✅ Database migration tested
- ✅ Agent creation/cloning in workflows verified
- ✅ Response format switching (text ↔ JSON) validated
- ✅ Backward compatibility with existing agents confirmed
## Migration Notes
- Existing agents will have `responseFormat: {type: 'text'}` set
automatically
- No breaking changes - all existing functionality preserved
- Agents can be updated to use JSON format through settings UI
68 lines
1.4 KiB
TypeScript
68 lines
1.4 KiB
TypeScript
import { Field, InputType } from '@nestjs/graphql';
|
|
|
|
import {
|
|
IsNotEmpty,
|
|
IsObject,
|
|
IsOptional,
|
|
IsString,
|
|
IsUUID,
|
|
} from 'class-validator';
|
|
import GraphQLJSON from 'graphql-type-json';
|
|
|
|
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
|
import { ModelId } from 'src/engine/core-modules/ai/constants/ai-models.const';
|
|
import { ModelConfiguration } from 'src/engine/metadata-modules/agent/types/modelConfiguration';
|
|
|
|
@InputType()
|
|
export class UpdateAgentInput {
|
|
@IsUUID()
|
|
@IsNotEmpty()
|
|
@Field(() => UUIDScalarType)
|
|
id: string;
|
|
|
|
@IsString()
|
|
@IsOptional()
|
|
@Field({ nullable: true })
|
|
name?: string;
|
|
|
|
@IsString()
|
|
@IsOptional()
|
|
@Field({ nullable: true })
|
|
label?: string;
|
|
|
|
@IsString()
|
|
@IsOptional()
|
|
@Field({ nullable: true })
|
|
icon?: string;
|
|
|
|
@IsString()
|
|
@IsOptional()
|
|
@Field({ nullable: true })
|
|
description?: string;
|
|
|
|
@IsString()
|
|
@IsOptional()
|
|
@Field({ nullable: true })
|
|
prompt?: string;
|
|
|
|
@IsString()
|
|
@IsOptional()
|
|
@Field(() => String, { nullable: true })
|
|
modelId?: ModelId;
|
|
|
|
@IsUUID()
|
|
@IsOptional()
|
|
@Field(() => UUIDScalarType, { nullable: true })
|
|
roleId?: string;
|
|
|
|
@IsObject()
|
|
@IsOptional()
|
|
@Field(() => GraphQLJSON, { nullable: true })
|
|
responseFormat?: object;
|
|
|
|
@IsObject()
|
|
@IsOptional()
|
|
@Field(() => GraphQLJSON, { nullable: true })
|
|
modelConfiguration?: ModelConfiguration;
|
|
}
|