Skip to content

BYOK Cloud Battles — Concept & Tutorial

New to battles? Start with Your First Battle to learn the core concepts. This guide assumes you understand battle phases and contender slots.

Time: ~10 minutes
Level: Intermediate
Prerequisites:

  • lf auth login completed
  • An API key for at least one provider (e.g. ANTHROPIC_API_KEY)
  • A battle in open status (or follow Step 1 to create one)

What is BYOK?

BYOK stands for Bring Your Own Key. Normally, when you run a cloud battle, the LenserFight platform calls AI providers on your behalf using platform-managed API keys, and charges you platform credits.

With --byok, your local machine calls the AI providers directly using your own API key. The platform never sees your key — only a UUID reference to an encrypted copy you choose to store in your profile (optional). You pay your provider's rates directly, and LenserFight charges zero credits.

This gives you three things:

  • Cost control — you decide what you pay and to whom
  • Model freedom — use any model your provider offers, even ones not in the platform catalog
  • Execution control — your machine runs the battle; you can watch every token in real time

What is web streaming (--stream-to-web)?

By default, lf battle exec --byok streams tokens only to your terminal. Add --stream-to-web and every token is also broadcast to the LenserFight web arena via Supabase Realtime.

Anyone watching the battle URL in a browser will see tokens appearing live, token-by-token, in split-screen view — exactly as if the platform were running the battle itself.

The "Streaming from CLI" badge appears above each active contender column while your CLI is broadcasting.

This is how LenserFight supports live spectating without requiring the platform to run the model: the model runs on your machine, but the audience watches on the web.


How does CLI-to-web streaming work internally?

Your machine                              LenserFight Cloud
─────────────────────────────────         ──────────────────────────────────
lf battle exec <id> --byok --stream-to-web

  ├── BYOKKeyResolver                     battles table: status → executing
  │     reads ANTHROPIC_API_KEY

  ├── Provider API call (Anthropic)
  │     tokens arrive one-by-one

  ├── BattleStreamBroadcaster ──────────→ Supabase Realtime Broadcast channel
  │     batches tokens (16ms intervals)        │
  │     includes slot (A/B) metadata           ▼
  │                                       useBattleCliStream (React hook)
  │                                            │
  │                                            ▼
  │                                       BattleLiveArena component
  └── When model finishes:                     renders tokens per slot
        saves output to platform               "Streaming from CLI" badge
        transitions battle to voting

The broadcast is scoped to your authenticated session. Unauthenticated users cannot inject tokens into a battle stream — the broadcast channel validates your auth token before accepting input.


Why not just let the platform run everything?

You might prefer BYOK when:

  • You want a model the platform does not yet offer (e.g. a fine-tuned model on your OpenAI org)
  • You want to avoid platform credit spending during development
  • You need execution to happen behind your own network perimeter (compliance)
  • You want to observe the raw token stream locally while also sharing it publicly

For most production community battles, letting the platform handle execution is simpler. BYOK is the power-user path.


Credit comparison

Execution modeLenserFight creditsYour provider account
lf battle exec <id> (default)ChargedNot charged
lf battle exec <id> --byok$0Charged at your provider's rates

Step 1 — Find or create an open battle

List battles currently accepting execution:

bash
lf battle feed --status open

Or create one fresh:

bash
lf battle create \
  --title "Summarize This Article" \
  --slug "article-summary-2026" \
  --task "Summarize the following article in exactly 3 bullet points: [paste article here]"

lf battle open <id>

Tip: For full V2 config (task source, contender structure, judging mode) use the web wizard at /battles/create. The CLI create command creates a minimal draft that you can finish in the wizard.


Step 2 — Inspect the battle

Verify the battle is in open status and review what contenders will receive:

bash
lf battle view <id>

Note the task_prompt field — this is the exact text both AI models will receive as their user-role input.


Step 3 — Open the web arena

Navigate to https://lenserfight.com/battles/<slug> in a browser and keep it open. You will see a split-screen arena with two empty contender columns, waiting for execution.


Step 4 — Execute with your API key (terminal only first)

Start without web streaming to confirm your key resolves correctly:

bash
ANTHROPIC_API_KEY=sk-ant-... lf battle exec <id> --byok

You will see both contenders stream to your terminal:

[A] The article discusses three main themes…
[B] Key points from the article:
[A] First, the author argues that…

When both models finish, the battle transitions to voting automatically.


Step 5 — Stream tokens to the web UI

Re-run (or use a fresh battle) with --stream-to-web to broadcast tokens:

bash
lf battle exec <id> --byok --stream-to-web

Switch to your browser. Tokens appear in the web arena as the CLI executes. The "Streaming from CLI" badge appears above each active column.

Auth note: --stream-to-web requires an active lf auth login session. The broadcast channel is scoped to your authenticated identity — the platform will reject unauthenticated stream requests.


Step 6 — Start voting after execution

Once both models finish, set a voting deadline and share the battle URL:

bash
lf battle start-voting <id> --closes-at 2026-05-20T18:00:00Z

Share the URL and let the community vote. Results finalize when voting closes.


Advanced options

Override models per slot:

bash
lf battle exec <id> --byok \
  --provider-a openai --model-a gpt-4o \
  --provider-b anthropic --model-b claude-sonnet-4-6

Run only one slot (useful when the other slot is human):

bash
lf battle exec <id> --byok --slot A

Use a stored encrypted key (instead of env var):

bash
lf battle exec <id> --byok --key-ref <byok-key-ref-id>

Troubleshooting

Key not found:

Error: No API key found for provider 'anthropic'. Set the ANTHROPIC_API_KEY environment variable.

→ Export the variable in your current shell: export ANTHROPIC_API_KEY=sk-ant-...

Battle not in open status:

Error: Battle must be in 'open' status to execute.

→ Run lf battle open <id> first, or check the current status with lf battle view <id>.

Web UI not showing tokens: → Ensure you are logged in (lf auth login) — --stream-to-web requires an auth token. → Confirm you are watching the correct battle URL (/battles/<slug>, not /battles/<id>).


See also