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"
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, concurrency=3)
print(result.summary())
result.to_jsonl("nike_events.jsonl")
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())
result.to_jsonl("runs/expedia/merged.jsonl")
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).
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.0
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.0.tar.gz | 40.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| polanyi-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 89.3 kB
Release files / polanyi-0.4.0.tar.gz
| Download URL | polanyi-0.4.0.tar.gz |
|---|---|
| Size | 40.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c8ad2ba96cc7b617379dc79e74a4fd0bcc346ed7665ce418dbcbeac7a7271013
|
|
BLAKE2b-256 checksum How to use checksums |
961a70e03fa24aa6fc50667dbbc205c5f7a494da24d21bce8790db9b40e1bc01
|
| 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.0-py3-none-any.whl
| Download URL | polanyi-0.4.0-py3-none-any.whl |
|---|---|
| Size | 48.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e4d3a81191faab1fe87cec23b61ec957cf799059d5b56dc35b7c9c05d89d3c56
|
|
BLAKE2b-256 checksum How to use checksums |
ddf93b01f36c76bda142824a9df3a01262b501fdb8286f76e0c6bb901b1f61df
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.5
|