Skip to content

Commit 63c0106

Browse files
Add files via upload
1 parent d9ec366 commit 63c0106

1 file changed

Lines changed: 244 additions & 1 deletion

File tree

README.md

Lines changed: 244 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,244 @@
1-
# microsoft-webwright-example
1+
# Microsoft WebWright — Google Flights Example
2+
3+
> A reference implementation of the **Microsoft WebWright architecture**.
4+
> Route: **HKG ⇌ CJU** · Depart: **08-Aug-2026** · Return: **14-Aug-2026** · Budget: **HK$20,000**
5+
6+
---
7+
8+
## Project Structure
9+
10+
```
11+
Microsoft-WebWright-Example/
12+
├── env.py # Environment: shell execution, workspace I/O
13+
├── model.py # Model endpoint: OpenAI GPT-4o wrapper
14+
├── run.py # Runner: agent loop, orchestration, logging
15+
├── self_reflection.py # Self-reflection: evaluates critical points post-run
16+
├── requirements.txt # Python dependencies
17+
├── .env # API key (not committed)
18+
├── README.md # This file
19+
├── skills/
20+
│ └── google_flights_comparison.py # Skill: task definition, metadata, workflow steps
21+
├── workspace/ # Agent working directory (created at runtime)
22+
│ ├── flights_report.txt # Final recommendation report (generated)
23+
│ ├── flights_data.json # Structured comparison data (generated)
24+
│ ├── screenshots/ # Browser screenshots captured during run
25+
│ └── run_log_<YYYYMMDD_HHMMSS>.jsonl # Step-by-step agent log (generated)
26+
└── final_runs/ # Promoted artifacts after successful run
27+
└── run_1/
28+
├── final_script.py # The agent's final reusable script
29+
├── final_script_log.txt # Log from the final script execution
30+
├── screenshots/ # Screenshots copied from workspace
31+
└── self_reflect_result.json # Self-reflection evaluation output
32+
```
33+
34+
---
35+
36+
## Skill: `google-flights-comparison`
37+
38+
> *Skill-guided Google Flights comparison for a Hong Kong to Jeju trip.*
39+
> *Shows a generated flight skill being selected and reused as a task-specific workflow.*
40+
41+
The skill is defined in `skills/google_flights_comparison.py` and loaded by `run.py` at startup. It encapsulates all task parameters and the ordered workflow steps the agent follows.
42+
43+
**Skill metadata:**
44+
45+
| Field | Value |
46+
|---|---|
47+
| Route | HKG ⇌ CJU |
48+
| Dates | 08-Aug-2026 → 14-Aug-2026 |
49+
| Budget | HK$20,000 |
50+
| Cabin | Economy · 1 passenger |
51+
| Min options | 3 complete round-trip itineraries |
52+
53+
**Workflow steps:**
54+
55+
| Time | Step | Description |
56+
|---|---|---|
57+
| 00:00 | TASK START | Agent receives the HKG ⇌ CJU prompt with fixed dates, economy class, budget, and min 3 c |
58+
| 01:00 | SETUP: load skill | Agent selects the `google-flights-comparison` skill to run the browser-backed workflow |
59+
| 01:43 | BROWSER TASK START | Browser opens Google Flights scoped to HKG and CJU, form ready for date selection |
60+
| 02:30 | DATA LOAD | First fares appear while prices are still stabilising |
61+
| 03:20 | KEY FINDING | Cheapest nonstop option identified and recorded |
62+
| 03:46 | RETURN SELECTION | Workflow advances to return-leg page, pairs outbound + inbound into itineraries |
63+
| 04:08 | BALANCED OPTION | Identifies a more practical nonstop avoiding very early departures |
64+
| 04:45 | BOOKING SOURCE CHECK | Notes the booking platform (e.g. Agoda, Google Flights direct) |
65+
| 05:20 | COMPARISON OPTION | Third itinerary checked — may be pricier but with a later return |
66+
| 05:56 | TASK END | Recommendation delivered, `flights_report.txt` and `flights_data.json` saved |
67+
68+
---
69+
70+
## Architecture
71+
72+
This project follows the three-component **WebWright** pattern:
73+
74+
```
75+
User Task ——→ | run.py (Runner) |
76+
| • Initialises history with the task |
77+
| • Orchestrates the agent loop |
78+
| • Logs every step to .jsonl |
79+
|
80+
history + observation
81+
82+
| model.py (Model Endpoint) |
83+
| • Wraps OpenAI GPT-4o API |
84+
| • Sends system prompt + history |
85+
| • Returns { thought, action, done } |
86+
|
87+
predicted action (shell cmd)
88+
89+
| env.py (Environment) |
90+
| • Executes commands in workspace/ |
91+
| • Captures stdout / stderr |
92+
| • Reads and writes workspace files |
93+
|
94+
observation
95+
————————————→ back to Runner
96+
```
97+
98+
### Agent Loop — step by step
99+
100+
| Step | Component | What happens |
101+
|---|---|---|
102+
| 1 | `run.py` | Receives the task string, initialises an empty conversation history |
103+
| 2 | `model.py` | Runner sends history → GPT-4o returns `{ thought, action, done }` |
104+
| 3 | `env.py` | Runner passes `action` (a shell command) to `execute_command()` |
105+
| 4 | `env.py` | `capture_observation()` formats stdout + stderr + workspace file listing |
106+
|| `run.py` | Runner logs the step, appends observation to history, goes to step 2 |
107+
|| `run.py` | Loop ends when model sets `done: true` or `MAX_STEPS` (15) is reached |
108+
109+
---
110+
111+
## WebWright Paradigm
112+
113+
> *"The agent can launch multiple browser sessions in terminal."*
114+
115+
Unlike traditional web agents that keep one browser session alive and predict the next click/type/scroll, WebWright separates the agent from the browser session entirely.
116+
117+
| Principle | Description | Implemented in |
118+
|---|---|---|
119+
| **Disposable browsers** | Agent spawns fresh browser sessions, captures screenshots only when useful, inspects failures, and reruns scripts without being trapped in a single stateful page | `execute_command()`, `take_screenshot()` |
120+
| **Code composes actions** | Date selection, form filling, filtering, comparison, and extraction are written as loops and functions — not long chains of primitive browser actions | `write_browser_script()` |
121+
| **Artifacts survive** | The durable output is `workspace/` — exploratory scripts, action logs, screenshots, final outputs, and eventually a reusable task program | `write_workspace_file()`, `workspace/` |
122+
123+
---
124+
125+
## File Reference
126+
127+
### `run.py` — Runner
128+
129+
| Symbol | Purpose |
130+
|---|---|
131+
| `TASK` | Natural-language task string given to the agent |
132+
| `MAX_STEPS` | Hard cap on loop iterations (default: 15) |
133+
| `run()` | Entry point — starts and drives the agent loop |
134+
| `log_step()` | Appends one JSONL line per step to `workspace/run_log_*.jsonl` |
135+
| `promote_to_final_run()` | Copies all workspace artifacts to `final_runs/run_N/` after completion |
136+
| `get_next_final_run_dir()` | Returns the next available `final_runs/run_N/` path |
137+
138+
### `self_reflection.py` — Self-Reflection
139+
140+
| Symbol | Purpose |
141+
|---|---|
142+
| `reflect(task, report, log_entries)` | Calls GPT-4o to evaluate critical points — returns `{ task_completed, critical_points, overall_status, recommendation }` |
143+
| `run_reflection(task, report_path, log_path, output_path)` | Loads report + log, runs reflection, saves `self_reflect_result.json` |
144+
145+
**Self-reflection output schema:**
146+
```json
147+
{
148+
"task_completed": true,
149+
"critical_points": [
150+
{ "point": "flights found", "status": "pass", "detail": "5 outbound, 5 return" },
151+
{ "point": "budget respected", "status": "pass", "detail": "all options under HK$20,000" }
152+
],
153+
"overall_status": "success",
154+
"recommendation": "None — task fully completed."
155+
}
156+
```
157+
158+
### `model.py` — Model Endpoint
159+
160+
| Symbol | Purpose |
161+
|---|---|
162+
| `SYSTEM_PROMPT` | Instructs GPT-4o to act as a web automation agent and respond in JSON |
163+
| `get_next_action(history)` | Calls `gpt-4o` with full history, returns `{ thought, action, done }` |
164+
165+
**Model response schema:**
166+
```json
167+
{
168+
"thought": "reasoning about what to do next",
169+
"action": "python search.py",
170+
"done": false
171+
}
172+
```
173+
174+
### `env.py` — Environment
175+
176+
| Function | Purpose |
177+
|---|---|
178+
| `ensure_workspace()` | Creates `workspace/` directory if it does not exist |
179+
| `execute_command(command)` | Spawns a fresh subprocess in `workspace/` — disposable browser sessions are launched this way |
180+
| `write_browser_script(filename, url, extraction_code)` | Writes a self-contained Playwright script to `workspace/` — agent composes full scripts instead of primitive actions |
181+
| `take_screenshot(script_name, url)` | Spawns a disposable browser, captures a screenshot to `workspace/`, then discards the session |
182+
| `capture_observation(cmd_result)` | Formats command result + workspace file list into an observation string |
183+
| `read_workspace_file(filename)` | Reads a file from `workspace/` |
184+
| `write_workspace_file(filename, content)` | Writes a file to `workspace/` — artifacts persist after the browser session is gone |
185+
| `list_workspace_files()` | Returns list of all files currently in `workspace/` |
186+
187+
### `workspace/` — Agent Working Directory
188+
189+
Created automatically at runtime. Contains:
190+
191+
| File | Description |
192+
|---|---|
193+
| `flights_report.txt` | Final itinerary recommendation written by the agent |
194+
| `run_log_<timestamp>.jsonl` | One JSON line per agent step: `step`, `timestamp`, `thought`, `action`, `observation` |
195+
| *(any scripts)* | Python/shell scripts the agent writes and executes during its run |
196+
197+
---
198+
199+
## Setup
200+
201+
### 1 — Configure API Key
202+
203+
Create a `.env` file in the project root:
204+
```
205+
OPENAI_API_KEY=sk-...
206+
```
207+
208+
### 2 — Install Dependencies
209+
210+
```bash
211+
pip install -r requirements.txt
212+
```
213+
214+
### 3 — Install Playwright Browser
215+
216+
```bash
217+
playwright install chromium
218+
```
219+
220+
### 4 — Run
221+
222+
```bash
223+
python run.py
224+
```
225+
226+
---
227+
228+
## Dependencies
229+
230+
| Package | Version | Purpose |
231+
|---|---|---|
232+
| `openai` | 1.30.0 | GPT-4o API calls in `model.py` |
233+
| `playwright` | 1.44.0 | Browser automation executed by the agent |
234+
| `python-dotenv` | 1.0.1 | Loads `OPENAI_API_KEY` from `.env` |
235+
| `requests` | 2.31.0 | Available to agent-generated scripts |
236+
237+
---
238+
239+
## Output
240+
241+
After a successful run you will find:
242+
243+
- **`workspace/flights_report.txt`** — recommended itinerary within HK$20,000
244+
- **`workspace/run_log_<timestamp>.jsonl`** — full trace of every thought, action, and observation

0 commit comments

Comments
 (0)