Polanyi
Synthetic shoppers hard-pinned to any website → recommendation-system event logs.
Point Polanyi at a URL. It runs a diverse set of Nemotron personas as on-site shoppers (search, compare, select, stop before PII/payment) and emits privacy-safe recsys_events for offline experiments.
Install
pip install polanyi
From source:
cd polanyi_agent_harness
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
Colab / product path (POLANYI_API_KEY)
- Sign up at https://polanyilabs.com/signup, verify your email, and create a key in the dashboard.
- In Colab:
!pip install -q "polanyi>=0.4.2"
import os
os.environ["POLANYI_API_KEY"] = "pk_live_..." # from your dashboard
from polanyi import Client
result = Client().simulate(site="https://www.nike.com", n=3)
While it runs you get live text progress: each step, each shopper as they're cast and as they finish, and a spinning braille Polanyi sphere next to the status line. When it finishes, Colab downloads a zip with:
| File | Contents |
|---|---|
personas.json |
Every persona used: demographics, interests, and the journey each was given |
recsys_events.jsonl |
All recsys events from all shoppers, merged |
summary.json |
Run summary |
The same files are in result.output_dir (default output/<site>_<timestamp>/), plus one folder per shopper.
Shoppers run in parallel: concurrency defaults to min(n, 5); pass e.g. concurrency=10 to go faster.
import pandas as pd
events = pd.read_json(result.events_jsonl, lines=True)
personas = pd.read_json(result.personas_json)
If the Colab runtime resets, fetch a finished run again with Client().fetch("sim_...").
Options: progress=False hides the progress output, download=False skips the browser download.
Local / power-user path (BROWSER_USE_API_KEY)
cp .env.example .env
# BROWSER_USE_API_KEY=bu_...
from polanyi import Client
client = Client() # uses Browser Use Cloud directly
result = client.simulate(
site="https://www.expedia.com",
n=10,
concurrency=5,
output_dir="runs/expedia",
)
print(result.summary())
# runs/expedia/personas.json and runs/expedia/recsys_events.jsonl are written automatically
Agents are hard-pinned: they start on your site and must not leave that domain. External “Book with…” handoffs stop with checkout_boundary_stop (first-party-shaped data).
Accounts and API keys
Accounts, keys and usage live in Supabase (schema: supabase/migrations/ in the website repo).
- Users sign up on the website (email + password with a 6-digit verification code, or Google).
- In the dashboard they create, name and revoke
pk_live_…keys. A key is shown once; only its SHA-256 hash is stored. - This server authorizes each request with the Supabase service-role key, enforces the user's
monthly_persona_limit(default 100 personas/month), and records every simulation inusage_records. Simulations are private to the account that created them.
Server env (Fly):
fly secrets set -a polanyi \
SUPABASE_URL="https://<project>.supabase.co" \
SUPABASE_SERVICE_ROLE_KEY="<service_role key>" \
POLANYI_DAILY_PERSONA_CAP=300
POLANYI_DAILY_PERSONA_CAP is a global safety limit across all users (optional).
POLANYI_MAX_CONCURRENCY (default 10) caps parallel browsers per simulation, whatever the client asks for.
To raise one user's quota, edit profiles.monthly_persona_limit in the Supabase table editor.
Legacy: POLANYI_API_KEYS (comma-separated) and POLANYI_ADMIN_TOKEN + POST /v1/admin/keys
still work for internal keys stored in POLANYI_DATA_DIR/api_keys.json.
Docker:
docker build -t polanyi-api .
docker run --rm -p 8080:8080 \
-e POLANYI_API_KEYS=pk_live_... \
-e BROWSER_USE_API_KEY=bu_... \
polanyi-api
API surface:
| Method | Path | Purpose |
|---|---|---|
GET |
/health |
Liveness |
POST |
/v1/simulations |
Start a job (Bearer pk_…) |
GET |
/v1/simulations/{id} |
Poll status + events |
CLI
# Any site, N diverse personas
polanyi-sim --site https://www.nike.com --batch 5 --concurrency 5 \
--output-dir output/nike_run
# Optional journey brief
polanyi-sim --site expedia.com --batch 10 --concurrency 10 \
--prompt "Browse hotels and flights; pick what fits your budget." \
--output-dir output/expedia_run
# Dry-run (personas only, no Browser Use)
polanyi-sim --site example.com --batch 3 --dry-run-persona --output-dir output/dry
Legacy (no --site) still works but is not hard-pinned.
Outputs
Each session directory contains:
| File | Purpose |
|---|---|
persona.json |
Synthetic identity |
browser_use_raw.json |
Raw Browser Use run |
recsys_events.jsonl / .parquet |
Ordered recsys events |
simulate_meta.json |
Site + run config (SDK / --site runs) |
simulate_plan.json |
Inferred vertical + per-persona journey goals |
How journeys are planned
Live runs (Client.simulate / polanyi-sim --site without --dry-run-persona):
- LLM diagnosis — a Browser Use agent opens the real site and returns an accurate JSON profile (
site_name,vertical,description,journey_templates) - Saved to
simulate_diagnosis.json - Each persona gets a different template from that diagnosis, personalized with their location/budget
Dry-runs skip the LLM and fall back to URL heuristics only.
from polanyi import diagnose_site, plan_journeys
from polanyi.personas import load_personas
diagnosis = diagnose_site("https://www.ticketnetwork.com")
print(diagnosis.site_name, diagnosis.vertical)
print(diagnosis.description)
plan = plan_journeys("https://www.ticketnetwork.com", load_personas(count=3), diagnosis=diagnosis)
Safety
- Synthetic actor IDs only (
syn_nmusa_*) training_use=offline_sandbox_only- Hard stop before identity / payment
- Hard site pin (first-party shaped)
Publish to PyPI
pip install build twine
python -m build
twine upload dist/*
The polanyi name is available on PyPI as of packaging time.
Roadmap
Schema, personas, Cloud runner, batch concurrencyPython SDKClient.simulate(site=…)+ hard pinLLM site diagnosis → diverse per-persona journeysPOLANYI_API_KEY+ self-hostable API wrapping Browser Use- Parse quality gates + JSON repair for agent output
- Hosted
api.polanyi.ai+ public PyPI release
Metadata
Release files for polanyi 0.4.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| polanyi-0.4.2.tar.gz | 50.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| polanyi-0.4.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 109.3 kB
Release files / polanyi-0.4.2.tar.gz
| Download URL | polanyi-0.4.2.tar.gz |
|---|---|
| Size | 50.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d5cd1f41b3abcb46a2cf119f2e4023a48574c5baa06e18df4791c6221fb60ab3
|
|
BLAKE2b-256 checksum How to use checksums |
1c20b7fac20f783151128d7201c1b21226548454db6808892805d9aaf62fade6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.5
|
Release files / polanyi-0.4.2-py3-none-any.whl
| Download URL | polanyi-0.4.2-py3-none-any.whl |
|---|---|
| Size | 59.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
358e242e7b9d59263aebe96d5a1315ba7c5d7c0ee02b2a54e47eb244d1bc9328
|
|
BLAKE2b-256 checksum How to use checksums |
14c10af86b2a8df0d0a73b40078c2c1a9b1b92d735e05e323137eea120b630f2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.5
|