Skip to main content
As you build your workflow in the editor, a productionize agent runs in the background and automatically generates an executable Python file in workspace/flow.py from your scratch_work/*.py files and conversation history. This is the file executed in production runs.

Productionizing the flow

The productionize agent auto-triggers to run every two TODOs and also after all TODOs are completed. You can view production agent logs in the editor. Production logs You can also manually trigger the production agent to save your work. We recommend doing this before closing a session if you have made important edits. Auto-productionize

Running production flows

The workspace/flow.py file is executed by a lightweight “workflow runner” agent when running a production workflow session. This workflow runner agent has self-healing capabilities to handle minor page changes, including longer page load times, scrolling if element placements have changed, and handling popups. For major changes (i.e. page is down or has changed completely), the workflow runner agent will return a Failed status. You can view session replay and logs to see what happened and edit the workflow to account for the changes.

How flow.py is structured

Flows are built to be resilient to changes in test data and changes to the page.

Variables

For security reasons and to ensure the file handles a large distribution of test data, production flows do not hard code sensitive data or variables.
workspace/flow.py
import asyncio
import json
from servers.browser_tools import click, type

async def main():
    with open("/home/chrome_user/agent/data/variables.json", "r") as f:
        variables = json.load(f)

    await click(selector="input#caLicense")
    await type(text=variables["Medical License"])

asyncio.run(main())
For dropdowns that are fully loaded on page start, the agent builds a dropdown mapping in workspace/dropdown_mappings.json that it references in code.
workspace/dropdown_mappings.json
"cures_status": {
    "type": "native_select",
    "container": "select#curesStatus",
    "options": {
        "active - registered": "Active - Registered",
        "pending registration": "Pending Registration",
        "exempt from cures": "Exempt from CURES"
    }
}
The production flow then uses these mappings to select from the dropdown.
workspace/flow.py
import asyncio
import json
from servers.browser_tools import select_option

async def main():
    with open("/home/chrome_user/agent/workspace/dropdown_mappings.json", "r") as f:
        mappings = json.load(f)

    cures_mapping = mappings["cures_status"]
    await select_option(selector=cures_mapping["container"], label="Active - Registered")

asyncio.run(main())
For lazy loading and searchable dropdowns where the full content is unknown, the agent falls back to using has-text as a selector:
workspace/flow.py
import asyncio
import json
from servers.browser_tools import click, type

async def main():
    with open("/home/chrome_user/agent/data/variables.json", "r") as f:
        variables = json.load(f)

    with open("/home/chrome_user/agent/workspace/dropdown_mappings.json", "r") as f:
        mappings = json.load(f)

    payer_mapping = mappings["payer"]
    await type(text=variables["payer"])
    await click(selector=f'{payer_mapping["option_selector"]}:has-text("{variables["payer"]}")')

asyncio.run(main())

Popups

If the agent encounters popups during editing or in a production run, it automatically dismisses them and adds handling to the production flow.
workspace/flow.py
import asyncio
from servers.browser_tools import click

async def try_click(selector):
    """Click element if present, ignore if not (for popups/modals)."""
    try:
        await click(selector=selector)
    except Exception:
        pass

async def main():
    await try_click("button#onetrust-accept-btn-handler")

asyncio.run(main())

Structured outputs

Define and prompt the agent to use structured output schemas. Learn more about structured outputs.
workspace/flow.py
import asyncio
from servers.browser_tools import set_structured_output

async def main():
    await set_structured_output(key="form_result", value="SUBMITTED")

asyncio.run(main())