Nova UFast Agent ⚡
A browser agent with a dynamic, indexed action space.
Give it one goal. A decision model (TypeSafe) picks an operation and an element in a single request. A small LLM writes text only when the operation is TYPE_TEXT. Every other action is executed by code against real observed DOM nodes — the model never emits selectors, coordinates, or executable JavaScript.
Derived from browser-use/jev-ultrafast (MIT). Rebranded, repackaged, and shipped with a rebuilt local inspector UI.
How it thinks
Every observation produces a fresh element table:
[1] button Change ticket type · Round trip
[2] combobox Where from? · San Francisco
[3] combobox Where to? · empty
[4] textbox Departure · empty
...
The operations are CLICK, TYPE_TEXT, SELECT, SCROLL_UP, SCROLL_DOWN, WAIT, DONE, and BLOCKED. Only supported operations and targets are offered.
one decision request
┌───────────────────────────┐
page → element table → operation │
│ click_target │
│ type_text_target │
│ select_target, if present │
└─────────────┬─────────────┘
use the matching target
│
CLICK [7] ─────┤──→ browser
TYPE_TEXT [3] ─────┘
↓
small LLM → text → browser
Target questions are speculative: if the operation is CLICK, only click_target can execute. Two decisions, one network round trip. Each target head contains only compatible elements. Native dropdown choices carry an observed element/option index.
Quickstart
git clone <your-repo> nova-ufast-agent
cd nova-ufast-agent
uv sync
cp .env.example .env
# Add TYPESAFE_API_KEY and TEXT_MODEL_API_KEY.
uv run nova-ufast
Open http://127.0.0.1:8766 and click Start demo. The inspector shows numbered elements, operation probabilities, target probabilities, and the executed action trail. Choose next pauses before execution.
Chrome connects through Browser Harness, installed by uv sync. Run uv run browser-harness --doctor if it needs connecting. Allow remote debugging in Chrome when prompted.
Use the library
from nova_ufast_agent import Agent
with Agent(
"https://www.google.com/travel/flights?hl=en",
"Find one-way flights from Zurich to London on September 20, 2026, "
"for one adult in economy. Stop when matching flight options are visible.",
) as agent:
for state in agent.run():
print(state["elapsed_ms"], state["status"])
Run with uv run --env-file .env python your_script.py. The same policy can run a different task:
uv run --env-file .env python examples/run.py \
--url https://en.wikipedia.org/wiki/Main_Page \
--goal 'Find and open the Wikipedia article about Gödel’s incompleteness theorems.'
uv run --env-file .env python examples/flights.py --keep-open performs a live Google Flights search, independently checks the resulting route/date/results, and saves its trace. It never selects or books a flight.
Install it as a normal dependency:
uv pip install . # editable: uv pip install -e .
python -m build # or: uv build
Environment
| Variable | Required | Purpose |
|---|---|---|
TYPESAFE_API_KEY |
✅ | Decisions: operation + target heads |
TYPESAFE_MODEL |
– | Default jev-latest |
TEXT_MODEL_API_KEY |
for TYPE_TEXT |
OpenAI-compatible text helper |
TEXT_MODEL_BASE_URL |
– | Default https://api.deepseek.com/v1 |
TEXT_MODEL |
– | Default deepseek-chat |
TEXT_MODEL_REASONING |
– | none disables reasoning on compatible providers |
Credentials stay server-side and .env is git-ignored.
Why it moves
- One request per decision cycle. Operation and target heads share the same observed state.
- No screenshots in the default agent loop. The model consumes structured state; the inspector opts into screenshots.
- One browser call per snapshot. Visible controls, names, values, and text are read atomically with references to the actual DOM nodes.
- Validate the selected target. Clicks re-check the document, form values, target, and nearby context. Geometry is resolved and covered controls are rejected before input.
- Wait for useful state. After typing into a combobox, suggestions are awaited (capped at 200 ms). Other interactions get at most two animation frames or 50 ms.
- Keep hidden tabs rendering. Focus emulation prevents background throttling without switching Chrome's visible tab.
- Send visible text only. Offscreen bodies and footers do not fill the model context.
- Reuse an interrupted text request. A generated value survives a stale-page retry only while the entire text-helper input is unchanged.
Every executed target resolves from an observed node. The executor rechecks freshness and click occlusion. Model output never becomes selectors, coordinates, shell commands, or executable JavaScript. Text-helper output must parse as a small JSON object before typing.
Structure
| File | Job |
|---|---|
nova_ufast_agent/agent.py |
The complete loop and text-helper handoff |
nova_ufast_agent/snapshot.js |
Atomic DOM snapshot, indexed controls, freshness guards |
nova_ufast_agent/browser.py |
Browser connection, current geometry, execution |
nova_ufast_agent/model.py |
Dynamic operation/target heads and text generation |
nova_ufast_agent/questions.py |
Model instructions |
nova_ufast_agent/demo.py |
Local inspector server |
Limits
DONE still requires independent outcome verification. The DOM reader handles common HTML and ARIA controls, not the full accessible-name specification. Shadow roots, frames, canvas, uploads, pop-up tabs, nested scrolling, and arbitrary keyboard widgets are out of scope for this MVP. Owned tabs share the existing Chrome profile.
Development
uv run ruff check .
uv run pytest
node --check nova_ufast_agent/static/app.js
node --check nova_ufast_agent/snapshot.js
uv build
Tests are offline and never call paid APIs.
License
MIT. Original copyright (c) 2026 Browser Use for the upstream jev-ultrafast project, from which this library is derived.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nova_ufast_agent-0.1.0.tar.gz.
File metadata
- Download URL: nova_ufast_agent-0.1.0.tar.gz
- Upload date:
- Size: 35.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1ca5521fa0bc6596ba8845860511663c2ab51e6e996acf65656fbb51b593030e
|
|
| MD5 |
21d575b835cbcff8e16593f60ea1b3c2
|
|
| BLAKE2b-256 |
c448a7a3c6cd3a16419a11283bc641eaabe292fd8e467c6da9f4f7462ba57c34
|
File details
Details for the file nova_ufast_agent-0.1.0-py3-none-any.whl.
File metadata
- Download URL: nova_ufast_agent-0.1.0-py3-none-any.whl
- Upload date:
- Size: 36.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
64bc1f4353554e62e9842a14e653ff64b87dd0c596ab71fd28672a4f6a52d74a
|
|
| MD5 |
fa187f75f924dbfcc1d67cf4d2edc91b
|
|
| BLAKE2b-256 |
40f9984bd604d2581bef3d5d4fe755f9d9703ef375444760972424a37e5910d9
|