Four open-weights LLMs. One prompt. Same instant. Two rounds. No brackets, no scorecards — the clock decides round 1, and the winner's own words become round 2's weapon.
Built for the JigJoy × daily.dev × Hyperskill hackathon —
Build Systems of Concurrent Agents, on @mozaik-ai/core.
A real-time arena where 4 LLM fighters (Kimi, DeepSeek, Qwen, GPT-OSS) answer the same prompt at the same instant and race to finish. Then it gets interesting: the winner's answer becomes the prompt for round 2, and every fighter — including the champion — must react to it, concurrently. Rebut it, top it, or defend it.
Run it:
npm install
cp .env.example .env # FEATHERLESS_API_KEY + MOZAIK_API_KEY
npm start -- "Explain recursion to a 10-year-old in one paragraph."Every run prints a mozaik cloud session link — a live, replayable trace of
every event. Watch a recorded bout (prompt: "Why is the sky blue?"):
https://app.jigjoy.ai/?s=ses_69fe847c2c534412a70aa481572b0be4
Round 1: GPT-OSS 2.5s [#1], Qwen 3.4s, DeepSeek 10.2s, Kimi 24.5s. Round 2: Qwen rebuts in 1.9s [CHAMP] — 8/8 answers posted, zero blanks.
Most "multi-agent" demos are pipelines: agent A finishes, agent B starts. That is a script with extra steps. The hackathon brief asks for the opposite — agents that run at the same time, share state, and coordinate. Fight Club is built to make concurrency observable: per-token stream previews interleave live in the terminal, so you can see four models thinking at once instead of taking it on faith.
The second motive is verification. AI demos are easy to fake and hard to replay. Every bout streams its full event trace to Mozaik Cloud, so a judge never has to trust a screenshot — open the link, replay the fight. And at ~$0.0007 a bout on Featherless free credit, anyone can run it all day.
One message.sent event fans out to 4 fighter agents in a shared
AgenticEnvironment. Each fighter's handler awaits only its own streaming
LLM call — nobody blocks anyone — emitting per-token fighter.delta events
and a final model.answer. A Scoreboard observer ranks the bout by latency.
Round 2 is where it becomes a system instead of 4 parallel API calls. The 4th
model.answer fires a round2.start event carrying the champ's answer as
shared state. Every fighter reacts to state it did not produce, in a second
concurrent race (rebuttal.delta → rebuttal.answer). The round is caused
by the previous round, not scheduled by a script.
Host --(prompt)--> [Kimi | DeepSeek | Qwen | GPT-OSS] all at once
| fighter.delta (per-token, interleaved)
v
Scoreboard: round-1 board, fastest == champ
|
round2.start(champ) --> [all four react at once]
| rebuttal.delta (per-token, interleaved)
v
Scoreboard: round-2 board + verdict Cloud: live trace
Shared state (FightState): prompt, results[], rebuttals[], round2 flag.
Event catalog: message.sent → fighter.started → fighter.delta →
model.answer → round2.start → rebuttal.delta → rebuttal.answer.
Failure is a first-class citizen: a fighter that errors still emits its answer
event with finishReason: "error", so one lab's outage never kills the bout.
Reasoning models that burn their streaming budget on thinking tokens get one
non-streaming retry — no blank posts, ever.
Fight Club is meant to be stolen from. Beyond the demo, it is a reference for three patterns every Mozaik builder needs:
- Fan-out race — N agents, one event, independent
awaits, ranked by a shared observer. The minimal honest concurrency pattern (bell.ts). - Causal rounds — round N+1 triggered by round N's state, not by a
timer or orchestrator. The difference between a system and a pipeline
(
own-answer.ts→round2.start→round2.ts). - Error-tolerant observers — scoreboards and mirrors that count
completions instead of assuming success, so partial failures degrade the
show instead of hanging it (
scoreboard.ts,main.tsdrain).
Plus two reusable parts: per-fighter multi-provider routing (FighterSpec
carries its own baseURL/apiKeyEnv, so fighters can live on different
inference backends in one bout) and the cloud-mirror bridge (one createHuman
participant that forwards every event to Mozaik Cloud — copy-paste live
tracing for any Mozaik app).
src/runtime.ts shared FightState + bus
src/participants/fighter/llm.ts per-fighter streaming (+ fallback)
src/participants/fighter/situations/bell.ts round 1: one event, four racers
src/participants/fighter/situations/own-answer.ts medals + rings the round-2 bell
src/participants/fighter/situations/round2.ts round 2: react to the champ
src/participants/fighter/situations/rebuttal-answer.ts records rebuttals
src/participants/scoreboard.ts live previews + both leaderboards
src/main.ts runtime + cloud-mirror bridge
demo/render.py regenerates the demo video from any bout log
All open-weights, all on Featherless (~$0.0007/bout — $10 of free credit is ~15,000 bouts):
| Fighter | Model | Style |
|---|---|---|
| Kimi | moonshotai/Kimi-K2-Instruct |
vivid storyteller |
| DeepSeek | deepseek-ai/DeepSeek-V3.2 |
terse technician |
| Qwen | Qwen/Qwen3-Next-80B-A3B-Instruct |
systematic, loves structure |
| GPT-OSS | openai/gpt-oss-120b |
precise, clean examples |
Nobody trusts a single lab's latency. Four labs, one clock.
MIT — see LICENSE.