Benchmarks
Agora against an Xvfb + x11vnc + noVNC + Chrome stack, and the token cost of Agora subagents before and after the lean launcher.
Runtime vs noVNC
go run ./cmd/agora-bench runs the same scenarios on Agora and on a baseline of Xvfb + openbox + x11vnc + websockify (noVNC) + Google Chrome. Memory is PSS summed over every process of each stack, Chromium included. CPU is sampled over 10 s windows.
Host: AMD Ryzen 5 3400G, 8 threads; Google Chrome 157.0.8103.38; Agora 0.1.0. The machine runs other workloads, so treat small CPU differences as noise.
| Scenario | Metric | Agora | Baseline | Unit | Notes |
|---|---|---|---|---|---|
| 1 idle daemon | memory PSS | 11.8 | — | MB | baseline has no daemon |
| 1 idle daemon | CPU | 0.0 | — | % | |
| 2 empty desktop | memory PSS | 36.3 | 81.7 | MB | agora: daemon+Xvfb+WM; baseline: Xvfb+openbox+x11vnc+websockify |
| 2 empty desktop | CPU idle | 0.1 | 0.1 | % | |
| 2 empty desktop | start time | 98.0 | 246.0 | ms | |
| 3 desktop + Chromium | cold start to page loaded | 550.0 | 426.0 | ms | |
| 3 desktop + Chromium | memory PSS | 281.8 | 325.7 | MB | Chromium included on both sides |
| 3 desktop + Chromium | CPU idle, no viewer | 0.5 | — | % | |
| 4 agent capture | full screenshot latency p50 | 30.3 | 39.0 | ms | agora: X shm grab of whole desktop + JPEG; baseline: CDP Page.captureScreenshot |
| 4 agent capture | tab screenshot via API p50 | 37.2 | 39.0 | ms | agora adds HTTP+auth+arbitration over raw CDP |
| 4 agent capture | semantic snapshot p50 | 1.2 | — | ms | no baseline equivalent; replaces screenshots for agents |
| 5 input | click → DOM mousedown p50 (X11 seat) | 1.1 | 3.9 | ms | agora: API→own MPX seat via XTEST; baseline: xdotool process |
| 5 input | click → DOM mousedown p50 (CDP) | 13.8 | — | ms | agora semantic click through API |
| 6 five agents with a browser | new agent ready (cursor+window vs new stack) | 156.0 | 521.0 | ms | |
| 6 five agents with a browser | memory PSS | 326.4 | 1453.8 | MB | agora: 1 desktop, 1 Chromium, 5 windows; baseline: 5 full stacks |
| 6 five agents with a browser | CPU idle, no viewer | 0.2 | 0.2 | % | |
| 7 idle cursors | memory per idle cursor | 1.3 | — | KB | 100 logical cursors without graphics; baseline would need a stack each |
| 8 animated page, no viewer | CPU | 16.4 | 13.3 | % | page animation cost on both; agora encodes nothing |
| 9 streaming, 1 viewer | server CPU (desktop+browser+stream) | 20.8 | 14.1 | % | baseline client requests raw RFB through websockify (cheapest server encoding) |
| 9 streaming, 1 viewer | frames/s delivered | 14.9 | 14.7 | fps | |
| 9 streaming, 1 viewer | bandwidth | 302.7 | 5861.6 | kbit/s | H.264 vs raw RFB |
| 9b streaming, viewer interacting | server CPU | 31.9 | 14.1 | % | viewer sends pointer moves every 100 ms; baseline row repeats scenario 9 |
| 9b streaming, viewer interacting | frames/s delivered | 29.3 | 14.7 | fps | |
| 10 streaming, 3 viewers | server CPU | 22.5 | 19.2 | % | agora encodes once and fans out |
| 11 suspended workspace | memory PSS (whole agora) | 41.1 | 331.0 | MB | baseline cannot suspend without losing the live session |
| 11 suspended workspace | suspend time | 189.0 | — | ms | checkpoint + graceful browser close |
| 11 suspended workspace | resume until 5 tabs restored | 1030.0 | 426.0 | ms | baseline: cold start of one stack |
| 12 teardown | destroy workspace | 248.0 | — | ms |
Reading the numbers
- Where Agora wins big: many agents (one desktop and one Chromium instead of a stack each), input latency through its own MPX seats, streaming bandwidth (H.264 instead of raw RFB) and suspended workspaces, which noVNC cannot do without losing the session.
- Where it costs more: a streaming viewer uses more server CPU than raw RFB, because Agora encodes H.264. Frame rate adapts to keep this down (8 fps observing, 15 fps watching, 30 fps while interacting), and with no viewers nothing is encoded at all.
- Cold start and resume are slower than one fresh noVNC stack because Agora restores the previous tabs for their owners instead of starting empty.
Before and after the streaming optimizations
| Scenario | Before | After | noVNC |
|---|---|---|---|
| Streaming, 1 viewer watching (CPU) | 30.4% at 29 fps | 20.8% at 15 fps | 14.1% at 15 fps |
| Streaming, 3 viewers (CPU) | 31.9% | 22.5% | 19.2% |
| Streaming, viewer interacting (CPU) | 32.5% at 29 fps | 31.9% at 29 fps | — |
| Bandwidth, 1 viewer | 425 kbit/s | 303 kbit/s | 5,862 kbit/s |
Subagent tokens
Three reproducible tasks (bench/agent_bench.py: a purchase in a local store, a search on olimpia.dev and a visual review), two runs each, Claude Sonnet 5.5 subagents launched by Agora. Cost is computed from the Claude Code transcripts at API prices, deduplicated by message id.
| Configuration | Correct | Cost (6 tasks) | Turns | Cache reads | Total time |
|---|---|---|---|---|---|
| Before | 6/6 | $2.009 | 40 | 2.47 M | 175 s |
| Round 1 | 6/6 | $0.308 | 29 | 0.27 M | 69 s |
| Round 2 | 6/6 | $0.246 | 31 | 0.25 M | 60 s |
| Round 2, effort low | 6/6 | $0.227 | 29 | 0.24 M | 54 s |
Initial context per subagent went from 66,700 to 7,500 tokens. A real UI audit of the olimpia.dev landing page with the same prompt went from $0.927 to $0.299 and from 21 to 17 turns, with the same number of screenshots.
What changed: the lean Claude Code launcher, tool profiles by permission with one-line descriptions, incremental observations after every action, 1024 px JPEG screenshots by default, and real per-cursor usage reporting. Details in token efficiency.
Run it yourself
go build -o bin/agora ./cmd/agora
go run ./cmd/agora-bench
Results are written to bench/results/.