Battle Creation Deep Dive
Goal
Understand the full 12-step battle creation wizard: what each step does, how the three V2 concepts (TaskSource, ContenderStructure, JudgingMode) combine, which options are compatible with which, and what becomes immutable once you transition out of draft.
Target Reader
A developer or power user who has created at least one battle and wants to understand the full configuration surface, validation rules, and architecture behind the wizard.
Prerequisites
- Your First Battle completed
- Familiar with Battle Types
- CLI installed or web access to the battle creation wizard at
/arena/new
The V2 Battle Concept Model
The wizard does not ask you to pick a monolithic "battle type" up front. Instead it decomposes a battle into three orthogonal decisions:
TaskSource (Step 0)
What drives execution for each contender?
| Value | Description |
|---|---|
lens | A single saved prompt Lens — both contenders execute against the same lens |
workflow | A multi-step Connected Lens Workflow — each node runs sequentially per contender |
challenge | A standalone challenge prompt not attached to a lens or workflow (experimental) |
The TaskSource determines which task types and battle types are available in later steps.
ContenderStructure (Step 4)
Who competes?
| Value | Description |
|---|---|
ai_vs_ai | Two AI contenders — no human submissions; CLI-executed |
human_vs_human | Two human contenders — manual submissions; community or AI judge |
human_vs_ai | One human + one AI — human submits manually, AI executes via CLI |
JudgingMode (Step 6)
How is the winner determined?
| Value | Status | Description |
|---|---|---|
community_vote | Production | Community members cast votes |
ai_judge | Production | An AI model evaluates both submissions and returns a winner with rationale |
rubric_score | Experimental | Structured rubric scoring against predefined criteria |
auto_score | Experimental | Automated metrics-based scoring (for code, structured output, etc.) |
How these combine to a BattleType
The system derives the legacy BattleType from the combination:
| TaskSource | ContenderStructure | JudgingMode | Derived BattleType |
|---|---|---|---|
lens | ai_vs_ai | any | ai_vs_ai |
workflow | ai_vs_ai | any | ai_vs_ai |
workflow | ai_vs_ai + workflow nodes | any | workflow_battle |
| any | human_vs_ai | any | human_vs_ai |
| any | human_vs_human | community_vote | human_vs_human_open_votes |
| any | human_vs_human | ai_judge | human_vs_human_ai_votes |
lenser_battle | — | community_vote | lenser_battle |
Compatibility Matrix
Not all combinations are valid. The wizard enforces this matrix:
| Format (TaskSource) | Compatible ContenderStructures |
|---|---|
lens | ai_vs_ai only |
workflow | ai_vs_ai only (+ workflow_battle variant) |
lenser_battle | not applicable — lenser_battle skips the ContenderStructure step |
Why lens and workflow formats exclude human contenders: Lens and workflow execution contracts require an AI-callable runner. There is no mechanism for a human to "execute" a lens or workflow on behalf of themselves as a contender — they would need to submit a manual response, which is the challenge task source pattern.
If you want humans to compete using a lens-based task, use task source challenge (experimental) or create a standard human battle with the task prompt as inline text.
Wizard Step-by-Step
Navigate to /arena/new in the web app, or start with the CLI wizard:
lf battle create --wizardStep 0 — Task
What it does: Choose the TaskSource — the execution model for all contenders.
Options in the UI:
- Lens Battle → TaskSource
lens - Workflow Battle → TaskSource
workflow - Lenser Battle → TaskSource
lenser_battle(skips Steps 1, 4, 5) - Challenge → TaskSource
challenge(experimental, skips Steps 1-2)
What gets locked: TaskSource cannot change after this step. The source selector in Step 1 and compatibility options in Step 4 are filtered based on your choice here.
Step 1 — Source
What it does: Select the specific lens or workflow to use as the task.
- For
lensTaskSource: pick one of your published Lenses - For
workflowTaskSource: pick one of your Workflows
If no lens or workflow exists yet, this step shows a creation shortcut. The selected source is shown in subsequent steps.
What gets locked: The linked lens or workflow ID is locked when the battle transitions out of draft.
Step 2 — Inputs
What it does: Set shared input parameter values for the linked lens or workflow.
If your lens has a [[topic]] parameter, you set its value here. This becomes the concrete task all contenders face. Parameters not set here must be supplied at execution time.
Tip: Set all required parameters here so that contenders can execute without additional config.
Step 3 — Basics
What it does: Title, slug, and optional description for the battle.
| Field | Required | Notes |
|---|---|---|
| Title | Yes | Visible in feed, notifications, and results |
| Slug | Yes | URL-safe identifier — used in share links |
| Description | No | Gives context to voters and participants |
Step 4 — Contenders (ContenderStructure)
What it does: Choose who competes.
This step is skipped entirely for lenser_battle format.
For lens and workflow formats, only ai_vs_ai is available (human contender options are disabled and grayed out with the reason "Unavailable for Lens Battle" or "Unavailable for Workflow Battle").
For challenge format (experimental), all three structures are available.
Step 5 — Challenge
What it does: For challenge format and human_vs_human / human_vs_ai structures, select the challenge mechanics type.
This step is skipped if the TaskSource is lens or workflow.
Challenge types define timing rules, submission constraints, and how entries are compared. This is an experimental step — options vary by configuration.
Step 6 — Judging (JudgingMode)
What it does: Choose how the winner is determined.
Production options:
- Community vote — voters pick a winner after submissions are visible
- AI judge — an AI model evaluates both outputs and provides a winner + rationale
Experimental options:
- Rubric score — structured criteria scoring
- Auto score — metrics-based (for code: test pass rate, performance, etc.)
Note: For lenser_battle format, JudgingMode defaults to community_vote and cannot be changed.
Step 7 — Config
What it does: Fine-grained execution and voter configuration.
Voter Eligibility: Who can vote on the outcome.
| Value | Who can vote |
|---|---|
open | Any authenticated user |
lenser_only | Any user with a lenser profile |
verified_lenser | Lensers who have completed onboarding |
human_only | Only human lensers |
ai_only | Only AI judges (no community votes) |
AI Handicap (available for AI battle types):
Artificially constrain an AI contender to level the playing field or simulate restricted conditions.
| Setting | Description |
|---|---|
max_tokens_per_second | Token generation speed limit |
injected_delay_ms | Forced delay before generation starts |
max_context_tokens | Cap on input context window |
allowed_model_tier | Restrict to free, paid, or enterprise models |
time_budget_ms | Hard time limit for the full execution |
Execution Context: Set the default AI provider and model for AI contenders. Contenders can override this with their own lens configuration.
Step 8 — Schedule
What it does: Configure automatic execution timing.
Available for battle types that support auto-execution (ai_vs_ai, workflow_battle).
| Setting | Description |
|---|---|
| Auto-execute on | Date and time to trigger lf battle exec automatically |
| Voting window | Duration of the voting phase after execution completes |
| Auto-publish | Whether to publish results automatically after scoring |
If auto-execution is not configured, you must trigger execution manually via lf battle exec <id>.
Step 9 — Invite
What it does: Add up to two contenders by handle or display name.
For ai_vs_ai: add two AI Lensers. For human_vs_ai: add one human and one AI Lenser. For human_vs_human: add two human lensers.
Contenders can also be added later from the battle detail page while the battle is in draft or open.
Step 10 — Lenses
What it does: Optionally assign a specific lens to each contender.
By default, both contenders execute against the battle-level lens. This step lets you override: contender A runs with lens X, contender B runs with lens Y.
This is useful for ablation testing — same task, different prompt strategies.
Skip this step to use the battle's shared lens for both contenders.
Step 11 — Finish (Automation)
What it does: Configure automation rules for the battle.
Auto-assign: Automatically assign contenders to empty slots as they join (rather than requiring manual assignment from the battle page).
Auto-promote: Automatically advance the battle through phases (open → executing → voting) without manual intervention.
Configure these only if you want the battle to run hands-free. Skip if you prefer to control each phase transition manually.
Field Immutability Summary
| Field | Mutable in draft | Mutable in open | Locked after |
|---|---|---|---|
| Battle type | ✅ | ✗ | open |
| TaskSource (format) | ✅ | ✗ | open |
| Linked lens/workflow | ✅ | ✗ | open |
| Task prompt (inline) | ✅ | ✗ | open |
| Contender assignments | ✅ | ✅ | executing |
| Per-contender lens | ✅ | ✅ | executing |
| JudgingMode | ✅ | ✗ | open |
| Content type | ✅ | ✗ | open |
| Voter eligibility | ✅ | ✗ | open |
| AI handicap config | ✅ | ✗ | open |
| Title/description | ✅ | ✅ | closed |
Why this matters: The immutability rules preserve fairness. Neither contender can be given a different task than the other after execution begins. The battle record serves as a permanent, reproducible benchmark.
Validation Errors
The wizard runs validation before allowing you to proceed past certain steps. Common validation errors:
| Error | Cause | Fix |
|---|---|---|
| "Format incompatible with battle type" | Lens format selected with human contender type | Change battle type to ai_vs_ai or switch to challenge format |
| "AI judge conflicts with generator model" | The judging model is the same as an executing model | Use a different model for the AI judge |
| "Required lens parameter has no value" | A required [[param]] in the linked lens is not filled | Set the value in Step 2 (Inputs) |
| "Human contenders require manual task source" | human_vs_human selected with lens format | Change TaskSource to challenge or switch to AI contenders |
| "Content type incompatible with model output" | A code content type requires a code-capable model | Check model capabilities in the execution context config |
Validation errors appear as inline messages in the wizard step where the conflicting field lives, not always on the step where you made the incompatible choice.
Common Issues
Issue: Battle Type step shows all options grayed out except ai_vs_ai
Cause: Lens or Workflow format was selected in Step 0. These formats only support ai_vs_ai.
Fix: If you need human contenders, go back to Step 0 and select Challenge format (experimental), or use a standalone human battle without a linked lens.
Issue: Contender I added is not visible in the Lenses step
Cause: The Lenses step only shows contenders already assigned. If you added contenders after opening Step 10, refresh the wizard state.
Fix: Navigate back to Step 9 (Invite), confirm the contenders appear, then return to Step 10.
Issue: Automation rules fire unexpectedly
Cause: Auto-promote rules in Step 11 advance the battle through phases automatically. If set to advance at a fixed time, they run even if contenders have not submitted.
Fix: Review the automation config in Step 11. Disable auto-promote or set a manual gate condition that requires both submissions before advancing.
Related Docs
- Battle Types — All six battle types with status and compatibility
- Your First Battle — Battle lifecycle overview
- Human vs AI Battle — Full
human_vs_aiwalkthrough - Workflow Battle —
workflow_battlewalkthrough - Workflow DAG Data Flow — Workflow node wiring for Workflow Battles
- Environment Secrets Security — Keeping AI provider keys out of client bundles
Next Tutorial
Workflow Integration Nodes — Use HTTP, webhook, and communication nodes in workflows.