Skip to main content

This repository contains the code for the A3 framework, which uses LLMs to systematically generate synthetic web agent training data by decomposing the annotation process into three roles: Task Designer, Annotator, and Supervisor.

Installation

pip install agent-as-annotators

Or install from source:

git clone https://github.com/McGill-NLP/agent-as-annotators.git
cd agent-as-annotators
pip install -e .

Quick Start: Evaluation

1. Serve a model with vLLM

vllm serve --config configs/vllm/Qwen3.5-9B.yaml

2. Run evaluation

a3-eval --benchmark webarena_test --model A3-qwen3.5-9b

Pipeline: Generating A3-Synth

The A3 pipeline generates synthetic training data in 5 steps:

Step 1: Create personas

python scripts/create_personas.py

Step 2: Generate task intents (via exploration)

# 2a. Build the exploration.tasks.json config that a3-explore consumes.
# One task per (persona, site) pair, written to
# agent_as_annotators/configs/<exploration_model>/exploration.tasks.json so
# that a3-explore picks it up via importlib.resources.
python scripts/generate_exploration_tasks.py -m <exploration-model>

# 2b. Run the exploration agent. Trajectories are saved as agentlab pickles
# under $AGENTLAB_EXP_ROOT/<study_dir>/<task_dir>/step_*.pkl.gz.
a3-explore

# 2c. Extract chat messages from each step pickle into a parallel JSON tree
# at outputs/chat_messages/<study_dir>/<task_dir>/step_*.json.
python scripts/extract_chat_messages.py --find-latest <exploration-model>

# 2d. For each trajectory, randomly sample N steps (default 3, skipping step 0),
# append the TASK_INTENT_PROMPT_TEMPLATE as a final user turn, and write each
# prompt as outputs/task_intents/prompts/<exploration_model>/task_<i>.step_<j>.json.
python scripts/prepare_tasks_intents_prompts.py --find-latest <exploration-model>

# 2e. Send each prepared prompt to the Task Designer LLM. Completions land in
# outputs/task_intents/completions/<exploration_model>/<task_designer_model>/.
python scripts/generate_task_intents.py \
    --exploration-model <exploration-model> \
    --model <task-designer-model>

What exactly gets passed to the Task Designer

One exploration step, not the whole trajectory. Each prepared prompt is the exploration agent's own prompt/response pair at a single sampled step, with one user turn appended. For the released gemini-3-pro-preview run that is exactly four messages:

# role content
0 system the exploration agent's system prompt
1 user the agent's step prompt, as a text part plus the screenshot of that step (image_url). The text holds # Instructions, ## Goal: (the exploration instruction and the persona), # Observation of current step: (open tabs, AXTree, focused element), # History of interaction with the task:, # Action space: and the formatting examples
2 assistant what the explorer actually produced at that step (<thought>…</thought><action>…</action>)
3 user appended by prepare_tasks_intents_prompts.py: TASK_INTENT_PROMPT_TEMPLATE.format(annotator_instructions=WEBARENA_ANNOTATOR_INSTRUCTIONS, num_intents=…)

So the Task Designer sees the AXTree and screenshot of the sampled step only. Earlier steps reach it solely through the agent's # History of interaction with the task: block, which lists past actions and nothing else (## step 0 <action>click('156')</action> …) — no earlier observations, and no multi-turn chat history.

How exploration_step_num is chosen

prepare_tasks_intents_prompts.py globs step_*.json in each trajectory, sorts by step number, drops step_0, and takes a uniform random sample without replacement:

random.seed(seed)                                     # --seed, default 42
sampled = random.sample(step_files, min(num_samples, len(step_files)))

Each sampled step becomes one prompt file task_<task_num>.step_<step_num>.json, and that step_num is what scripts/create_synth_configs.py records as exploration_step_num in the A3-Synth task configs. The released run used the defaults --num_samples 3, --num_intents 2, --seed 42, which is why exploration_step_num in A3-Synth is never 0, is capped at the exploration budget of 20 steps, and appears at most three times per exploration trajectory.

Known wart, kept for reproducibility. A trajectory's terminal step records no agent call, so it extracts to messages: [] and, if sampled, yields a prompt whose only turn is the appended instruction — the Task Designer is asked to write tasks "based on the conversation above" with no conversation above. This affected 381 of 4497 prompts (8.5%) in the released run. The default behaviour is unchanged so that generation reproduces exactly; pass --skip-empty-steps to exclude those steps in new collections.

Step 3: Create A3-Synth task configs

python scripts/create_synth_configs.py

Step 4: Collect trajectories

a3-synth --benchmark a3_synth --model gemini-3-pro

Step 5: Convert to training data

python scripts/convert_trajectories_to_json.py
python scripts/generate_rft_data.py

Training

a3-train --config configs/train/qwen3.5-9b.json

Training uses SFT with FSDP for multi-GPU parallelism. See configs/train/ for hyperparameters and configs/accelerate/ for FSDP configuration.

Reproducing Dataset Statistics

The A3-Synth website-state coverage, instruction-diversity, and frequent-page statistics can be reproduced with a standalone standard-library script:

python3.12 scripts/analyze_a3_synth.py data/A3-Synth/training/train.jsonl

See the methodology and data instructions for the exact definitions and a machine-readable output option.

To reproduce the full-benchmark Wilson confidence intervals and exact paired McNemar tests, install the analysis dependency, place the base and A3 AgentLab study directories under agentlab_results/, and run:

pip install -e '.[analysis]'
python scripts/analyze_evaluation_significance.py \
  --results-root agentlab_results

CLI Commands

Command Description
a3-eval Run evaluation on WebArena, VisualWebArena, WorkArena, MiniWoB
a3-synth Run trajectory collection for A3-Synth
a3-explore Run environment exploration
a3-train Fine-tune a model with SFT
a3-screen-utils Screen session management utilities

Project Structure

agent-as-annotators/
  agent_as_annotators/       # Core package
    cli/                     # CLI entry points (eval, synth, explore, train)
    modeling.py              # Agent model wrapper (vLLM, Gemini, OpenAI)
    prompts/                 # All prompt templates
    judge/                   # Inverted evaluation protocol (Judge module)
    benchmarks/a3_synth/     # A3-Synth benchmark registration
    exploration/             # Exploration task registration
    utils/                   # Utilities
    configs/a3_synth/        # A3-Synth task configurations
  configs/
    model_configs.json       # Model registry
    train/                   # Training hyperparameters
    vllm/                    # vLLM serving configs
    accelerate/              # FSDP configs
  scripts/                   # Data pipeline scripts

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agent_as_annotators-0.1.1.tar.gz (78.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

agent_as_annotators-0.1.1-py3-none-any.whl (85.3 kB view details)

Uploaded Python 3

File details

Details for the file agent_as_annotators-0.1.1.tar.gz.

File metadata

  • Download URL: agent_as_annotators-0.1.1.tar.gz
  • Upload date:
  • Size: 78.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for agent_as_annotators-0.1.1.tar.gz
Algorithm Hash digest
SHA256 3f1eefcb8d1cb277b1ec4df145c67bdb6eda3cc074fbcf165830e4a9dcc96c19
MD5 e3d960e2a04457ee78df3cce6b7d0a7f
BLAKE2b-256 8f388ad084a84919f580f9dfffafe2aa668eece9046ef3986ca5a0049ff2b5e6

See more details on using hashes here.

File details

Details for the file agent_as_annotators-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for agent_as_annotators-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 8e303864ac8b0ae11f78ae2dbe62dbdf2114268154a236a035e9c2dd54d3e011
MD5 0ba8aac80d3e436f53a6ab4fb6b5d7b6
BLAKE2b-256 81d315bab7d4ab2b7a0b86d92602743dca833600d236ab1b986750cde517b3a0

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 files

0.1.0

2 files

0.0.1

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page