Skip to main content

Overview

Since remote desktops maintain state between workflow runs, you need to consider how multiple workflows interact. This guide covers best practices for managing stateful environments.

Understanding Desktop State

Unlike stateless APIs, desktop environments persist:
  • Open applications remain open
  • Login sessions stay active
  • Downloads accumulate
  • Window positions don’t reset
A workflow might start with the desktop in an unexpected state from a previous run.

Designing for State

Assume Nothing About Initial State

Always verify the starting state:
from nen import Agent
from pydantic import BaseModel

class Params(BaseModel):
    ...

class Result(BaseModel):
    ...

def run(params: Params) -> Result:
    agent = Agent()
    # Check if we're on the expected screen
    if not agent.verify("Is the dashboard visible?", timeout=5):
        # Navigate to starting point
        agent.execute("Close all open windows")
        agent.execute("Open the application from the start menu")
        agent.verify("Is the login screen visible?", timeout=15)

Create Idempotent Workflows

Design workflows that work regardless of starting state:
def run(params: Params) -> Result:
    agent = Agent()
    # Always navigate from a known starting point
    agent.execute("Go to Home screen")
    agent.verify("Is the home screen visible?")

    # Now proceed with the actual task
    agent.execute("Navigate to Reports")

Clean Up After Completion

Leave the desktop in a predictable state:
def run(params: Params) -> Result:
    agent = Agent()
    try:
        # Main workflow logic
        agent.execute("Generate the report")
        data = agent.extract("Extract report data", ReportSchema.model_json_schema())

    finally:
        # Always clean up
        agent.execute("Close the current window")
        agent.execute("Return to home screen")

    return Result.model_validate(data)

Best Practices Summary

PracticeDescription
Verify initial stateCheck screen before acting
Navigate explicitlyDon’t assume current location
Clean up on exitReturn to known state
Use try/finallyEnsure cleanup runs
Isolate workflowsConsider dedicated deployments