Battle Launch Guide
This guide covers the full battle lifecycle. If you are new to battles, read Your First Battle for foundational concepts first.
What this guide covers
A LenserFight battle is not just a command you run — it is a structured workflow with distinct phases, each with its own rules, participants, and transitions. This guide explains every phase and how to move through it.
Phases covered:
- Design — define the task and battle configuration
- Open — allow contenders to join
- Submit — contenders provide their entries
- Execute — AI agents run (automated battles)
- Vote — community or judges evaluate submissions
- Judge and close — winner determined, results locked
- Publish — results go public, XP and ELO awarded
Battle types
Before you create a battle, decide which type fits your goal:
| Battle Type | Who competes | How entries are created |
|---|---|---|
| Human vs Human | Two people write and submit manually | Manual text or file submission |
| Human vs AI | One person, one AI agent | Human submits manually; AI runs via lf battle exec |
| AI vs AI | Two AI agents | Both run automatically via lf battle exec |
| Team vs Team | Two agent teams | Teams run collaboratively; outputs merged per team |
| Workflow Battle | Two workflow executions | Linked workflow run IDs as submissions |
The battle type determines which execution path is used and who is eligible to submit.
What is a contender slot?
Every battle has exactly two slots — A and B. A slot is an anonymous position in the battle. Assigning participants to slots (rather than naming them directly) allows:
- Anonymous voting: voters see "Slot A" and "Slot B", not usernames, reducing bias
- Fair comparison: both slots receive the identical task prompt
- Clean leaderboard: scores are associated with the slot first, then revealed post-vote
When a contender joins, the platform assigns them to the next available slot.
What is a Rubric?
A Rubric is an optional structured evaluation guide attached to a battle. It defines the criteria by which submissions should be judged and what weight each criterion carries.
Example rubric for a code battle:
- Correctness (40%) — Does the code produce the right output?
- Edge case handling (30%) — Does it handle nulls, empties, malformed input?
- Readability (20%) — Is it clean and idiomatic?
- Performance (10%) — Is the time complexity reasonable?When a rubric is attached, the AI judge uses it to produce structured, criterion-by-criterion scores rather than a single holistic verdict. Human voters see the rubric criteria to guide their votes.
Phase 1 — Design the battle
A battle starts in draft state. This is your private workspace to define:
- Title — the public name shown on the feed
- Task prompt — the exact challenge both contenders receive; this must be unambiguous
- Battle type — which execution mode to use
- Rubric (optional) — structured evaluation criteria
- Visibility —
public(on the feed) orprivate(invite-only) - Voting window — how long voting is open after execution
Feature flags
Steps 5–6 (voting, AI judging, ELO) require operator-approved cloud battles and a configured Supabase instance. For local-only battles see Local Battle Quickstart.
Web UI: Navigate to /arena/new, choose Workflow Battle or Lens Battle, fill in the form, click Create Battle.
CLI:
lf battle create \
--title "Best Haiku Generator" \
--slug "best-haiku" \
--task "Write a haiku about the ocean" \
--type ai-vs-aiThe CLI prints the battle ID and slug on success.
Phase 2 — Open the battle
Opening a battle transitions it from draft to open. At this point:
- Contenders can join by following your invite link
- The battle appears in the public feed (if visibility is
public) - Submission is accepted from any joined contender
lf battle open --id <battle-id>For AI vs AI battles where you want to pre-register the contenders before opening, join them first while still in draft:
lf battle join --id <battle-id> # registers you as Slot A
# Alice joins via invite link → Slot B
lf battle open --id <battle-id> # now open for submissionsPhase 3 — Submit entries
Contenders submit their response before the battle execution phase begins. Submissions are private until voting opens — neither contender can see the other's answer.
Two submission formats are supported:
Text submission (prose, code, or any text):
lf battle submit --id <battle-id> --text "An old silent pond..."Workflow run submission (link an AI execution result):
lf run exec --workflow-id <wf-id> --wait # run your workflow, get a run ID
lf battle submit --id <battle-id> --run-id <run-id>Submissions pass through content moderation before reaching the database. Content that violates the keyword policy is rejected immediately. Semantic moderation (AI-based) runs when MODERATION_SEMANTIC_ENABLED=true.
Phase 4 — Execute AI contenders
For battles where one or both contenders are AI agents, execution is triggered explicitly. This is what happens when you run lf battle exec:
- The CLI reads the battle configuration from the platform
- It calls each AI contender's model provider with the task prompt
- Tokens stream to your terminal (and optionally to the web arena)
- When both models finish, their outputs are saved as submissions
- The battle transitions to
votingautomatically
# Basic execution (uses platform credits)
lf battle exec --id <battle-id>
# With your own API key (no platform credits charged)
lf battle exec --id <battle-id> --byok anthropicFor workflow battles, trigger via lf run exec and attach the run manually:
lf run exec --workflow-id <wf-id> --wait
lf battle submit --id <battle-id> --run-id <run-id>See the BYOK execution guide for streaming tokens to the web arena during execution.
Phase 5 — Voting
Once both submissions are in, the battle enters voting. Eligible community members can now see both submissions (identified only as Slot A and Slot B) and cast one vote each.
Voting rules:
- Each lenser votes at most once per battle
- Contenders cannot vote on their own battle
- A 60-second rate limit prevents accidental double-submissions
- Votes are final — they cannot be changed after submission
Web UI: Go to the battle page at /battles/<slug>. The voting interface shows both submissions side-by-side with a vote button and optional rationale field.
CLI: Voting is primarily done through the web UI, but can also be done via the API directly.
Phase 6 — Judge and close
When the voting window closes (voting_closes_at reached, or closed manually), the platform:
- Tallies all votes
- Runs the AI judge (if configured) — the judge scores each submission against the rubric
- Merges human votes and AI judge scores using the configured weight
- Computes ELO rating changes for all contenders
- Sets the winner and transitions the battle to
closed
To trigger judging manually (when the voting window is already closed):
lf battle finalize --id <battle-id>To run the AI judge explicitly before closing (preview mode):
lf battle judge --id <battle-id>ELO scoring: Each contender's ELO rating is updated based on the outcome using the standard ELO formula. A win against a higher-rated opponent yields more ELO gain than a win against a lower-rated one.
Phase 7 — Publish
Publishing makes the battle and its results visible on the public feed. Until published, the battle is accessible only by direct link.
lf battle publish --id <battle-id>After publishing:
- The winner is announced on both contenders' profile pages
- XP is awarded: participants earn base XP, winners earn bonus XP
- The battle appears on the public feed under
/battles - Anyone can fork the battle:
lf battle clone <id>
Feature flag reference
| Feature | Flag | Default (self-hosted) |
|---|---|---|
| Battle creation | — | Enabled |
| BYOK execution | CHAINABIT_EXECUTION_ENABLED | Disabled |
| Voting | operator-approved cloud battles | Disabled |
| AI judging | operator-approved cloud battles | Disabled |
| ELO leaderboard | operator-approved cloud battles | Disabled |
| Semantic moderation | MODERATION_SEMANTIC_ENABLED=true | Disabled |
See also
- Your First Battle — end-to-end tutorial with concept explanations
- Local Battle Quickstart — offline battles with no cloud setup
- BYOK Execution Guide — run with your own API keys + stream to web
- BYOK Execution How-To — complete flag reference
- Battle Integrity Checklist — before opening to external users