Inspiration

Teams are handing AI agents a shared budget with no way to govern it. Uber burned its entire 2026 AI coding budget in four months — one internal demo cost $1,200 in two hours. 79% of enterprises had AI cost overruns in the past year, and only 36% have any token or usage controls at all.

The gap isn't dashboards — those report yesterday. The gap is real-time, shared, enforced governance: who is using the agents right now, what it's costing, whose turn is next, and what happens when the budget runs out.

Operating systems solved exactly this for CPU fifty years ago: scheduling, quotas, fair queueing. HiveOS applies that abstraction to a team's shared AI compute. The interaction model borrows from Munder Difflin's "office of agents" idea — but for a team, in the cloud, on one budget everyone can see.

What it does

HiveOS is a cloud-deployed office where a team hires and runs a floor of AI agents together.

  • You staff the floor. A workspace opens with two agents — Ada, an engineer, and Iris, a researcher. Any member can hire up to four: name them, give them a role and a character, and brief them with a persona that becomes their system prompt. They walk onto the floor and take a desk.
  • You watch them work. A desk lights up when its agent is running and the person who asked walks over to it — live, on every member's screen at once, over one open WebSocket.
  • One shared, enforced budget. The token meter is identical on every screen. At 100% the server refuses to invoke the model — not one token is spent. It's a ceiling, not a gauge.
  • A fair queue. When every desk is busy, further requests queue with a real position, visible team-wide, and a freed desk auto-dispatches the next one. Nobody re-asks.
  • Team memory. A fact one member saves is loaded into the next member's agent before their task starts, through tools the model chooses to call.
  • Agent-to-agent handoff. An agent can pass work to a better-suited desk — one request, two agents, one bill, bounded to one hop.
  • Isolated workspaces with optional passphrases and an owner who sets the budget, plus a per-person spend ledger.
  • Eight worlds. The board can wear Paper Office, Night Watch, Enchanted Forest, Reef Station, Alien Colony, Cloud City, Arctic Base or Desert Outpost — swapped live with no reload. Same sockets, same scheduler; re-dressed. A world never changes what a colour means.

How we built it

Solo, in ~72 hours, entirely serverless on AWS from one SAM template (16 CloudFormation resources):

Browser ──wss──► API Gateway WebSocket ──► Router Lambda ──► DynamoDB
│ ▲
▼ │
SQS ──► Agent Runner Lambda ──► model
  • API Gateway WebSocket holds one open socket per member; every state change fans out to all of them.
  • Two Lambdas, split so agent latency never blocks connection handling. The Router owns connections, slot claims and queueing. The Agent Runner loads team memory, checks the ceiling, calls the model, accounts the tokens, releases the desk, dispatches the next task and broadcasts.
  • DynamoDB single-table. Atomic conditional writes do the slot claiming — two simultaneous clicks are safe. Atomic counters do the token accounting.
  • SQS + DLQ for durable, at-least-once handoff of every agent task.
  • SSM Parameter Store for the model key as a SecureString — never in the template, the stack or git.
  • Amplify Hosting for the React 19 + Vite frontend. No game engine — the pixel office is CSS and DOM.
  • AWS Budgets as a spend backstop behind the in-app ceiling. The video narration is Amazon Polly. Two design decisions worth naming. The queue is gated in DynamoDB, not SQS — SQS exposes approximate depth, not "where am I in line," and a conditional claim that falls back to a QUEUE#<timestamp> item makes position a trivial count. And the ceiling is checked immediately before the model call, not at claim time, because a queued task can sit while the tasks ahead of it burn what was left.

Claude Code was the sole implementation assistant, operated by me. The trick that made it work across many context resets was treating the repository as the agent's memory: CLAUDE.md for workflow, PROGRESS.md for state, CONTRACT.md for the schemas and protocol so nothing drifts between sessions.

Challenges we ran into

  • Bedrock is blocked account-wide on my AWS account. 42 of 43 per-day token quotas sit at zero and are non-adjustable — including Amazon Nova. I verified it across three regions before giving up. Inference is therefore one outbound HTTPS call to Groq (openai/gpt-oss-120b); everything else is AWS. The swap touched one function plus a 130-line client and nothing in the scheduler moved — which is the product's own argument: a governance layer that only works against one vendor is a worse governance layer.
  • Frame ordering is a correctness property. claim_agent dispatched to SQS before broadcasting BUSY, so a fast-failing task could post its reply ahead of the BUSY frame and leave a desk stuck busy for the session. It failed about half the time.
  • The cold-load path is the one a judge takes. Twice I shipped something correct for a watching client and wrong for a joining one — the "partly estimated" token flag and a queue ETA both rode only on incremental frames, not the snapshot.
  • A passing test for the wrong reason. Avatar moves silently failed because Decimal(24.92) from a float raises decimal.Inexact in boto3. My test used 73.5 and 21.25 — exactly representable in binary. Only a real mouse click produced a coordinate that wasn't.
  • A world is not a colour scheme. Eight worlds surfaced a long list of shared-code traps: a gradient radius as a floor percentage is a different shape at every framing, a radial-gradient that doesn't end in transparent hides every layer under it, a bright world inverts the whole lighting method, and every value register a world adds costs a re-pitch of the small type.

Accomplishments that we're proud of

  • A deployed, public, multi-user office that three browsers can open cold with no sign-in — and the demo was recorded from the live URL, not localhost.
  • Measured cross-browser latency: a claim reaching a second browser in 282 ms, auto-dispatch visible in 187 ms, an avatar move painted in 270–294 ms — click-to-paint across two separate browsers.
  • The token counts are real: tokens_used is what the provider reports, never an estimate, and a degraded call can never be laundered into a billed-looking meter.
  • Every check runs against deployed AWS: 109/113 end-to-end smoke checks, 15/15 rehearsed demo takes twice unattended, and the unit suite has grown from 27 to 112 since submission.
  • The agent chooses its tools. "Please make a note for the whole team that our staging URL is staging.hiveos.dev" — the model picked set_team_memory and extracted the key and value itself. extracted the key and value itself.
  • Eight worlds, every state hue measured at ≥4.5:1 against every surface it paints, with Paper Office proven byte-for-byte unchanged after each one.
  • The public repo has already taken outside pull requests, and four post-submission bugs — including DLQ recovery and multi-tab presence — are merged and deployed.

What we learned

  • The hard part was not the AI. It was making three browsers agree on one number.
  • Test what the user sees, not what the code returns. The slot-leak and ordering bugs were invisible to unit tests and obvious the moment I asserted on frames arriving at a second, observing client. A zero exit code proves a command succeeded, not that the system behaved.
  • A green measurement can describe a broken screen. scrollHeight === innerHeight went green because two panels were amputated off-screen. A screenshot showed it in one second. Verify the artifact, not the proxy.
  • Diagnose the account, not the code. Hours went into assuming Bedrock was a permissions problem. Reading 1,123 service quotas and noticing two vendors failed identically ruled out my codebase in one step.
  • The failure a layer below yours will impersonate your own. Cloudflare rejecting a default User-Agent looks like a bad API key. A retired model name fails at runtime, not deploy. CloudFormation keeps a stack's existing parameter values, so editing a template Default: changes nothing.
  • Tests that encode a placeholder's behaviour break when the placeholder gets better. Swapping the stub for a real model broke three tests and none were product bugs. Rewritten as the real invariants, they hold in both modes and are stronger.
  • Ship the thing that survives being cut. I built the public URL before the model integration, against the plan's own ordering. That inversion is why there was a submission at all.

What's next for HiveOS

  • Ancient Ruins — the ninth world, a dark torchlit look and the first dark world since Reef Station.
  • World polish and Random World — a CSS cross-fade between worlds that survives a pawn mid-walk, micro-animations gated behind prefers-reduced-motion, a full contrast matrix across every world, and a "surprise me" picker.
  • Bedrock, when the account allows it. The provider is one function away; the governance layer doesn't care where a token was spent, only that it was counted.
  • Longer term: per-agent budgets within a team's ceiling, richer handoff chains, and a spend history that shows who drove the budget and which agent did the work — the same OS abstraction, one level down.

Built With

Share this project:

Updates

Submission history