Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion workflows/examples/scripts/generate_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ async def generate_and_store_workflow():
original_task=TASK_DESCRIPTION.strip(),
)

print(f'✅ Workflow saved to storage!\n')
print('✅ Workflow saved to storage!\n')

# Display summary
print('=' * 80)
Expand Down
4 changes: 4 additions & 0 deletions workflows/examples/workflows/basic/example.workflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ steps:
xpath: id("single")
elementTag: BUTTON
elementText: null
- description: Extract form submission confirmation and status
type: extract_page_content
goal: Extract the confirmation message, success status, or any validation errors from the current page
output: form_status
input_schema:
- name: first_name
type: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ steps:
- description: Select marital status
type: click
target_text: Single
- description: Extract form completion status
type: extract_page_content
goal: Extract any confirmation messages, success status, or validation errors from the form page
output: form_status
input_schema:
- name: first_name
type: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ steps:
- description: Continue to next section
type: click
target_text: 'Next: Contact Information'
- description: Extract form progress and confirmation
type: extract_page_content
goal: Extract the current section confirmation, any success messages, or validation errors shown on the page
output: form_status
input_schema:
- name: first_name
type: string
Expand Down
2 changes: 1 addition & 1 deletion workflows/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "workflow-use"
version = "0.2.9"
version = "0.2.10"
authors = [{ name = "Gregor Zunic" }]
description = "Create, edit, run deterministic workflows"
readme = "README.md"
Expand Down
4 changes: 4 additions & 0 deletions workflows/tests/test_go_back.workflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ steps:
url: https://google.com
- description: Go back to example.com
type: go_back
- description: Extract page title to confirm navigation
type: extract_page_content
goal: Extract the page title and URL to verify that we successfully navigated back to example.com
output: navigation_confirmation
version: 1.0.0
2 changes: 1 addition & 1 deletion workflows/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 10 additions & 4 deletions workflows/workflow_use/healing/prompts/workflow_creation_prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,29 @@ You are a master at building re-executable workflows from browser automation ste

**BEFORE YOU START - THESE RULES ARE MANDATORY:**

1. **NEVER use `agent` steps for simple search/input/click actions!**
1. **ALL workflows MUST end with an extract step!**
- EVERY workflow must have `extract` or `extract_page_content` as the final step
- This is CRITICAL - AI processing is ALWAYS needed at the end
- Even form-filling workflows should extract confirmation/success status
- Example final step: `{{"type": "extract_page_content", "goal": "Extract the confirmation message or success status"}}`

2. **NEVER use `agent` steps for simple search/input/click actions!**
- If you see `input_text` action → Use `input` step with `target_text`
- If you see `click_element` action → Use `click` step with `target_text`
- If you see `send_keys` action → Use `keypress` step
- Agent steps are 10-30x SLOWER and cost money per execution!

2. **ALWAYS use semantic `target_text` for element targeting!**
3. **ALWAYS use semantic `target_text` for element targeting!**
- Look for visible text, labels, placeholders, aria-labels
- Use `{{variable}}` syntax (one pair of curly braces) in `target_text` for dynamic values
- Example: `{{"type": "click", "target_text": "{{repo_name}}"}}`

3. **Variables MUST use {variable} syntax (one pair of curly braces)**
4. **Variables MUST use {variable} syntax (one pair of curly braces)**
- ✅ CORRECT: `"value": "{{email}}"` or `"target_text": "{{repo_name}}"`
- ❌ WRONG: `"value": "{{{{email}}}}"` or `"value": "email"`
- Python's str.format() substitutes {variable} with actual values at runtime

4. **Prefer direct navigation over search engines!**
5. **Prefer direct navigation over search engines!**
- If task involves "search GitHub" → Navigate directly to https://github.com
- If task involves "search Twitter" → Navigate directly to https://twitter.com
- Only use search engines if the target URL is genuinely unknown
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ Review the provided workflow definition and:
- Extract steps without `extractionGoal`
- Key press steps without `key`

6. **Workflow Must End with Extract Step**
- ALL workflows must end with an extract step (`extract` or `extract_page_content`)
- This is CRITICAL because AI processing is always needed at the end
- Even form-filling workflows should extract confirmation/success status
- Example: After submitting a form, add `{"type": "extract_page_content", "goal": "Extract the confirmation message or success status"}`

### Warnings (May Cause Issues)

1. **Generic Target Text**
Expand Down Expand Up @@ -117,6 +123,7 @@ Use these standardized issue types:
- `incorrect_step_type`: Wrong step type for the action
- `invalid_variable`: Variable reference doesn't exist in input_schema
- `missing_required_field`: Required field is missing
- `missing_final_extract`: Workflow doesn't end with extract step (CRITICAL)
- `generic_target_text`: Target text is too generic
- `missing_error_handling`: No conditional logic for errors
- `hardcoded_value`: Value that should be a variable
Expand Down
22 changes: 21 additions & 1 deletion workflows/workflow_use/schema/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Any, Dict, List, Literal, Optional, Union

from pydantic import BaseModel, Field
from pydantic import BaseModel, Field, validator


# --- Base Step Model ---
Expand Down Expand Up @@ -237,6 +237,26 @@ class WorkflowDefinitionSchema(BaseModel):
description='List of input schema definitions.',
)

@validator('steps')
def validate_ends_with_extract(cls, steps: List[WorkflowStep]) -> List[WorkflowStep]:
"""Validate that the workflow ends with an extract step."""
if not steps:
raise ValueError('Workflow must have at least one step')

last_step = steps[-1]
# Check if last step is an extract step
# We need to check the 'type' attribute from the step dict/model
step_type = getattr(last_step, 'type', None)

if step_type not in ['extract', 'extract_page_content']:
raise ValueError(
f'Workflow must end with an extract step (extract or extract_page_content). '
f'Current last step type: {step_type}. '
f'AI processing is always needed at the end of a workflow.'
)

return steps

# Add loader from json file
@classmethod
def load_from_json(cls, json_path: str):
Expand Down
Loading