Project Info
Inspiration
User testing is expensive, slow, and hard to scale. Recruiting real humans to click through your app takes days and costs hundreds of dollars per round. We asked: what if AI personas could simulate diverse real users — skeptics, multitaskers, accessibility-focused users — and give you actionable UX feedback in minutes? And then, how do you know the AI feedback is any good? That's where the eval loop comes in: we grade our AI testers against real human reviewers to keep them honest.
What it does
UserSwarm generates diverse AI personas, each with distinct traits and goals, then launches them into your live web app via browser automation. Each persona navigates your site, attempts a task, and writes a structured UX report citing real on-screen evidence. Reports are aggregated, evaluated with code + LLM-judge evals, and compared against human reviewer labels to measure human-likeness — do the AI testers fail where real users fail? A built-in improve-and-rerun loop uses eval failures and human annotations to refine the testing prompt, then reruns to measure the delta.
How we built it
Backend: FastAPI orchestrating a DAG — PersonaGenerator → fan-out UXTesters → ReportCritic → Aggregator → Evals Browser automation: Playwright driving headless Chromium; each AI persona gets its own browser session with screenshot capture LLM: Anthropic Claude (Sonnet for per-persona testing, Opus for aggregation/judging) with structured JSON output Evals: Code evals (task success, evidence coverage), LLM-judge evals (actionability, hallucination risk), and agreement evals (human agreement, human likeness) Observability: Arize AX via OpenTelemetry — every LLM call and eval is traced end-to-end Human baseline: Terac marketplace integration to recruit real reviewers; their labels feed the human-agreement eval Frontend: Next.js 14 App Router for run management, report viewing, and base-vs-improved comparison Orchestration: Agentspan (Orkeble execution of reasoning agents, with automatic fallback to in-process Challenges we faced Browser + LLM coordination: Each persona needs its own isolated browser session. RuPlaywright instances in parallelavigation step required carefulconcurrency management and timeout tuning. - Hallucination in UX reports: E elements that didn't exist. Weadded a ReportCritic agent that cross-checks claims against screenshot evidence, plushallucination-risk eval. Rate limits at scale: Fan-out of 3+ testers hitting the Anthropic API simultaneousltoken-per-minute limits. We tune logic with backoff. Eval grounding: Defining what "good" AI UX feedback means is hard. We settled on a multi-signal approach — code che for quality, and human agreementfor ground truth. What we learned The gap between "AI can browse a website" and "AI can give feedback a product team would actually act on" is enormous. Evructured evals, and ahuman-in-the-loop calibration step are what make the difference between a demo and a tool.## Inspiration
Accomplishments we're proud of
End-to-end autonomy: A single API call spins up personas, launches browsers, tests your app, critiques the reports, runs evals, and produces an aggregated analysis — zero human intervention required. Human-likeness eval: We built a metric that measures whether AI testers fail where real humans fail. This isn't just "does the AI find bugs" — it's "does the AI behave like a real user would?" Self-improving loop: The improve-and-rerun pipeline takes human annotations and eval failures, rewrites the testing prompt, and reruns — then shows you a side-by-side delta of what got better. Closed-loop optimization for UX testing. Evidence-grounded reports: Every friction point cites exact on-screen text, button labels, or screenshot steps. The ReportCritic agent enforces this — no vague "the UX could be better" hand-waving survives. Full observability from day one: Every LLM call, every eval, every persona session is traced to Arize AX via OpenTelemetry. We can debug a single persona's reasoning chain across 20+ browser steps.
What's next
Video replays: Record each persona's browser session as a video so product teams can watch the AI user struggle, not just read about it. Multi-device testing: Simulate mobile viewports, slow 3G connections, and tablet layouts — real users aren't all on MacBook Pros. Accessibility personas: Personas that use screen readers, keyboard-only navigation, and high-contrast mode to surface WCAG compliance issues. CI/CD integration: Run UserSwarm on every pull request — catch UX regressions before they ship, just like unit tests catch code regressions. Larger human baselines: Scale up Terac reviewer recruitment to build richer ground-truth datasets, driving the human-likeness eval from a sanity check to a statistically significant benchmark. Custom persona libraries: Let teams define their own user archetypes — "our power user," "a first-time visitor from organic search" — and reuse them across sprints.
UserSwarm
AI user-testing agents for builders, validated by real human feedback.
A builder enters a product URL + a task. UserSwarm fans out AI personas that drive the product with a browser agent, produce strict-JSON UX reports, then:
- Orkes / Agentspan orchestrates the durable multi-agent workflow,
- Terac collects human preference labels that calibrate the agent,
- Arize traces every run and evaluates report quality,
…and the agent is improved from those labels and rerun to prove measurable before/after gains.
AI user agents give instant UX feedback; Terac human labels calibrate whether that feedback is trustworthy; Arize proves improvement; Orkes/Agentspan coordinates the workflow. Not a replacement for real user research — a way to make synthetic user testing trustworthy.
Mock-first, real-ready
Every sponsor integration has a real code path and a mock code path behind
one interface. Mock mode auto-enables when a credential/server is missing, so the
entire demo runs fully offline with zero env vars. Add a key to flip that
integration live. Persistence uses Supabase/Postgres via DATABASE_URL, with a
SQLite fallback when it's unset.
| Integration | Live path | Mock path (default) |
|---|---|---|
| Anthropic LLM | anthropic SDK, claude-sonnet-4-6 / claude-opus-4-8 | Canned plausible JSON |
| Agentspan | Agentspan SDK against AGENTSPAN_SERVER_URL | In-process DAG runner (same nodes, still visible) |
| Arize | arize-otel + OpenInference spans + evals | Spans/evals logged locally + to console |
| Terac | Terac API annotation jobs | Synthetic human labels |
Quick start (offline, no keys needed)
Backend
cd backend
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
playwright install chromium # optional; static fallback works without it
uvicorn app.main:app --reload # http://localhost:8000 (GET / shows mock/live modes)
Frontend
cd frontend
npm install
cp .env.local.example .env.local # NEXT_PUBLIC_API_URL=http://localhost:8000
npm run dev # http://localhost:3000
Open http://localhost:3000 and submit a run.
Demo script (≈3 min)
- Submit on
/: a real public URL (e.g.https://example.com), product description, target audience, a task, and success criteria. → redirects to the run page. /runs/[id]— watch the Agentspan workflow timeline advance:PersonaGenerator → UXTester ×N → Aggregator → Evals. See 3–5 personas, each tester's real browser step log (open_url / get_page_state / click / scroll) with screenshots, friction points, severity, recommendations, Arize eval scores, and the Terac human-agreement score.- Annotate →
/annotate/[id]: act as a Terac human labeller; answer the six questions (usefulness, specificity, hallucination, task understanding, real-user agreement, A/B). Submit → the human-agreement eval updates. - Run Improvement — the
ImproverAgentturns labels + failing evals into an improved prompt and reruns the workflow as animprovedvariant. - Compare →
/runs/[id]/compare: base vs improved table — usefulness, evidence coverage, hallucination risk, human agreement, actionability pass rate, task-success rate, with deltas.
To show live mode: set ANTHROPIC_API_KEY (and optionally AGENTSPAN_SERVER_URL,
ARIZE_API_KEY+ARIZE_SPACE_ID, TERAC_API_KEY), restart, and rerun — real Claude
output and real spans, with mock fallback intact for any still-missing credential.
Going live per sponsor
- Agentspan / Orkes:
pip install agentspan→agentspan server start(UI athttp://localhost:6767) → setAGENTSPAN_SERVER_URL. The same DAG nodes register/run on Agentspan; the dashboard timeline reflects them. - Arize: set
ARIZE_API_KEY+ARIZE_SPACE_ID(installarize-otel+openinference-instrumentation). Every run, persona-gen, UX agent, browser tool call, aggregation, improved-prompt gen, and rerun is traced; six evals are logged. - Terac: set
TERAC_API_KEY. Real annotation jobs are created from agent reports; theterac.pyadapter has# TODOmarkers for the exact endpoint/payload — drop them in. The/annotateroute already writes real human labels regardless of mode.
Architecture
backend/ FastAPI · SQLAlchemy (Postgres|SQLite) · Anthropic · Playwright
app/agents/ PersonaGenerator · UXTester · ReportCritic · Aggregator · Improver
app/browser/ Playwright tools + safety guard (no destructive clicks; 8–12 action cap)
app/orchestration/ WorkflowRunner (InProcess | Agentspan) + event persistence
app/integrations/ arize.py · terac.py (real + mock)
app/evals/ code + LLM-judge evals, human agreement, improvement score
app/routers/ /runs · /annotate · /runs/{id}/compare
frontend/ Next.js 14 (App Router) + TS + Tailwind
app/ / · /runs/[id] · /runs/[id]/compare · /annotate/[id]
Evals
has_task_success · has_evidence (code) · actionability · hallucination_risk
(LLM judge) · human_agreement (Terac) · improvement_score (base vs improved).
Browser safety
Each agent is capped at 8–12 actions; purchase / payment / delete / send / invite / destructive clicks are blocked; login-required pages with no credentials stop and report; if automation is blocked the agent falls back to static page review.
API
| Method | Path | Purpose |
|---|---|---|
| POST | /runs | Start a workflow → {id} |
| GET | /runs/{id} | Full run: status, personas, reports+steps, events, evals, aggregate |
| GET | /runs | Recent runs |
| POST | /runs/{id}/improve | Improve from labels + rerun → improved {id} |
| GET | /annotate/{id} | Payload for the Terac annotation UI |
| POST | /annotate/{id} | Store a human label |
| GET | /runs/{id}/compare | Base vs improved metrics + deltas |
Env vars: see .env.example.
Analysis
View
Metric
- 16
- 12
- 5
- 1
Figures cover GitHub contributors during the hackathon window. A co-authored commit counts in full for each author, so per-member totals add up to more than the whole-team figures.
Technology
- AnthropicIn code
- CSSIn code
- FastAPIIn code
- JavaScriptIn code
- Next.jsIn code
- PythonIn code
- ReactIn code
- Tailwind CSSIn code
- TypeScriptIn code
- VercelClaimed
9 of 10 appear in the indexed code. 1 claimed on Devpost could not be matched to code, which may simply mean the tool leaves no trace in the repository.
AI coding agents
- Claude CodeCommits
Detected from committed agent config files and commit authorship. Absence of a signal is not proof an agent was unused.
Codebase size
Source size
348 KB
Source files
83
Counts recognized source files only; vendored directories, binaries and lockfiles are excluded, so this is smaller than the repository on disk.
Repository
Deepak-karani/userswarm
101 files · 649 KB · @ 956eb9c
Structure
Interface
70 files · 69%Screens, components and styles rendered to the user.
Application logic
3 files · 3%Domain rules, services and shared utilities.
Supporting
Layers are inferred from where files sit in the tree, not from reading the code. A project that names its directories unconventionally will read oddly here — open the file browser to check anything the diagram implies.
Languages
- TypeScript50%
- Python39%
- Markdown10%
- CSS0%
- JavaScript0%
Share of indexed source by file size. Binary and vendored files are excluded.
Dependencies
backend/requirements.txt
pypi · 12- agentspan
- anthropic
- arize-otel
- fastapi
- httpx
- openinference-instrumentation-anthropic
- playwright
- psycopg2-binary
- pydantic
- python-dotenv
- SQLAlchemy
- uvicorn[standard]
frontend/package.json
npm · 10- next
- react
- react-dom
- +7 more
test-app/package.json
npm · 10- next
- react
- react-dom
- +7 more
skill/userswarm/requirements.txt
pypi · 1- playwright
Declared in the repository’s manifests at the indexed commit. A declared package is not proof it is used, and runtime dependencies are listed first.
This project’s features have not been analysed yet.
Export this project's context (description, README, evidence, key source files) to chat with an AI agent elsewhere.