From 69fa3675846dba0f4b0a07fb477128dab3742f73 Mon Sep 17 00:00:00 2001 From: ValueOn AG Date: Sun, 2 Nov 2025 23:31:10 +0100 Subject: [PATCH] revised validation logic --- .../datamodels/PROPOSAL_CLASS_ENHANCEMENTS.md | 285 ++++++++++++++++++ modules/datamodels/datamodelChat.py | 13 +- .../processing/adaptive/contentValidator.py | 14 +- .../processing/adaptive/intentAnalyzer.py | 11 +- .../processing/adaptive/learningEngine.py | 25 +- .../workflows/processing/core/taskPlanner.py | 4 +- .../processing/modes/modeActionplan.py | 6 +- .../workflows/processing/modes/modeDynamic.py | 6 +- .../shared/promptGenerationTaskplan.py | 3 +- 9 files changed, 333 insertions(+), 34 deletions(-) create mode 100644 modules/datamodels/PROPOSAL_CLASS_ENHANCEMENTS.md diff --git a/modules/datamodels/PROPOSAL_CLASS_ENHANCEMENTS.md b/modules/datamodels/PROPOSAL_CLASS_ENHANCEMENTS.md new file mode 100644 index 00000000..50cc494f --- /dev/null +++ b/modules/datamodels/PROPOSAL_CLASS_ENHANCEMENTS.md @@ -0,0 +1,285 @@ +# Pydantic Class Enhancement Proposal +## Format Tracking & Validation Alignment + +**Date:** 2025-11-02 +**Purpose:** Align validation logic with prompt requirements, enable workflow-level validation, and track expected file formats + +**Simplified Approach:** Use existing document metadata (name, size, format, mimeType) - no summary fields needed + +--- + +## Executive Summary + +This proposal addresses: +1. **Validation alignment**: What prompts ask for matches what validators check +2. **Workflow-level validation**: Check ALL deliverables from ALL tasks against original user request +3. **Format tracking**: Track expected formats (list) at workflow and task levels +4. **Adaptive task planning**: Next task uses ALL workflow data (messages, document metadata) to refine objective + +**Key Simplification:** Actions deliver documents with metadata (as today). No summary fields needed - use existing document metadata. + +--- + +## 1. ActionResult Class Changes + +**File:** `gateway/modules/datamodels/datamodelChat.py` (lines 483-521) + +### NO CHANGES NEEDED + +**Current Structure (KEEP ALL - ALL USED):** +- ✅ `success: bool` - Used by validation +- ✅ `error: Optional[str]` - Used for error handling +- ✅ `documents: List[ActionDocument]` - Contains document metadata (name, data, mimeType) +- ✅ `resultLabel: Optional[str]` - Used for document routing + +**Documents already provide all needed metadata:** +- `documentName` - File name +- `documentData` - Content +- `mimeType` - MIME type (can derive format from this) + +**No summary field needed** - document metadata is sufficient. + +--- + +## 2. TaskResult Class Changes + +**File:** `gateway/modules/datamodels/datamodelChat.py` (lines 718-736) + +### NO CHANGES NEEDED + +**Current Structure (KEEP ALL - ALL USED):** +- ✅ `taskId: str` - Task identification +- ✅ `status: TaskStatus` - Task status tracking +- ✅ `success: bool` - Success flag +- ✅ `feedback: Optional[str]` - Task feedback +- ✅ `error: Optional[str]` - Error message + +**Document metadata available from workflow:** +- Can extract delivered formats from documents in workflow messages +- No need to store separately - use existing document metadata + +--- + +## 3. TaskStep Class Changes + +**File:** `gateway/modules/datamodels/datamodelChat.py` (lines 790-825) + +### Modify +- Change `expectedFormat: Optional[str]` → `expectedFormats: Optional[List[str]]` +- Keep `dataType` and `qualityRequirements` as-is + +### Modified Class: +```python +class TaskStep(BaseModel): + id: str + objective: str + dependencies: Optional[list[str]] = Field(default_factory=list) + successCriteria: Optional[list[str]] = Field(default_factory=list) + estimatedComplexity: Optional[str] = None + userMessage: Optional[str] = Field( + None, description="User-friendly message in user's language" + ) + # Format details extracted from intent analysis + dataType: Optional[str] = Field( + None, description="Expected data type (text, numbers, documents, etc.)" + ) + expectedFormats: Optional[List[str]] = Field( + None, description="Expected output file format extensions (e.g., ['docx', 'pdf', 'xlsx']). Use actual file extensions, not conceptual terms." + ) + qualityRequirements: Optional[Dict[str, Any]] = Field( + None, description="Quality requirements and constraints" + ) +``` + +### Register Labels +Update: +```python +"expectedFormats": {"en": "Expected Formats", "fr": "Formats attendus"} +``` + +--- + +## 4. ChatWorkflow Class Changes (for Workflow-Level Tracking) + +**File:** `gateway/modules/datamodels/datamodelChat.py` (find ChatWorkflow class) + +### Add (if not exists) +```python +expectedFormats: Optional[List[str]] = Field( + None, + description="List of expected file format extensions from user request (e.g., ['xlsx', 'pdf']). Extracted during intent analysis." +) +``` + +Note: `_workflowIntent` is already stored as a dict (not a model field), so `expectedFormats` can be extracted from there, but having it as an explicit field makes it easier to query. + +--- + +## 5. ActionItem Class Review + +**File:** `gateway/modules/datamodels/datamodelChat.py` (lines 652-715) + +### Current Structure (ALL USED - KEEP): +- ✅ `id: str` - Used for action identification +- ✅ `execMethod: str` - Used for action execution +- ✅ `execAction: str` - Used for action execution +- ✅ `execParameters: Dict[str, Any]` - Used for action execution +- ✅ `execResultLabel: Optional[str]` - Used for document routing +- ✅ `expectedDocumentFormats: Optional[List[Dict[str, str]]]` - Used by action planning +- ✅ `userMessage: Optional[str]` - Used for user communication +- ✅ `status: TaskStatus` - Used for tracking +- ✅ `error: Optional[str]` - Used for error handling +- ✅ `retryCount: int` - Used for retry logic +- ✅ `retryMax: int` - Used for retry logic +- ✅ `processingTime: Optional[float]` - Used for performance tracking +- ✅ `timestamp: float` - Used for ordering/auditing +- ✅ `result: Optional[str]` - Used to store action result text + +**NO CHANGES NEEDED** - All attributes are used + +--- + +## 6. Summary of Changes + +### Classes to Modify: +1. ✅ **TaskStep** - Change `expectedFormat` (str) → `expectedFormats` (List[str]) +2. ✅ **ChatWorkflow** - Add `expectedFormats` (optional, for explicit tracking) + +### Classes to Review (NO CHANGES): +- ✅ **ActionResult** - Keep as-is, documents already have metadata +- ✅ **TaskResult** - Keep as-is, no summary needed +- ✅ **ActionDocument** - Already correct (documentName, documentData, mimeType) +- ✅ **ActionItem** - All attributes used +- ✅ **Observation** - Already has contentValidation field +- ✅ **TaskItem** - Used for database storage, separate from TaskStep + +--- + +## 7. Implementation Impact + +### Files That Will Need Updates: + +1. **datamodelChat.py** - Class definitions (this proposal) + - Change `expectedFormat` → `expectedFormats` in TaskStep + - Add `expectedFormats` to ChatWorkflow (optional) + +2. **taskPlanner.py** - Populate `expectedFormats` list instead of single `expectedFormat` + - **Adaptive planning:** Use ALL workflow data (messages, document metadata) to refine next task objective + - Extract delivered formats from workflow documents + - Compare what was delivered vs. what was planned + +3. **contentValidator.py** - Use `expectedFormats` list for validation + - **Action-level validation:** Check action results against task objective (already exists) + - **Task-level validation:** Validate THIS task's deliverables against THIS task's expectations + - Uses document metadata (name, size, format, mimeType) - no summaries needed + +4. **intentAnalyzer.py** - Fix prompt to ask for actual file format extensions + - Change from conceptual terms ("raw_data", "formatted") to actual extensions ("pdf", "docx", "xlsx") + +5. **promptGenerationTaskplan.py** - Ask for `expectedFormats` in task planning + - **Adaptive planning:** Include ALL workflow data (messages, document names/sizes/formats/metadata) when planning next task + - Show what was actually delivered to help refine objective + +6. **workflowManager.py** - Pass ALL workflow data to next task planning + - Messages (text content) + - Document metadata (names, sizes, formats, mimeTypes) + - Validation results + +### Key Implementation Points: + +- **No summary fields:** Use existing document metadata (name, size, format, mimeType) +- **Adaptive task planning:** Next task receives ALL workflow data (messages + document metadata) to refine objective +- **Validation scope:** Task validation checks ONLY that task's actions, not all workflow actions +- **After each action:** Validate against task objective → decide if complete or next action needed + +--- + +## 8. Validation Logic Alignment + +### Action-Level Validation (Within Task): +- **When:** After each action execution within a task +- **Checks:** Action results against task objective +- **Against:** Action documents (name, size, format, mimeType metadata) +- **Purpose:** Decide if task is complete or next action needed +- **Triggers:** Continue to next action if incomplete, complete task if done + +### Task Planning (Adaptive - Uses ALL Workflow Data): +- **Input:** ALL workflow data available: + - All messages (text content) + - All document metadata (names, sizes, formats/extensions, mimeTypes) + - Previous task validation results +- **Process:** + - Extract delivered formats from all workflow documents + - Compare what was ACTUALLY delivered vs. what was PLANNED + - Refine next task objective: + - Deliver MORE if previous tasks delivered less than expected + - Deliver LESS if previous tasks already delivered more + - Adapt to actual workflow progress + +### Task-Level Validation (Task Completion): +- **When:** After ALL actions in a task complete +- **Checks:** Task objective, task `expectedFormats`, task `successCriteria` +- **Against:** Documents from THIS task only (extract formats from document metadata) +- **Purpose:** Verify THIS task delivered what was expected for THIS task scope +- **Output:** Validation result (used in workflow data for next task planning) + +### Workflow-Level Validation (Final): +- **When:** After ALL tasks complete +- **Checks:** Original user request, workflow `expectedFormats`, workflow success criteria +- **Against:** ALL documents from ALL tasks (extract formats from document metadata) +- **Purpose:** Final verification that complete workflow delivered what user requested +- **Triggers:** New compensatory task if validation fails (missing deliverables) + +--- + +## 9. Next Steps + +1. **Review and approve this proposal** +2. **Implement class changes** in datamodelChat.py +3. **Update intent analyzer prompt** to request actual file format extensions +4. **Update task planning prompt** to request `expectedFormats` list +5. **Update AI generation prompts** to include summary instruction +6. **Implement aggregation logic** for summaries at task/workflow levels +7. **Implement workflow-level validation** method +8. **Update all references** from `expectedFormat` to `expectedFormats` + +--- + +## Questions Answered + +✅ **Document metadata:** Use existing document fields (name, size, format from mimeType/extensions) - no summaries needed +✅ **Format extraction:** Extract formats from document metadata (mimeType or file extensions) +✅ **Task validation scope:** Task validation checks ONLY actions in that task, not all workflow actions +✅ **Adaptive planning:** Next task uses ALL workflow data (messages + document metadata) to refine objective +✅ **After each action:** Validate against task objective → decide complete or next action needed + +--- + +## 10. Validation Flow Clarification + +### Simplified Flow: + +1. **Within Task (Action-by-Action):** + - Action executes → delivers documents with metadata + - Validate action results against task objective + - If incomplete → next action needed + - If complete → task done + +2. **Task Planning (Adaptive):** + - Receives: ALL workflow data (messages, document metadata from all previous tasks) + - Extracts: Delivered formats from document metadata (file extensions/mimeTypes) + - Compares: What was actually delivered vs. what was planned + - Refines: Next task objective (may need more/less based on actual progress) + +3. **Task Completion:** + - Validate: THIS task's documents (extract formats from metadata) against THIS task's expectations + - Result: Used in workflow data for next task planning + +4. **Workflow Completion:** + - Final validation: All documents (extract formats from metadata) meet original user request + - If missing: Create compensatory task + +--- + +**Status:** Ready for implementation after approval + diff --git a/modules/datamodels/datamodelChat.py b/modules/datamodels/datamodelChat.py index 680bd3cc..cdeebfed 100644 --- a/modules/datamodels/datamodelChat.py +++ b/modules/datamodels/datamodelChat.py @@ -417,6 +417,13 @@ class ChatWorkflow(BaseModel): frontend_readonly=False, frontend_required=False, ) + expectedFormats: Optional[List[str]] = Field( + None, + description="List of expected file format extensions from user request (e.g., ['xlsx', 'pdf']). Extracted during intent analysis.", + frontend_type="text", + frontend_readonly=True, + frontend_required=False, + ) registerModelLabels( @@ -440,6 +447,7 @@ registerModelLabels( "tasks": {"en": "Tasks", "fr": "Tâches"}, "workflowMode": {"en": "Workflow Mode", "fr": "Mode de workflow"}, "maxSteps": {"en": "Max Steps", "fr": "Étapes max"}, + "expectedFormats": {"en": "Expected Formats", "fr": "Formats attendus"}, }, ) @@ -800,8 +808,8 @@ class TaskStep(BaseModel): dataType: Optional[str] = Field( None, description="Expected data type (text, numbers, documents, etc.)" ) - expectedFormat: Optional[str] = Field( - None, description="Expected output format (json, csv, markdown, etc.)" + expectedFormats: Optional[List[str]] = Field( + None, description="Expected output file format extensions (e.g., ['docx', 'pdf', 'xlsx']). Use actual file extensions, not conceptual terms." ) qualityRequirements: Optional[Dict[str, Any]] = Field( None, description="Quality requirements and constraints" @@ -821,6 +829,7 @@ registerModelLabels( "fr": "Complexité estimée", }, "userMessage": {"en": "User Message", "fr": "Message utilisateur"}, + "expectedFormats": {"en": "Expected Formats", "fr": "Formats attendus"}, }, ) diff --git a/modules/workflows/processing/adaptive/contentValidator.py b/modules/workflows/processing/adaptive/contentValidator.py index 61bad944..8b0c3127 100644 --- a/modules/workflows/processing/adaptive/contentValidator.py +++ b/modules/workflows/processing/adaptive/contentValidator.py @@ -263,22 +263,22 @@ class ContentValidator: # Use taskStep format fields if available, otherwise fall back to intent dataType = None - expectedFormat = None + expectedFormats = None if taskStep: if hasattr(taskStep, 'dataType') and taskStep.dataType: dataType = taskStep.dataType elif isinstance(taskStep, dict): dataType = taskStep.get('dataType') - if hasattr(taskStep, 'expectedFormat') and taskStep.expectedFormat: - expectedFormat = taskStep.expectedFormat + if hasattr(taskStep, 'expectedFormats') and taskStep.expectedFormats: + expectedFormats = taskStep.expectedFormats elif isinstance(taskStep, dict): - expectedFormat = taskStep.get('expectedFormat') + expectedFormats = taskStep.get('expectedFormats') # Fallback to intent if taskStep format fields not available if not dataType: dataType = intent.get('dataType', 'unknown') - if not expectedFormat: - expectedFormat = intent.get('expectedFormat', 'unknown') + if not expectedFormats: + expectedFormats = intent.get('expectedFormats', []) # Determine objective text and label objectiveText = taskObjective if taskObjective else intent.get('primaryGoal', 'Unknown') @@ -299,7 +299,7 @@ class ContentValidator: {objectiveLabel}: '{objectiveText}' EXPECTED DATA TYPE: {dataType} -EXPECTED FORMAT: {expectedFormat} +EXPECTED FORMATS: {expectedFormats if expectedFormats else ['any']} SUCCESS CRITERIA ({criteriaCount} items): {successCriteria} VALIDATION RULES: diff --git a/modules/workflows/processing/adaptive/intentAnalyzer.py b/modules/workflows/processing/adaptive/intentAnalyzer.py index 4ad17861..7fe0fbda 100644 --- a/modules/workflows/processing/adaptive/intentAnalyzer.py +++ b/modules/workflows/processing/adaptive/intentAnalyzer.py @@ -50,8 +50,10 @@ You are an intent analyzer. Analyze the user's request to understand what they w Analyze the user's intent and determine: 1. What type of data/content they want (numbers, text, documents, analysis, code, etc.) -2. What format they expect (raw data, formatted, structured, visual, etc.) -3. What quality requirements they have (accuracy, completeness, format) +2. What file format(s) they expect - provide matching file format extensions list + - If multiple formats requested, list all of them (e.g., ["xlsx", "pdf"]) + - If format is unclear or not specified, use empty list [] +3. What quality requirements they have (accuracy, completeness) 4. What specific success criteria define completion 5. What language the user is communicating in (detect from the user request) @@ -60,11 +62,10 @@ CRITICAL: Respond with ONLY the JSON object below. Do not include any explanator {{ "primaryGoal": "The main objective the user wants to achieve", "dataType": "numbers|text|documents|analysis|code|unknown", - "expectedFormat": "raw_data|formatted|structured|visual|unknown", + "expectedFormats": ["pdf", "docx", "xlsx", "txt", "json", "csv", "html", "md"], "qualityRequirements": {{ "accuracyThreshold": 0.0-1.0, - "completenessThreshold": 0.0-1.0, - "formatRequirement": "any|formatted|raw|structured" + "completenessThreshold": 0.0-1.0 }}, "successCriteria": ["specific criterion 1", "specific criterion 2"], "languageUserDetected": "en", diff --git a/modules/workflows/processing/adaptive/learningEngine.py b/modules/workflows/processing/adaptive/learningEngine.py index 5ed29e80..f7d26668 100644 --- a/modules/workflows/processing/adaptive/learningEngine.py +++ b/modules/workflows/processing/adaptive/learningEngine.py @@ -116,53 +116,56 @@ class LearningEngine: def _getStrategyKey(self, intent: Dict[str, Any]) -> str: """Gets strategy key based on intent""" dataType = intent.get('dataType', 'unknown') - expectedFormat = intent.get('expectedFormat', 'unknown') - return f"{dataType}_{expectedFormat}" + expectedFormats = intent.get('expectedFormats', []) + formatKey = '_'.join(expectedFormats) if expectedFormats else 'unknown' + return f"{dataType}_{formatKey}" def _createDefaultStrategy(self, intent: Dict[str, Any]) -> Dict[str, Any]: """Creates a default strategy for the intent""" dataType = intent.get('dataType', 'unknown') - expectedFormat = intent.get('expectedFormat', 'unknown') + expectedFormats = intent.get('expectedFormats', []) + formatStr = ', '.join(expectedFormats) if expectedFormats else 'any' + formatKey = '_'.join(expectedFormats) if expectedFormats else 'unknown' # Create strategy based on intent type if dataType == 'numbers': return { - 'strategyId': f"numbers_{expectedFormat}", + 'strategyId': f"numbers_{formatKey}", 'successfulActions': [], 'failedActions': [], 'successRate': 0.5, 'lastModified': datetime.now(timezone.utc).timestamp(), - 'recommendedPrompt': f"Deliver {dataType} data in {expectedFormat} format. Provide actual numbers, not code to generate them.", + 'recommendedPrompt': f"Deliver {dataType} data in {formatStr} format. Provide actual numbers, not code to generate them.", 'avoidPrompt': "Do not ask AI to write code when user wants data. Deliver the data directly." } elif dataType == 'text': return { - 'strategyId': f"text_{expectedFormat}", + 'strategyId': f"text_{formatKey}", 'successfulActions': [], 'failedActions': [], 'successRate': 0.5, 'lastModified': datetime.now(timezone.utc).timestamp(), - 'recommendedPrompt': f"Generate {dataType} content in {expectedFormat} format.", + 'recommendedPrompt': f"Generate {dataType} content in {formatStr} format.", 'avoidPrompt': "Ensure content is readable and well-structured." } elif dataType == 'documents': return { - 'strategyId': f"documents_{expectedFormat}", + 'strategyId': f"documents_{formatKey}", 'successfulActions': [], 'failedActions': [], 'successRate': 0.5, 'lastModified': datetime.now(timezone.utc).timestamp(), - 'recommendedPrompt': f"Create {dataType} in {expectedFormat} format with proper structure.", + 'recommendedPrompt': f"Create {dataType} in {formatStr} format with proper structure.", 'avoidPrompt': "Ensure document is properly formatted and organized." } else: return { - 'strategyId': f"unknown_{expectedFormat}", + 'strategyId': f"unknown_{formatKey}", 'successfulActions': [], 'failedActions': [], 'successRate': 0.5, 'lastModified': datetime.now(timezone.utc).timestamp(), - 'recommendedPrompt': f"Deliver {dataType} content in {expectedFormat} format.", + 'recommendedPrompt': f"Deliver {dataType} content in {formatStr} format.", 'avoidPrompt': "Ensure content matches user requirements." } diff --git a/modules/workflows/processing/core/taskPlanner.py b/modules/workflows/processing/core/taskPlanner.py index cc66a264..e2b84305 100644 --- a/modules/workflows/processing/core/taskPlanner.py +++ b/modules/workflows/processing/core/taskPlanner.py @@ -163,8 +163,8 @@ class TaskPlanner: if isinstance(workflowIntent, dict): if 'dataType' in workflowIntent and 'dataType' not in taskDict: taskDict['dataType'] = workflowIntent.get('dataType') - if 'expectedFormat' in workflowIntent and 'expectedFormat' not in taskDict: - taskDict['expectedFormat'] = workflowIntent.get('expectedFormat') + if 'expectedFormats' in workflowIntent and 'expectedFormats' not in taskDict: + taskDict['expectedFormats'] = workflowIntent.get('expectedFormats') if 'qualityRequirements' in workflowIntent and 'qualityRequirements' not in taskDict: taskDict['qualityRequirements'] = workflowIntent.get('qualityRequirements') diff --git a/modules/workflows/processing/modes/modeActionplan.py b/modules/workflows/processing/modes/modeActionplan.py index b9820ffc..0d5c4e08 100644 --- a/modules/workflows/processing/modes/modeActionplan.py +++ b/modules/workflows/processing/modes/modeActionplan.py @@ -242,12 +242,12 @@ class ActionplanMode(BaseMode): self.workflowIntent = await self.intentAnalyzer.analyzeUserIntent(originalPrompt, context) logger.warning(f"Workflow intent not found in workflow object, analyzed fresh") - # Task-level intent is NOT needed - use task.objective + task format fields (dataType, expectedFormat, qualityRequirements) + # Task-level intent is NOT needed - use task.objective + task format fields (dataType, expectedFormats, qualityRequirements) # These format fields are populated from workflow intent during task planning self.taskIntent = None # Removed redundant task-level intent analysis logger.info(f"Workflow intent: {self.workflowIntent}") - if taskStep.dataType or taskStep.expectedFormat or taskStep.qualityRequirements: - logger.info(f"Task format info: dataType={taskStep.dataType}, expectedFormat={taskStep.expectedFormat}") + if taskStep.dataType or taskStep.expectedFormats or taskStep.qualityRequirements: + logger.info(f"Task format info: dataType={taskStep.dataType}, expectedFormats={taskStep.expectedFormats}") # Reset progress tracking for new task self.progressTracker.reset() diff --git a/modules/workflows/processing/modes/modeDynamic.py b/modules/workflows/processing/modes/modeDynamic.py index 8a2d691d..9fa0a3c0 100644 --- a/modules/workflows/processing/modes/modeDynamic.py +++ b/modules/workflows/processing/modes/modeDynamic.py @@ -61,12 +61,12 @@ class DynamicMode(BaseMode): self.workflowIntent = await self.intentAnalyzer.analyzeUserIntent(original_prompt, context) logger.warning(f"Workflow intent not found in workflow object, analyzed fresh") - # Task-level intent is NOT needed - use task.objective + task format fields (dataType, expectedFormat, qualityRequirements) + # Task-level intent is NOT needed - use task.objective + task format fields (dataType, expectedFormats, qualityRequirements) # These format fields are populated from workflow intent during task planning self.taskIntent = None # Removed redundant task-level intent analysis logger.info(f"Workflow intent: {self.workflowIntent}") - if taskStep.dataType or taskStep.expectedFormat or taskStep.qualityRequirements: - logger.info(f"Task format info: dataType={taskStep.dataType}, expectedFormat={taskStep.expectedFormat}") + if taskStep.dataType or taskStep.expectedFormats or taskStep.qualityRequirements: + logger.info(f"Task format info: dataType={taskStep.dataType}, expectedFormats={taskStep.expectedFormats}") # NEW: Reset progress tracking for new task self.progressTracker.reset() diff --git a/modules/workflows/processing/shared/promptGenerationTaskplan.py b/modules/workflows/processing/shared/promptGenerationTaskplan.py index a01dd7e6..de101015 100644 --- a/modules/workflows/processing/shared/promptGenerationTaskplan.py +++ b/modules/workflows/processing/shared/promptGenerationTaskplan.py @@ -82,7 +82,8 @@ Break down user requests into logical, executable task steps. "dependencies": ["task_0"], "successCriteria": ["measurable criteria 1", "measurable criteria 2"], "estimatedComplexity": "low|medium|high", - "userMessage": "What this task will accomplish in language '{{KEY:USER_LANGUAGE}}'" + "userMessage": "What this task will accomplish in language '{{KEY:USER_LANGUAGE}}'", + "expectedFormats": ["pdf", "docx", "xlsx", "txt", "json", "csv", "html", "md",...] }} ], }}