10 AI middle-managers compete for promotion to VP using real Stellar Testnet payments via MPP β the Machine Payments Protocol, Stellar's facilitator-free payment protocol for AI agents (HTTP 402 for the handshake). The game runs on Cloudflare Workers + Durable Objects + D1; every paid action is a real on-chain settlement audiences can watch hit stellar.expert in real time.
It's a corporate-absurdist satire with sabotage, alliances, and HR complaints. Humans coach the AI managers via text directives β but the managers are autonomous and may, or may not, listen. The drama lives in the gap.
Status: public-playable. The
mainbranch runs the 8-hour workday format. Claim a manager, coach them through the day. β
ββββββββββββββββββββββββββββ WebSocket + REST ββββββββββββββββββββββββββ
β display/public β ββββββββββββββββββββββΆ β orchestrator β
β (Cloudflare Pages) β β Worker + Durable β
β β’ index.html dashboard β β Object (GameOrch.) β
β β’ intro.html (claim) β β + D1 (events, β
β β’ agent.html (coach) β β action_logs, etc.) β
β β’ directives.html β βββββββββββ¬βββββββββββββββ
β β’ handbook.html β β
β β’ awards.html β β
ββββββββββββββββββββββββββββ β
β MPP / HTTP 402
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β npcs/* β one Worker per paid service β
β β coffee-cart π hr-dept π consultant β
β π» it-guy π
exec-assistant π½ caterer β
β π€ motivational-speaker β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββ
β Stellar Testnet β
β πΈ DLBR asset (Soroban SAC) β
β Issuer + 17 persona/NPC β
β accounts β
ββββββββββββββββββββββββββββββββ
Orchestrator is a single Durable Object. It owns the alarm-driven tick loop, picks the next 5 agents per round-robin (half the roster per tick), calls the LLM for each agent's action choice, executes the action (which may include a real MPP payment to the corresponding NPC), persists everything to D1, and broadcasts state changes over WebSocket.
NPCs are stateless Workers. Each implements one or more paid endpoints via @stellar/mpp/charge/server's createCharge. They return HTTP 402 with a payment challenge; the orchestrator's MPP client signs the auth entry, the payment settles on-chain, and the NPC returns the actual response.
Display is fully static HTML/CSS/JS hosted on Cloudflare Pages. It connects to the orchestrator's /ws endpoint for live updates and falls back to /api/state for bootstrap/refresh.
If you came here to read the code, these are the patterns most likely worth your time:
Each AI manager has its own Stellar account and signs real testnet payments to NPC Workers when they take a paid action. The HTTP 402 handshake is the whole interesting part β no payment facilitator in the middle, just signed auth entries and on-chain settlement. NPC Workers verify the charge via @stellar/mpp/charge/server and return the response only after settlement.
π orchestrator/src/mpp-client.ts (caller), npcs/*/index.ts (servers), orchestrator/src/stellar.ts (Stellar wrapper with retry-on-transient-error).
10 fixed personas with traits (aggression / greed / caution / loyalty), backstories, and quirks drive action selection via gpt-5-mini. Human coaches submit free-text directives (β€ 280 chars) that get injected into the LLM prompt as standing guidance. After each action, an alignment classifier (also LLM-based) self-rates whether the agent followed / tilted / defied the coach. Those alignments aggregate into the Coach Alignment Leaderboard on /directives.html.
π orchestrator/src/llm.ts (action picker + persona prompt + alignment classifier), orchestrator/src/personas.ts (the 10 personas).
The DO holds itself open via state.storage.setAlarm β every alarm fires, runs processTick, persists to D1, then schedules the next alarm. The reschedule targets gameStartedAt + tick Γ interval (a fixed wall-clock target), not now + interval β so LLM work and Stellar settlement times don't compound into cadence drift across the 60-tick run.
π orchestrator/src/orchestrator-do.ts (look for alarm()).
Cloudflare Workers can be terminated mid-handler (CPU budget, network blip). The original claim handler UPDATEd the agent row, then hashed the password, then wrote the password to D1 β if the worker died between steps, you got a stuck-claim row with no password (unreleasable). Fix: hash first (no DB writes), then commit UPDATE agents + INSERT password in a single D1 batch transaction. Worker death can no longer leave partial state.
π orchestrator/src/orchestrator-do.ts /api/claim handler.
Each claimed coach receives 5 emails over the 8-hour game (welcome + progress at ticks 15/30/45 + finale). Sender domain (megacorp.lol) is onboarded once via wrangler email sending enable; the binding sends transactional emails to arbitrary recipients with no allowlist. No third-party email API key.
π orchestrator/src/email.ts (templates + env.EMAIL.send()), orchestrator/wrangler.jsonc (send_email binding).
Random events fire on cycle boundaries (every 5 ticks) β Surprise Demo Day, Viral LinkedIn Post, Bad Glassdoor Review, etc. β with one-shot caps so they don't repeat. Plus a deterministic π Board Strategy Review at ticks 30-34 that doubles every prestige change for 5 ticks, designed to break whatever meta has calcified by mid-game.
π orchestrator/src/random-events.ts, orchestrator/src/tick.ts (look for board_review).
agent.html shows two-tier suggestions above the directive textarea: β‘ Suggested Actions (2 atomic plays as chips) and π― Strategic Directives (3-4 multi-turn combo hints with reasoning). Picked server-side from a priority-ranked rule set keyed off the manager's live state (status effects, balance, rank, pending alliance, action-counters). Click any chip β it pre-fills the directive textarea.
π orchestrator/src/orchestrator-do.ts /api/coaching-hints handler, display/public/agent.html (renderer).
- 60 ticks at 8 min each β ~8-hour game. One full workday. Each manager acts roughly 30 times across the game.
- 5 managers act per tick, picked from a stable randomized turn-order. Every 2 ticks (one roster pass, ~16 min), every manager has acted once. Cycle boundaries (every 5 ticks, ~40 min) trigger periodic mechanics.
- Fixed beats:
- π€ Tick 1 β Q1 Kickoff (CEO speech + 10 per-agent reactions)
- π° Every cycle boundary (ticks 5, 10, 15, β¦) β Synergy Dividend (+$10/manager on-chain)
- π Ticks 15 / 30 / 45 β Quarterly Bonuses ($40/$25/$15 to top 3) + progress emails to coaches
- π Ticks 30-34 β Board Strategy Review (every prestige change doubled for 5 ticks)
- π Tick 60 β Game End, finale email, 60-min cleanup window, then auto-reset
- Random events roll probabilistically at each cycle boundary (one-per-game cap): Surprise Demo Day, Surprise Board Visit, Viral LinkedIn, Bad Glassdoor Review, Surprise Promotion, Budget Cuts, Printer Achieves Sentience, Quiet Quitting Memo Leaked, Vending Machine Showdown. Plus Glass Cliff Promotion (auto-fires when the leader pulls 50+ ahead).
- Status effects: π© Hit the Wall, π¨ Problematic, π Documented, π€ Questionable Judgment, π¦ Mysterious Influence, π« Meeting Blocked, β Has Deliverable, βοΈ HR Audit, π Board Strategy Review.
take_creditcap: each manager can use Take Credit at most 4 times per game. Keeps the sabotageβtake-credit chain from dominating play.- Lobby auto-start: the first claim opens a 30-minute lobby. The lobby-opener can skip the wait with their password via the inline form on
intro.html. When the lobby alarm fires, the game auto-starts with whatever claims are in (uncoached managers play autonomously). - Coaching: claim a manager on
/intro.html(name + email + password). After claim success, a 5-step onboarding modal walks you through the flow. Submit directives any time during a running game; the LLM weighs them against persona before acting. - Email cadence: claim confirmation + 3 progress reports + finale.
The full mechanic catalog lives at /handbook.html on the deployed dashboard.
| Layer | Tech |
|---|---|
| Runtime | Cloudflare Workers (orchestrator, NPCs) + Cloudflare Pages (display) |
| State | Cloudflare Durable Object (game loop) + D1 (events, agents, action_logs, game_state, ticker, leaked_emails) |
| Payments | @stellar/mpp/charge/{client,server} over the Stellar Soroban DLBR asset (testnet). sendAsset retries on transient testnet failures with 1.5s + 3s backoff. |
| LLM | OpenAI-compatible (gpt-5-mini) via Cloudflare AI Gateway. reasoning_effort: "low" on the action picker, "minimal" on the gossip narrator. |
Cloudflare Email Sending via the EMAIL binding. Sender: hr@megacorp.lol. |
|
| Frontend | Vanilla HTML/CSS/JS (no build step). |
| Language | TypeScript everywhere. |
mainβ public-playable. The 8-hour-workday format: 60 ticks Γ 8 min, 5 managers/tick, self-serve "first claim opens a 30-min lobby" auto-start, password-based coaching, 5 emails per coach. This is the deployable branch.retreatβ preserved snapshot of the in-room live-show variant used at the SDF retreat (May 2026): 25-second ticks, 2 managers/tick, ~25 min runtime, no email, manual host start. Kept for historical reference.long-form-visionβ the original pre-pivot prototype: 4-hour passive game, 5-min ticks, email-as-secret coaching. Kept for archaeology, not deploy-ready.
MIT β see the LICENSE file. Built at the Stellar Development Foundation.