Model Office
A local FastAPI + WebSocket + HTML5 Canvas demo that visualizes capability-based job routing across multiple LLMs as a blocky Lego/Minecraft-style office. Inspired by pixel-agents-hq/pixel-agents, but built for capability-based multi-model routing rather than parsing a single coding agent's transcript.
Architecture
scripts/server.py— FastAPI backend:POST /api/task(submit a task),POST /api/events(producers push status),GET /ws(broadcast to browser), servesscripts/frontend/as static files.scripts/dispatcher.py— one Claude call decomposes the task into 2-4 subtasks and assigns each to the worker whose capability best fits (claude= code/reasoning,gpt= writing/general,sonar= research requiring live web facts). EmitsjobCreated/jobAssignedevents.scripts/worker.py— runs each subtask against its real assigned model API, emittingqueued → thinking → done/errorstatus events as it goes. Subtasks for different workers run concurrently.scripts/run.py— orchestrator: starts the server if not running, opens the browser, and (optionally) dispatches a task from argv.scripts/frontend/— canvas-based two-zone office UI: an upper grey "WORKING AREA" (desks with monitors) and a lower green "WAITING AREA" (lounge benches), separated by a thick red brick divider — Lego/Minecraft blocky art style. Worker avatars (sprites/claude.png,sprites/gpt.png,sprites/sonar.png) smoothly slide up to their desk when status becomesthinking, and slide back down to the lounge whendone/idle/error. Job tickets fly from a queue to the assigned worker's desk; speech bubbles show live status text; a log feed sits underneath. Connects via WebSocket, replays event history on reconnect.
When to Use
Activate this skill when the user:
- Wants to see/demo how work routes across multiple models based on capability
- References "pixel agents", "pixel office", "model office", or this skill by name
- Wants a live visual (browser) showing multiple agents/models picking up jobs and their status
- Asks "can you show me job allocation across models visually"
Prerequisites
Real API keys must be present in the environment before running workers:
ANTHROPIC_API_KEY(dispatcher + claude worker)OPENAI_API_KEY(gpt worker)PERPLEXITY_API_KEY(sonar worker, native web search)
If any key is missing, worker.py raises an auth error for that worker
only — the other workers still complete. Check with:
bashenv | grep -E 'ANTHROPIC_API_KEY|OPENAI_API_KEY|PERPLEXITY_API_KEY' | sed 's/=.*/=<set>/'
An env var appearing in env output with a non-empty value after = is
what matters — a bare KEY= (empty) still shows the name but has no
value. Verify with echo "LEN=${#OPENAI_API_KEY}" (0 means unset/empty).
How to Run
bashcd skills/model-office/scripts pip install -q -r requirements.txt # first run only # Option A: server + browser only, submit tasks from the UI python3 server.py & python3 -c "import webbrowser; webbrowser.open('http://127.0.0.1:8787')" # Option B: one-shot — starts server, opens browser, dispatches a task, prints results python3 run.py "Plan a 3-day Tokyo trip, write a fun blog intro, and research current visa rules for US citizens."
The dashboard also has a text input + Dispatch button, so once the server is
running the user can type new tasks directly in the browser without invoking
run.py again — it posts to /api/task which runs the dispatcher+workers
in the background and streams status over the existing WebSocket.
If a live agent (e.g. AdaL, Claude Code) is already running and separate API
keys aren't configured for worker.py, the agent can relay the pipeline
itself: POST /api/events directly with jobCreated/jobAssigned/
workerStatus/jobDone events using its own model access (e.g. consult,
web_search) so the browser still animates a live run.
Customizing Workers
Capability routing rules live in dispatcher.py::WORKER_CAPABILITIES and the
DECOMPOSE_SYSTEM prompt. To add/swap a worker:
- Add its capability description to
WORKER_CAPABILITIES. - Add a
_call_<worker>()function inworker.pyand register it in_CALLERS. - Add an entry to
WORKERSinfrontend/app.jswith a deskxposition. - Generate a matching pixel-art sprite (16-bit style, magenta background,
front-facing standing pose) and save to
frontend/sprites/<worker>.png.
Known Limitations
- Single-machine demo only — not wired into any specific agent's own orchestration; it's a standalone visualization of the concept of capability-based multi-model routing, using direct API calls to Anthropic/OpenAI/Perplexity.
- No persistence — job history resets on server restart or
POST /api/reset. - No cost/token tracking per worker yet (a natural next step: add token
usage + running $ to the
jobDoneevent payload and render it under the worker's name plate). - No self-evolving/learned routing yet (a natural next step: a skill-library cache mapping job-type signatures to the model+prompt combo that succeeded before, with fallback to the LLM dispatcher on cache miss).

