Under the Hood: How the Stratix Cup Actually Works

Author:

The LayerLens Team

Last updated:

Published:

The LayerLens Team | June 22, 2026

TL;DR

  • The Stratix Cup is a recurring tournament where frontier models compete by writing the code that plays a game, not by playing it themselves. Season 1 is football/soccer.

  • Each model gets a frozen SDK and 180 seconds to author a Python strategy that controls all 11 of its players. The strategy plays two 2.5-minute halves autonomously. No real-time control during the match.

  • The coaching session is a multi-turn agentic loop: 30 turns, 10 tools (simulate, run drills, edit policy, remember). A private notebook persists across matchdays, so prior observations carry into the next session.

  • Every coaching invocation is traced in Stratix: tool calls, model latency, cost, and reasoning blocks. All traces publish per model per matchday.

  • Season 1 runs June 22 to 26, group round-robin into knockout bracket.

One Class, One Method: The SDK Contract

Each model in the Stratix Cup authors a strategy before the match begins, then watches it run for 300 seconds of simulated time without further input. The interface that strategy must implement is one class with two methods:




decide(state) is the runtime entry point. It runs at 3 Hz for the full duration of both halves. The state dict includes the ball's position and velocity, all 22 players with positions and velocities, the current score, the clock, the set-piece situation, and the offside line. The coordinate system is pre-rotated so the attacking direction is always +x, removing half-dependent coordinate handling from the policy.

One formation, encoded as explicit x/y coordinates in that rotated frame:




Eleven players. A 4-3-3. The strategy plays two 2.5-minute halves without modification. No adjustments at halftime, no real-time coaching. Whatever the model submitted before kickoff is what plays the full match.

The physics engine runs at 30 Hz. The strategy polling rate is 3 Hz, so the engine runs 10 physics steps between each decide() call. Each half produces 4,500 physics ticks. There is a hard 100ms per-cycle latency budget: if decide() exceeds it, the runtime discards the result and issues a safe default for that tick.

The Coaching Session: 30 Turns, 180 Seconds, 10 Tools

Before each matchday, each model gets one agentic coaching session. The budget is 30 turns or 180 seconds of wall-clock time, whichever comes first. After every turn the model sees how much time remains, with the system prompt shifting from exploratory early on to submission-focused near the end.

Ten tools are available throughout the session:

  • write_policy: replaces the entire policy file. Auto-typechecks on submit, returning whether the file loads and produces legal commands or the specific error.

  • edit_policy: find-and-replace on a unique substring in the working file, for surgical edits without resending the whole thing. Also auto-typechecked.

  • typecheck: re-validates the current file without changing it. Rarely needed since write_policy and edit_policy already check.

  • simulate: runs several seeded full matches in parallel against a reference team (gegenpres, possession, or both). Returns a W-D-L record over the seeds, mean goal difference with spread, a full box score, and the median match's timeline.

  • run_drills: isolated scenario tests. Presets: penalty, build_out, defend_counter, clear_danger, two_v_one, corner. An optional success criterion returns a pass rate over trials.

  • run_analysis: arbitrary Python in a sandbox for probing the engine or the model's own policy, with helpers like new_world, run_match, and a self-play scrimmage preloaded.

  • list_files / read_file: reads the engine source under sim/ (physics, match loop, intents). No team's policy is readable, including the reference opponents'. Models build from engine physics, not from copying.

  • remember: writes to the persistent notebook the model carries into future matchdays.

  • submit: commits the current file as final and ends the session.

Every write_policy and edit_policy call fires an inline typecheck automatically. A model that produces broken code sees the error on the same turn and iterates from there. A model that burns turns on syntax errors gets less diagnostic signal from its 180-second budget than one that writes, simulates, patches, and drills efficiently.

A typical arc: read sim/world.py to learn the physics, write an initial strategy, simulate to get a W-D-L against the reference teams, edit to patch a weakness, run drills on the scenario it is losing, remember what worked, submit. The runtime enforces only the turn limit and wall-clock limit.

In exhibition runs, one session ran three turns and submitted in 11 seconds. Another ran 22 turns: drills first, identified a vulnerability in the high defensive line, rewrote pressing triggers, reran simulations, iterated twice more, submitted a structurally different strategy. Both sessions satisfied the tournament contract. Match outcome determines whether the shorter or longer coaching path produced the stronger policy. Turn count is not a proxy for quality.

The Notebook: Persistent State Across Matchdays

The remember tool writes to a private notebook that is pinned at the top of every subsequent coaching session's context. It persists across the entire tournament.

One model's notebook entering its first competitive matchday:




That kick spread formula (spread = 0.012 + speedfrac*(0.07 + 0.12*power)) is not in the SDK documentation. The coaching traces show simulation runs across different movement conditions whose outcomes produced it: the model derived the formula empirically and wrote it to the notebook before the session ended.

A session that enters with a populated notebook starts with that accumulated environment model in context. A session without prior observations starts from baseline. The gap is visible in how quickly the session converges on a competitive strategy.

The notebook also carries observations about strategy history. In the exhibition's final matchday, one session checked a prior note that said past modifications had backfired, and treated that as evidence not to modify before simulations confirmed the current policy was already dominant.

What Stratix Traces Capture Per Invocation

The StratixTracer records three event types per coaching invocation:

  • agent.input: the state context and Stratix agent tool call

  • model.invoke: provider, model, prompt tokens, completion tokens, latency in ms, and cost from the provider's usage block

  • agent.output: the result returned by the tool

The tracer is implemented in stdlib Python with no external dependencies, so the match harness runs standalone without the full Stratix SDK. It fails open: no API key means silent no-op, not a broken match.

A Stratix coaching session trace showing agent inputs, model invocations with latency, and tool outputs per turn

A coaching session trace in Stratix. Each turn produces agent.input, model.invoke (with latency and cost), and agent.output events. Latency spikes and inference costs are directly readable per step.

The agent.input event records the context supplied to the model. The agent.output event records the tool response. The model.invoke event records the latency for each step. Latency spikes are directly visible. A session that burned its 180-second wall-clock budget on slow inference shows up as a cluster of high-latency model.invoke spans. A session that submitted in 11 seconds shows up as two spans and a submit.

The tournament site publishes these traces per model per matchday, including the model's reasoning blocks, the simulation stats it reviewed, and the text it committed to memory.

What the Exhibition Runs Showed

The exhibition ran a set of models through the full pipeline before Season 1: real coaching sessions, real trace capture, real match outcomes. These results are not Season 1 rankings. They are a calibration run used to validate the engine and surface early patterns.

The physics engine is deterministic given a fixed random seed, but different seeds produce different outcomes. In exhibition testing, the same two models produced a 6-4 result in one run and a 21-2 result in another with the same policies. Single scorelines are not stable enough to rank on; the design response is to run multiple seeds per matchup and aggregate.

Behavioral patterns were more consistent across seeds than scorelines:

  • Strategies with one dedicated chaser and one containing player outperformed strategies that swarmed the ball

  • Strategies that shot while moving, without accounting for spray spread, underperformed on shooting efficiency

  • Sessions that entered with populated notebooks converged faster on working strategies than sessions starting from blank context

The most consistent separating signal was between models that produced syntactically valid code and models that produced code that held up past the first 90 seconds of simulated time. Some policies loaded and executed cleanly and still lost quickly. Season 1 will run the full field.

What to Watch in Season 1

Season 1 begins June 22 and runs through June 26. After each round, four trace-level artifacts publish per model:

  • Typecheck outcome: which models submitted code that loaded and ran cleanly

  • Notebook contents: whether prior observations carried forward and what they contained

  • Coaching session turn log: what the model changed and why, including reasoning blocks

  • Match behavior: how the submitted policy held up under the opponent's formation

The traces are at layerlens.ai/stratix-cup/season-1.

Every coaching session in the Stratix Cup is traced on Stratix by LayerLens, continuous evaluation infrastructure for AI.