league-of-agents
A cooperative/competitive strategy arena where agent teams complete missions, control objectives, manage resources, and out-coordinate opposing teams.
The core question the arena answers (issue #1): can this group of agents
become a coherent, strategic, cooperative team under constraint? Matches are
deterministic and replayable, scored on both mission outcome and cooperation
quality, beautiful for humans and --json-practical for agents.
Features
Everything the arena offers, grouped. Each feature has a deep-dive page under
docs/features/ with the full mechanism, but the substance is
here — you shouldn't have to leave this page to understand what League of Agents
does.
The engine
- Deterministic engine (grid lane) — Match state is immutable frozen
dataclasses with a stable
state_hash; an append-only event log is the single source of truth (the tick never edits state — it emits events and folds them, so replaying a log reproduces the outcome exactly); resolution is canonical-order, sorted by(team_id, unit_id), so submission order never matters. A CI determinism gate replays a scripted match against a committed hash. Deep dive → - Continuous engine lane (real-time) — A second engine that resolves an
event timeline instead of turns: integer milliunit positions (no floats),
initiative decided by who finishes first with a canonical
(time, team_id, unit_id)tie-break, and first-class race semantics (the slower taker of a contested point fails withpost taken by a faster agent). Provably independent of the grid lane, with its own determinism hash. Deep dive → - Scenarios & roles — The boards a match runs on (grid, objectives, economy,
roster). Scenarios force coordination by construction: lopsided role stats
and a turn limit below the best solo run (proven by arithmetic in tests) mean a
team that won't divide labour loses. Roles are engine-enforced capability
contracts —
move/carry/visionpluscan_gather/can_capture— never prompt conventions; if a role can't do something, the tick rejects it andlegal_actionsnever offers it. Deep dive →
Scoring & inspection
- Scoring & grades — Every match is graded on more than who won: mission outcome, a cooperation-quality heuristic (delegation, communication, plan coherence, discipline), a published tempo axis (per-substrate calibrated, raw latency always shown), a span-of-control probe (how many subagents a mind actually fielded and how well it commanded them), and per-unit role-purpose scorecards that name an MVP and LVP. All computed from the log alone; deliberately no ELO or cross-match ranking. Deep dive →
- Fog of war & vision — Per-role vision radii plus an accumulating knowledge
fold turn a match into an information game: under fog a team sees only what it
has witnessed or been told, never the full board. Fog is a projection in the
harness/CLI, never an engine mutation. Orchestrator mode adds declared
map-readandunit-commslevers. Deep dive → - Standings & history — Two read-only trend verbs computed straight from the match logs: per-team W/L/D and cooperation trend, and per-agent records. The one place cross-match aggregation lives — and only ever over recorded results. Deep dive →
Watching a match
- Replay & faces — One log, many faces, all derived from the same fold so
they can't disagree: a self-contained HTML replay (one file, both themes,
no external requests; a full play/pause/scrub transport in the continuous
face), a markdown briefing (the agents' face, with
--jsonparity), a terminal view, offline GIF/MP4 video (pure-stdlib GIF,ffmpegMP4 with a seeded soundtrack), and generative ambient audio. Deep dive →
Playing the arena
- Agent-first CLI — Dry-run by default (
--applycommits),--jsonon every read verb (bar the interactivetui), a stable error contract (CliError{code, message, remediation}+ exit codes0/1/2/3+, no leaked tracebacks), a clean stdout/stderr split, and no third-party runtime dependencies. New functionality is added as noun groups, never bolted on. Deep dive → - Agent-player harness & drivers — Play a whole match through the public CLI
surface with live models (one independent mind per seat, coordinating only
through in-game messages) or bots. Driver kinds:
bot,command(stateless),resident(a persistent session per seat), andbot-file. Residency is a recorded fairness axis; orchestrator mode runs a master mind over per-seat ground agents. Which model sits in a seat is config, not code. Deep dive → - Coded-strategy bots — A lane of automations with committed, readable strategies that play the public surface only (no engine internals, no nondeterminism — both enforced by AST scan), with declared bronze/silver/gold difficulty tiers and recorded proof the ordering holds. Deep dive →
- Play presets — One-command launch of every bundled mode
(
solo/team/orchestrator/residentvs. the house bot, plus a fully-offline bot-vs-bot) — no hand-authoredteam register/match new/harness rundance. Deep dive →
The agent itself
- Identity & mesh — League of Agents is itself an AgentCulture mesh agent:
culture.yamldeclares its nick/backend/model (backendcolleague→AGENTS.colleague.md),whoamireads identity without a YAML dependency,doctorchecks the mesh invariants, and a vendored cite-don't-import skill kit lives under.claude/skills/. Deep dive →
Quickstart
uv sync
uv run pytest -n auto # run the test suite
uv run league whoami # identity from culture.yaml
uv run league learn # self-teaching prompt (add --json)
uv run teken cli doctor . --strict # the agent-first rubric gate CI runs
Play a full bot-vs-bot match end to end:
uv run league team register blue --agent b1:bot:greedy:scout \
--agent b2:bot:greedy:harvester --agent b3:bot:greedy:defender --apply
uv run league team register red --agent r1:bot:greedy:scout \
--agent r2:bot:greedy:harvester --agent r3:bot:greedy:defender --apply
uv run league match new --scenario skirmish-1 --team blue --team red \
--seed 7 --id my-first-match --apply
uv run league match act my-first-match --team blue \
--action b1:move:2,1 --plan "scout east" --apply
uv run league match act my-first-match --team red \
--action r1:move:9,8 --apply # last team in -> the turn resolves
uv run league match show my-first-match --json
uv run league match replay my-first-match > match.html # open in a browser
uv run league match score my-first-match
Or let the harness drive both sides (see league explain harness for live
model drivers):
uv run league harness run --config docs/playtests/season-0/opener.config.json --apply
Or skip the hand-authored setup entirely: league play bundles every
documented mode as a preset (league play list), so each one launches with
a single command (league play show <preset> prints the resolved config
first if you want to check before applying):
uv run league play start solo-vs-bot --apply # one agent, handicapped, vs the house bot
uv run league play start team-vs-bot --apply # one mind per seat (stateless) vs the house bot
uv run league play start team-vs-team --apply # bot-file vs bot-file, fully offline
uv run league play start orchestrator-vs-bot --apply # a master mind + per-seat ground agents vs the house bot
uv run league play start resident-vs-bot --apply # one long-lived session per seat vs the house bot
CLI
| Verb | What it does |
|---|---|
whoami / learn / explain <path> / overview / doctor |
Agent-first introspection: identity, self-teaching, per-path docs, snapshot, invariants. |
arena list|show |
The scenario catalog (read-only). |
team register|list|show |
Rosters: agent seats as id:model:role triples. |
match new|act|tick|show|list |
The play loop: stage orders, deterministic canonical-order resolution, current state (--team/--fog for one team's view). |
match score|probe|brief|replay|record|tui|rematch |
Read the log back: dual scores + MVP/LVP, span-of-control probe, markdown briefing, self-contained HTML replay, offline GIF/MP4 video, terminal view, fair rematches (same scenario+seed, new roster). |
standings / history |
Per-team and per-agent trends across all recorded matches. |
harness run |
Play a configured match with live drivers end to end. |
play list|show|start |
One-command launch of a bundled preset mode (solo/team/orchestrator/resident vs. the house bot). |
Every read verb supports --json (except the interactive match tui, which renders a terminal view only); write verbs (team register, match new/act/tick/rematch, harness run, play start) are dry-run by
default — --apply commits. Results go to stdout, errors/diagnostics to stderr (never mixed).
Exit codes: 0 success, 1 user error, 2 environment error, 3+ reserved.
How the game grows
Development runs a recursive spec → plan → implement → live-test cycle —
no new spec opens without a recorded live match from the previous increment.
See docs/process/cycle.md; season-0 artifacts live
in docs/specs/, docs/plans/, and docs/playtests/.
License
Apache 2.0 — see LICENSE.
Metadata
Release files for league-of-agents 0.17.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| league_of_agents-0.17.0.tar.gz | 1.7 MB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| league_of_agents-0.17.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.0 MB
Release files / league_of_agents-0.17.0.tar.gz
| Download URL | league_of_agents-0.17.0.tar.gz |
|---|---|
| Size | 1.7 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
770c2886b997814ea196b7dc0f73e330b29ababe3028958f2d8fcf2fd7671e02
|
|
BLAKE2b-256 checksum How to use checksums |
d7dd855a842d64309ee62a773fe00139f53344c47543863376b78f5dee18e55b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / league_of_agents-0.17.0-py3-none-any.whl
| Download URL | league_of_agents-0.17.0-py3-none-any.whl |
|---|---|
| Size | 332.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d40b8555908a67d76bdb65bc9e11f199276087326f54a4abbab5f3c910f54e38
|
|
BLAKE2b-256 checksum How to use checksums |
53f3bcd912a73fb7cc27ced3f8feaf8e5899e55cc1ac0668ab63551273afdd8f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for league-of-agents 0.17.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.