Skip to content

Repository files navigation

WebOperator: Action-Aware Tree Search for Autonomous Agents in Web Environment

🌐 Website📃 Paper💻 Code

WebOperator

📖 Abstract

LLM-based agents often operate in a greedy, step-by-step manner, selecting actions solely based on the current observation without considering long-term consequences or alternative paths. This lack of foresight is particularly problematic in web environments, which are only partially observable—limited to browser-visible content (e.g., DOM and UI elements)—where a single misstep often requires complex and brittle navigation to undo. Without an explicit backtracking mechanism, agents struggle to correct errors or systematically explore alternative paths. Tree-search methods provide a principled framework for such structured exploration, but existing approaches lack mechanisms for safe backtracking, making them prone to unintended side effects. They also assume that all actions are reversible, ignoring the presence of irreversible actions—limitations that reduce their effectiveness in realistic web tasks. To address these challenges, we introduce WebOperator, a tree-search framework that enables reliable backtracking and strategic exploration. Our method incorporates a best-first search strategy that ranks actions by both reward estimates and safety considerations, along with a robust backtracking mechanism that verifies the feasibility of previously visited paths before replaying them, preventing unintended side effects. To further guide exploration, WebOperator generates action candidates from multiple, varied reasoning contexts to ensure diverse and robust exploration, and subsequently curates a high-quality action set by filtering out invalid actions pre-execution and merging semantically equivalent ones. Experimental results on WebArena and WebVoyager demonstrate the effectiveness of WebOperator. On WebArena, WebOperator achieves a state-of-the-art 54.6% success rate with gpt-4o, underscoring the critical advantage of integrating strategic foresight with safe execution.

📊 Results on WebArena Benchmark

AgentModelOverall (#812)Reddit (#106)GitLab (#180)Shopping (#187)CMS (#182)Map (#109)Multisite (#48)
BrowserGymgpt-415.020.219.017.214.825.5-
LM-TSgpt-4o19.211.313.927.816.526.616.7
Go-Browseqwen-2.5-7b22.630.715.322.425.317.9-
AWMgpt-435.550.931.830.829.143.3-
Branch-n-Browsegpt-4o35.850.936.734.626.446.818.8
WebPilotgpt-4o37.265.139.436.924.733.9-
AgentOccamgpt-4-turbo45.767.043.346.238.952.316.7
AgentSymbioticclaude-3.552.166.051.048.049.060.029.0
ScribeAgentgpt-4o53.073.759.745.837.956.3-
WebOperatorgpt-4o54.5676.4252.7849.2054.9555.2431.25

Experimental trajectories:

📂 Project Structure

.
├── weboperator/ # Source code for the web agent
├── webshepherd/ # Source code for the Process Reward Model
├── browsergym/ # Source code for the web environment simulator
├── gobrowse/ # Source code for the experience retrieval module
└── README.md

⚙️ Installation

1️⃣ Clone the repository

git clone https://github.com/kagnlp/WebOperator.git
cd WebOperator

2️⃣ Create environment

conda create -n weboperator_env python=3.12
conda activate weboperator_env
# or using pip and virtualenv (if python3.12 is the system python)
python -m venv weboperator_env
source weboperator_env/bin/activate # On Windows use `weboperator_env\Scripts\activate`

3️⃣ Install dependencies

Refer to the Running with Docker section if you don't have admin rights to install Playwright dependencies.

pip install -r requirements.txt
playwright install chromium --with-deps # Need admin rights

4️⃣ Set up environment variables

Create a .env file by copying the example configuration:

cp .env.example .env

Then open the .env file and update any necessary values (such as API keys, website urls) according to your environment.

🚀 Usage

Run the Demo

python demo.py

or

python run.py --config weboperator/configs/demo.yml

🐳 Running with Docker

Useful if you don't have admin rights to install Playwright dependencies. No need to create a virtual environment or install dependencies.

docker compose run --user $(id -u) weboperator --config weboperator/configs/demo.yml

Skeleton Code

Boilerplate code (demo.py) to run WebOperator on an interactive, open-ended task:

importgymnasiumasgymimportbrowsergym.core# register the openended task as a gym environmentfromweboperator.tree_search_agentimportTreeSearchAgentfromweboperator.action_generatorimportActionGeneratorfromweboperator.models.openrouterimportOpenRouterModel# start an openended environmentenv=gym.make(
"browsergym/openended",
task_kwargs={"start_url": "https://map.google.com/"}, # starting URLwait_for_user_message=True, # wait for a user message after each agent message sent to the chatheadless=False
)
# Create an agentaction_generator=ActionGenerator(
model=OpenRouterModel("openai/gpt-oss-20b:free") # Set OPENROUTER_API_KEYS in .env file
)
agent=TreeSearchAgent(
chat_mode=True,
action_generator=action_generator,
)
# run the environment <> agent loop until terminationobs, info=env.reset()
whileTrue:
preprocessed_obs=agent.obs_preprocessor(obs) # Preprocess observationaction=agent.get_action(preprocessed_obs, env) # Decide actionobs, reward, terminated, truncated, info=env.step(action) # Act and Observeifterminatedortruncated:
break# release the environmentenv.close()

Sample Output

Open-ended + Google Maps

Screenshot

🎯 Benchmarks

WebArena Setup

Before running WebArena experiments, you must host the WebArena websites and configure the corresponding endpoints.

Host Websites (choose one):

Set Environment Variables:

PUBLIC_HOSTNAME=<YOUR_SERVER_DOMAIN_OR_IP>export WA_SHOPPING=http://${PUBLIC_HOSTNAME}:7770
export WA_SHOPPING_ADMIN=http://${PUBLIC_HOSTNAME}:7780/admin
export WA_REDDIT=http://${PUBLIC_HOSTNAME}:9999
export WA_GITLAB=http://${PUBLIC_HOSTNAME}:8023
export WA_GITLAB_IP=${PUBLIC_HOSTNAME}export WA_WIKIPEDIA=http://${PUBLIC_HOSTNAME}:8888/wikipedia_en_all_maxi_2022-05/A/User:The_other_Kiwix_guy/Landing
export WA_MAP=http://${PUBLIC_HOSTNAME}:3000

Inference

Run the agent on each benchmark using the corresponding configuration file.

  • WebArena

    python run.py --config weboperator/configs/wa-gpt-4o.yml
  • WebVoyager

    python run.py --config weboperator/configs/wv-gpt-4o.yml

Evaluation

Move the inference outputs and compute benchmark scores.

  • WebArena

    python -m utils.move_exp --src_dir results/webarena/gpt-4o --dst_dir experiments/webarena/gpt-4o
    python -m utils.eval_exp --results_dir experiments/webarena/gpt-4o --task_type webarena 
  • WebVoyager

    python -m utils.move_exp --src_dir results/webvoyager/gpt-4o --dst_dir experiments/webvoyager/gpt-4o
    python -m utils.eval_exp --results_dir experiments/webvoyager/gpt-4o --task_type webvoyager 

⚙️ Agent Configuration Explanation

Environment

env:
task_type: "openended"# ["webarena", "webvoyager", "openended"]max_steps: 100# Maximum steps per episode (For BrowserGym)headless: false # false: show browser UI; true: hide browser UI

Experiment

experiment:
results_dir: "./results/openended/gpt-oss-20b"# Directory to save results. Give relative path.

Agent

agent:
allow_unauthorized_page: true # Whether allow visit to pages outside the benchmark domain

Models

models: # List of models used in the agentaction_model: # Unique identifier of the modeltype: "OpenRouterModel"# Options: ["OpenAIModel", "AzureOpenAIModel", "OpenRouterModel", "OpenHFModel"]model_name: "openai/gpt-oss-20b:free"reward_model:
type: "AzureOpenAIModel"model_name: "gpt-4o"temperature: 1.0

Agent Components

components:
action_validator: # Optional: Action validator configurationallow_invalid_action: false # Whether to allow semantically invalid actions (Default: false)allow_invalid_page: false # Whether to allow navigation to invalid pages (Default: false)observation_processor: # Observation processor configurationoptimized: true # true: use full or visible-only observation based on the observation size. false: always use visible-only observationtruncate_error_message: true # Truncate long error messagesaction_processor: # Action processor configurationmerge_strategy: "sum"# ["sum", "max", "none"]: strategy to merge semantically similar actions. "none": do not merge.recovery_assistant: # Optional: Recovery assistant configurationrecover_from_invalid_page: true # true: forcefully go_back or tab_close when on invalid pagerecover_from_captcha: true # Whether to allow human intervention for captcha recoverybacktrack_manager: # Optional: Enables backtracking mechanismdestruction_aware: true # Whether to re-root the tree after executing destructive actionssimulation_verified: true # Whether to do snapshot-validation or notaction_selector: # Action selection strategy configurationselection_strategy: "action-aware"# options: ["highest-reward", "action-aware"]search_budget: 4# Frontier budgetn_candidates: 2# Number of solution candidates to considermax_depth: 20# Maximum search depthmax_steps: 20# Maximum steps (excluding backtracking steps)rephraser: # Optional: Enables instruction rephrasermodel: "action_model"# Model used for rephrasing instructionsretriever: # Optional: Enables examples retriever (Set RETRIEVER_API_SERVER in environment variables)type: "faiss"# ["faiss", "bm25"]model: "all-MiniLM-L6-v2"# Sentence transformer model (for faiss retriever)top_k: 5# Number of examples to retrievejudge: # Reward and checklist model configuration. Note: Applicable only for multiple action candidatesprompt_type: "web_operator"# Options: likert_scale, web_shepherd, web_operatorchecklist_model: "reward_model"# Model used for checklist generationreward_model: "reward_model"# Model used for reward estimationaction_generator:
max_retry: 5# Maximum retries for generating syntactically and semantically valid actionsfull_action_space: # List of all possible actions
- "click"
- "fill"
- "select_option"
- "goto"
- "go_back"
- "go_forward"
- "scroll"
- "new_tab"
- "tab_focus"
- "tab_close"
- "stop"action_space_type: "adaptive"# options: ["fixed", "adaptive"]candidates: # List of action generator candidates
- name: "simple_action_generator"# Unique name for the candidatemodel: "action_model"# Model to use history_length: 5# Number of previous steps to include in the contextrephraser: false # Whether to include rephrased task instructionretriever: false # Whether to include retrieved examples
- name: "action_generator_w_retriever"model: "action_model"history_length: 3rephraser: falseretriever: true
- name: "action_generator_w_rephraser"model: "action_model"history_length: 4rephraser: trueretriever: false

📝 Citation

Please cite our paper:

@article{dihan2025weboperator,
title={WebOperator: Action-Aware Tree Search for Autonomous Agents in Web Environment},
author={Dihan, Mahir Labib and Hashem, Tanzima and Ali, Mohammed Eunus and Parvez, Md Rizwan},
journal={arXiv preprint arXiv:2512.12692},
year={2025}
}

Releases

Packages

Contributors

Languages