OMNISM

Documentation

OMNISIM Synthetic Users runs persona-driven journeys against your staging API, web app, or both. Register a product once, start runs from Python or REST, and receive friction clusters plus per-agent UX narratives and an observer report.

Canonical SDK: Python omnisim v0.2 (pip install omnisim). TypeScript @omnisim/sdk mirrors the same /api/v1 surface. All routes require X-API-Key.

New here? QuickstartProducts Web & hybridRuns.

Quickstart

Install the SDK, set your key, register a product, and start a run.

Terminal
pip install omnisim
export OMNISIM_API_KEY="omni_sk_your_key"
export OMNISIM_BASE_URL="https://api.omnisim.io"   # optional; defaults to http://localhost:8000
quickstart_api.py
import os
from omnisim import Omnisim

client = Omnisim(api_key=os.environ["OMNISIM_API_KEY"], base_url=os.environ.get("OMNISIM_BASE_URL", "https://api.omnisim.io"))

product = client.products.register(
    name="Acme Staging API",
    base_url="https://staging.api.acme.dev",
    openapi=open_api_dict,
    auth={"type": "bearer", "token": os.environ["STAGING_TOKEN"]},
)

run = client.synthetic_users.run(
    product_id=product["id"],
    personas=50,
    rounds=3,
    scenarios=["signup"],
    mode="behavioral_only",
)

result = run.wait_for_complete()
print(result.get("friction_points"), result.get("recommendations"))

API keys: dashboard. Web apps: see Web & hybrid.

Authentication

Every v1 request must include your API key:

http
X-API-Key: omni_sk_xxxxxxxx

Keys are tied to a tier (Free, Pro, Pro+). Limits apply to personas per run, daily API calls, registered products, and webhooks. Invalid or missing keys return 401.

Your tier also selects the agent capability level and browser screen reads (see Credits & tiers). Final observer reports are generated by a hosted report model on all tiers.

Products (API)

A product is your staging surface: base_url, optional OpenAPI spec, and encrypted credentials for the proxy.

POST/api/v1/products

API product
{
  "name": "Acme Staging API",
  "base_url": "https://staging.api.acme.dev",
  "interaction_mode": "api",
  "openapi": { },
  "auth": { "type": "bearer", "token": "staging-token" },
  "redact_fields": ["password", "ssn"]
}

auth.type: none, bearer, api_key, basic. Staging URLs only — production hostnames are rejected.

GET /api/v1/products

GET /api/v1/products/{product_id}

DELETE /api/v1/products/{product_id}

Web & hybrid products

Register a staging web app with interaction_mode: "web" — no OpenAPI required. Use "hybrid" for Playwright UI plus real HTTP from OpenAPI.

Web product (SDK)
product = client.products.register(
    name="My SaaS staging",
    base_url="http://127.0.0.1:3000",
    app_url="http://127.0.0.1:3000",
    interaction_mode="web",
    user_flows={
        "signup": [
            {"action": "goto", "path": "/"},
            {"action": "read_screen", "scope": "page"},
            {"action": "click", "selector": "#signup", "label": "Sign up"},
        ],
        "_config": {
            "journey_mode": "exploratory",
            "repo_path": "/path/to/my-app",
            "staging_command": "npm run dev",
            "browser_harness_url": "http://127.0.0.1:9333",
        },
    },
)

# Hybrid: API + browser
product = client.products.register_hybrid(
    name="Acme full stack",
    base_url="https://staging.api.acme.dev",
    app_url="https://staging.app.acme.dev",
    openapi=open_api_dict,
    user_flows={"...": []},
    auth={"type": "bearer", "token": "..."},
)

Flow actions: goto, click, fill, wait_for, read_screen (accessibility tree — not screenshot OCR), read_text, screenshot (visual proof).

Pro / Pro+ add enhanced DOM on read_screen (bounding boxes + key computed styles). Free uses ARIA snapshots only.

Localhost products can auto-start via user_flows._config (staging_command, repo_path, health_path). Server needs playwright install chromium and browser requirements installed.

POST /api/v1/products/{product_id}/browser-session

Attach Playwright storage_state (cookies) for authenticated UI runs — client.products.attach_browser_session(product_id, storage_state).

Synthetic runs

Starts an async run: LLM agents exercise your product, then friction analysis and an observer report are generated. Poll or use webhooks (Pro+).

POST /api/v1/products/{product_id}/runs

Request body
{
  "personas": 50,
  "agents": 50,
  "rounds": 3,
  "focus": "general",
  "scenarios": ["signup", "checkout"],
  "mode": "behavioral_only"
}

agents is an alias for personas. mode must be behavioral_only (behavioral accepted as legacy alias). Response 202 with run_id, poll_url, and often watch_url for live HTML.

GET /api/v1/runs/{run_id}

GET /api/v1/runs/{run_id}/traces

GET /api/v1/runs/{run_id}/report.html

GET /api/v1/runs/{run_id}/watch

Usage

Rate/limit usage for your key — not dollar credit balance (see dashboard wallet).

GET /api/v1/usage

python
summary = client.usage.get()
# daily_calls, daily_limit, tier, total_tokens, ...

Webhooks

Pro and Pro+ can register HTTPS endpoints for run completion.

POST /api/v1/webhooks

GET /api/v1/webhooks

DELETE /api/v1/webhooks/{webhook_id}

HMAC-SHA256 (v0.2+):

http
X-OMNISIM-Timestamp: 1716566400
X-OMNISIM-Signature: v1=<base64_hmac>

Signed payload: {timestamp}.{raw_json_body}

python
from omnisim import verify_webhook

body = await request.body()
if not verify_webhook(body, request.headers, webhook_secret):
    raise HTTPException(401, "invalid signature")

Full guide: docs/synthetic-users-sdk.md

Environment variables

VariableRequiredDescription
OMNISIM_API_KEYYesDashboard API key (omni_sk_...)
OMNISIM_BASE_URLNoAPI base (default http://localhost:8000)
OMNISIM_TIMEOUTNoHTTP timeout seconds (default 120)
OMNISIM_REQUIRE_HTTPSNoSet 1 to reject non-HTTPS remote URLs

Server-side (self-hosted API): GROQ_API_KEY for Free agent calls; MOONSHOT_API_KEY for Pro/Pro+ agents; ANTHROPIC_API_KEY for observer reports and UX narratives.

Python SDK

Package omnisim v0.2 — Omnisim.from_env() or explicit api_key / base_url. Namespaces: products, synthetic_users, usage, webhooks.

python
from omnisim import Omnisim, RunMode

client = Omnisim.from_env()

run = client.synthetic_users.run(
    product_id=product_id,
    agents=100,
    scenarios=["explore"],
    mode=RunMode.BEHAVIORAL_ONLY,
)
result = run.wait_for_complete(timeout=600, interval_ms=5000)
traces = run.get_traces()

wait_for_complete() uses exponential backoff (min interval_ms, cap 15s). Retries 429, 502, 503, 504 up to 3 times.

Typed errors: OmnisimValidationError, OmnisimAuthError, OmnisimNotFoundError, OmnisimRateLimitError.

TypeScript SDK

bash
npm install @omnisim/sdk
typescript
import { Omnisim, verifyWebhook } from "@omnisim/sdk";

const client = Omnisim.fromEnv();
const usage = await client.usage.get();

Python is canonical for production; TypeScript mirrors REST + webhook verify.

Reports & CLI

After completion, each agent can include a first-person UX narrative in the result.

python
result = run.wait_for_complete()
run.print_report(verbose=True)
run.open_visual_report()  # GET .../report.html

# Fields on result / observer_report:
# agent_ux_reports[], journey_results, friction_points

Terminal watch while running:

python
def on_agent(agent: dict) -> None:
    print(agent["agent_id"], agent.get("task_label"))

run = client.synthetic_users.run(product_id=pid, agents=10, scenarios=["signup"])
result = run.wait_for_complete(on_agent=on_agent, interval_ms=2000)

CLI (from OMNISIM repo):

bash
pip install -e "packages/sdk-python[cli]"
omnisim-run run --agents 10 --scenarios explore --verbose

Agent evals (internal QA)

Evaluate synthetic agent behavior quality and narrative trustworthiness via the --evals flag. Intended for internal testing of the simulation engine, not your product.

bash
# Install DeepEval in backend venv first
pip install -r backend/requirements-eval.txt

# Run with evals (adds ~2-5s per agent)
omnisim-run run --product-id prod_xxx --agents 5 --evals

# Or with test-product
omnisim-run test-product --product-id prod_xxx --scenarios explore --evals

# JSON output for automation
omnisim-run run --product-id prod_xxx --agents 5 --evals --json | jq '.agent_evals'

Requires ANTHROPIC_API_KEY in backend env for LLM-judge metrics. Without it, only deterministic metrics run.

See docs/agent-evals.md for full documentation.

Credits & tiers

TierPriceCredits / moMax personasProductsAgent tierScreen reads
Free$0$2051StandardARIA
Pro$30$30405AdvancedEnhanced DOM
Pro+$60$608020AdvancedEnhanced DOM

1 credit = $1. Synthetic runs use behavioral billing: ~$0.05/persona per run (min $1). Max rounds per run: Free 1, Pro 3, Pro+ 4. Daily API call caps vary by tier — see pricing and GET /api/v1/usage.

Errors & limits

  • 400 — validation or tier limits (personas, products, staging URL rules)
  • 401 — invalid API key
  • 404 — product or run not found
  • 429 — rate limit (SDK retries with backoff)

OpenAPI explorer: https://api.omnisim.io/docs