WorkArena Benchmark for BrowserGym

repository·main·Indexed 42 days ago

https://github.com/servicenow/workarena

A benchmark suite of browser-based tasks designed to evaluate web agents performing routine knowledge work on the ServiceNow platform. It includes WorkArena-L1 for atomic tasks and WorkArena++ for compositional tasks evaluating planning, reasoning, and memorization. The suite provides tools for knowledge base generation, task validation, and API utilities for managing ServiceNow requests and items.

Tokens
17.1K
Snippets
39
Records
69
Agent score
54%

What's inside WorkArena

  1. Use utility scripts for configuration generation and validation

    main

    The tasks/scripts/ directory contains utility scripts for managing WorkArena task configurations. These scripts are used to:

    1. Generate configurations: Scripts are provided to programmatically create task configurations.
    2. Validate tasks: The validate.py script performs parallel validation of existing configurations against their corresponding tasks to ensure consistency.

    Note: There is one script provided per task type. These scripts are intended for development and maintenance and are not part of the official released package.

  2. Gain access to ServiceNow instances

    main

    WorkArena requires access to gated ServiceNow instances hosted on Hugging Face. Follow these steps to obtain access:

    1. Visit the WorkArena-Instances dataset on Hugging Face.
    2. Complete the access request form and wait for approval.
    3. Ensure your execution environment is authenticated with Hugging Face (e.g., using huggingface-cli login or setting the HUGGING_FACE_HUB_TOKEN environment variable).
    4. If upgrading from a previous installation, unset any existing WorkArena environment variables such as SNOW_INSTANCE_URL.
  3. Manage task lifecycle with setup and teardown

    main

    The AbstractServiceNowTask provides a structured lifecycle for tasks:

    1. setup(page, do_start=True): Configures the Playwright page, sets timeouts, creates a new ServiceNow user with the specified user_roles, injects utility scripts (SNOW_JS_UTILS_FILEPATH), and executes start() if do_start is True.
    2. start(page): Handles authentication via url_login and navigates the browser to the start_url.
    3. teardown(): Performs cleanup. If the task created a user during setup (delete_user_on_teardown is True), this method automatically deletes that user from the ServiceNow instance using the table_api_call on the sys_user table.
  4. How Dashboard Retrieval Tasks work

    main

    Dashboard retrieval tasks follow a specific lifecycle to ensure data is accurately extracted from ServiceNow's Highcharts visualizations:

    1. Initialization: The task is initialized with a seed, a SNowInstance, and an optional fixed_config.
    2. Setup & Goal Generation: The setup_goal method determines the task's objective (e.g., "What is the maximum value in the 'Incident' chart?") based on the sampled configuration.
    3. Page Readiness: The task uses _wait_for_ready to ensure the gsft_main iframe, the Highcharts API, and the WORKARENA_HIGHCHARTS_ALL_LOADED flag are all present.
    4. Data Extraction: The task uses _get_charts to find available charts and _read_chart to extract series data, including labels, counts, and percentages.
    5. Validation: The validate method compares the agent's response against the ground truth extracted from the chart data, supporting various question types like value, max, min, mean, median, and mode.
  5. Use Dashboard Infeasible Catalog Ordering Tasks

    main

    These tasks are designed for evaluating agents on scenarios where they must retrieve information from a ServiceNow dashboard (e.g., finding max, mean, median, or mode values from incident charts) and then attempt to order a specific catalog item. These tasks are labeled as 'infeasible' because the ordering step is intentionally designed to fail or be problematic in the benchmark context.

    Available catalog items for these tasks include:

    • Apple Watch
    • Apple MacBook Pro 15
    • Development Laptop (PC)
    • Loaner Laptop

    Each task class typically follows a pattern of retrieving a statistical value (max, mean, median, or mode) and then attempting an order. Some classes include a WithReason suffix, which sets provide_reason=True, requiring the agent to provide reasoning for its actions.

  6. Use compositional dashboard and catalog tasks

    main

    WorkArena provides compositional tasks that combine dashboard data retrieval with service catalog ordering. These tasks typically follow a pattern: retrieve a specific metric (max, mean, median, or mode) from a dashboard chart related to incidents, and then use that information to order a specific item from the service catalog.

    Common task families include:

    • Max Order Tasks: Uses SingleChartMinMaxRetrievalTask to find a maximum value and then orders an item.
    • Mean/Median/Mode Order Tasks: Uses SingleChartMeanMedianModeRetrievalTask to compute statistical metrics from dashboard data before ordering.

    Available catalog items for these tasks include:

    • Developer Laptop (Mac)
    • iPad mini
    • iPad pro
    • Sales Laptop
    • Standard Laptop
    • Apple Watch
    • Apple MacBook Pro 15
    • Development Laptop (PC)
    • Loaner Laptop
  7. Use Dashboard-to-Catalog Infeasible Tasks

    main

    Infeasible tasks are designed to evaluate how agents handle scenarios where a requested action (like ordering a specific catalog item) cannot be completed based on information retrieved from a ServiceNow dashboard. These tasks typically follow a pattern:

    1. Retrieve Information: The agent analyzes a dashboard (using classes like SingleChartMinMaxRetrievalTask or SingleChartMeanMedianModeRetrievalTask) to answer a question (e.g., 'max', 'mean', 'median', 'mode') regarding incidents.
    2. Attempt Action: The agent then attempts to order a specific item from the Service Catalog (e.g., 'Developer Laptop (Mac)', 'iPad mini', 'Sales Laptop').
    3. Handle Infeasibility: Because the task is marked as 'infeasible', the agent must navigate the constraints of the environment.

    Common task variations include:

    • ...InfeasibleTask: The base task for a specific item.
    • ...InfeasibleWithReasonTask: A variation that requires the agent to provide a reason for its actions or failure.
    • ...MaxOrder...Task: Specifically targets the 'max' value from dashboard charts.
    • ...MeanOrder...Task: Specifically targets the 'mean' value.
    • ...MedianOrder...Task: Specifically targets the 'median' value.
    • ...ModeOrder...Task: Specifically targets the 'mode' value.
  8. Configure WorkArena installation behavior

    main

    The installation process can be managed using the following modes:

    • Fresh Install: Triggered by the --fresh flag. This clears existing installation progress and resets report filters (via patch_report_filters(fresh=True)) to ensure a clean state.
    • Resumed Install: Triggered by the --resume flag or by choosing the resume option during the interactive prompt. This skips steps that are already marked as completed in the installation progress tracker.
    • Interactive Mode: If neither --fresh nor --resume is provided, the CLI will check for existing progress and prompt the user to either [r]esume or [s]tart fresh.
  9. Run a demo of WorkArena-L1 (Atomic Tasks)

    main

    WorkArena-L1 consists of atomic tasks covering main ServiceNow UI components. The following example uses the env.task.cheat() method to automatically solve tasks using Playwright.

    Note: To evaluate a real agent instead of using the oracle/cheat function, you must use env.step() instead of env.task.cheat().

    import random
    
    from browsergym.core.env import BrowserEnv
    from browsergym.workarena import ATOMIC_TASKS
    from time import sleep
    
    
    random.shuffle(ATOMIC_TASKS)
    for task in ATOMIC_TASKS:
        print("Task:", task)
    
        # Instantiate a new environment
        env = BrowserEnv(task_entrypoint=task,
                        headless=False)
        env.reset()
    
        # Cheat functions use Playwright to automatically solve the task
        env.chat.add_message(role="assistant", msg="On it. Please wait...")
        cheat_messages = []
        env.task.cheat(env.page, cheat_messages)
    
        # Send cheat messages to chat
        for cheat_msg in cheat_messages:
            env.chat.add_message(role=cheat_msg["role"], msg=cheat_msg["message"])
    
        # Post solution to chat
        env.chat.add_message(role="assistant", msg="I'm done!")
    
        # Validate the solution
        reward, stop, message, info = env.task.validate(env.page, cheat_messages)
        if reward == 1:
            env.chat.add_message(role="user", msg="Yes, that works. Thanks!")
        else:
            env.chat.add_message(role="user", msg=f"No, that doesn't work. {info.get('message', '')}")
    
        sleep(3)
        env.close()
  10. Run a demo of WorkArena++ (L2/L3 Tasks)

    main

    WorkArena++ (L2/L3) contains compositional tasks that evaluate planning, reasoning, and memorization. Use get_all_tasks_agents to sample tasks.

    Note: This example uses the oracle/cheat function. For agent evaluation, use env.step().

    import random
    
    from browsergym.core.env import BrowserEnv
    from browsergym.workarena import get_all_tasks_agents
     
    AGENT_L2_SAMPLED_SET = get_all_tasks_agents(filter="l2")
     
    AGENT_L2_SAMPLED_TASKS, AGENT_L2_SEEDS = [sampled_set[0] for sampled_set in AGENT_L2_SAMPLED_SET], [
        sampled_set[1] for sampled_set in AGENT_L2_SAMPLED_SET
    ]
    from time import sleep
    
    for (task, seed) in zip(AGENT_L2_SAMPLED_TASKS, AGENT_L2_SEEDS):
        print("Task:", task)
    
        # Instantiate a new environment
        env = BrowserEnv(task_entrypoint=task,
                        headless=False)
        env.reset()
    
        # Cheat functions use Playwright to automatically solve the task
        env.chat.add_message(role="assistant", msg="On it. Please wait...")
        
        for i in range(len(env.task)):
            sleep(1)
            env.task.cheat(page=env.page, chat_messages=env.chat.messages, subtask_idx=i)
            sleep(1)
            reward, done, message, info = env.task.validate(page=env.page, chat_messages=env.chat.messages)
       
        if reward == 1:
            env.chat.add_message(role="user", msg="Yes, that works. Thanks!")
        else:
            env.chat.add_message(role="user", msg=f"No, that doesn't work. {info.get('message', '')}")
    
        sleep(3)
        env.close()