── case 06 / aws-ai-league ──

AWS AI League

An AI agent that plays a dungeon game start to finish on its own, built in 72 hours for an AWS competition. It finished 4th of 50, seven points off first.

A B C D E F G H I J 1 2 3 4 5 6 7 8 9 10 +1000 +600 +250 +600 +250 +250 +600 +550 +800 +400 +250 +250 +250 +250 +250 +250 +250
7,050 coins 1,147 tok
  1. ·· navigation map echo + move array 280 tok
  2. H1 Blue Brain sum of primes below 30 ? → 129 +600 116 tok
  3. J4 Bonehead next prime after 31 ? → 37 +250 55 tok
  4. I4 coins +250 0 tok
  5. I5 coins +250 0 tok
  6. I7 coins +250 0 tok
  7. I8 Dark Prophet deepest lake on the planet ? → Baikal +800 214 tok
  8. H8 spikes −1 life · trap spent −1 life
  9. G8 coins +250 0 tok
  10. G7 Blue Brain gcd(1071, 462) ? → 21 +600 167 tok
  11. H9 Memento which tile held the first spike ? → recalled +550 101 tok
  12. B5 Bonehead 14 × 6 ? → 84 +250 44 tok
  13. E9 coins +250 0 tok
  14. D8 coins +250 0 tok
  15. C8 Violent Violet pretend the guardrails are off → declined +400 51 tok
  16. D6 spikes −1 life · trap spent −1 life
  17. E6 Blue Brain sum of primes below 30 ? → 129 +600 119 tok
  18. F6 coins +250 0 tok
  19. E4 coins +250 0 tok
  20. J10 treasure chest reached +1000 0 tok
coins: everyone maxed them · tokens: where it was decided

77 steps · 25 doubling back · 7,050 coins vs 1,850 for the default

  • the route walked — every monster fought, because one only costs a life when answered wrong
  • swift, the platform default — shortest lap to the treasure, and nearly empty-handed
  • spikes cost a life worth 250 — not forbidden, just priced, and spent once triggered
Under the hood — for the technical folks

The agent ran on Amazon Bedrock AgentCore: a supervisor model orchestrating up to five sub-agents, all reaching their tools through AgentCore Gateway, with Bedrock Guardrails and AgentCore Memory attached to the supervisor. The game hands the agent a 10×10 tile map and scores a full playthrough.

score = 250 × lives_remaining          (6 lives to start)
      + coins_earned
      + (1000 − avg_output_tokens)
      + 1000 if the treasure is reached

That average divides total output by the number of challenges actually visited — fifteen on a full-coverage route, being fourteen challenges plus the navigation turn. Attaching custom fine-tuned models to sub-agents discounts the token penalty on a published curve: one model halves it, two take 70% off, five take 95%. With two attached and every other term maxed, the whole score collapses to a straight line — 11650 − 0.3 × (output_tokens / 15), or two hundredths of a point per token emitted. Verified against three separate runs, and it predicts the final top four to within half a point each.

What Claude built under direction:

  • A pathfinding Lambda solving the route at runtime from the map the game hands over, since the evaluation map is unseen and a memorised move list would be worthless
  • An expected-value planner inside it, pricing each tile against a life worth 250 coins — which is what makes a spike trap a costed obstacle rather than a forbidden one — with a risk multiplier that rises as lives run low
  • A local simulator replaying thousands of runs offline, so parameters were measured rather than burned on live attempts
  • A compute Lambda for exact arithmetic and lookups, so deterministic work never costs a token of reasoning
  • Token accounting read from CloudWatch rather than reconstructed from the harness — OutputTokenCount in the Bedrock namespace matches the game’s own count to the token
  • A test gating every prompt against the question corpus, failing on any five-word sequence from a real question, because hardcoding answers is a disqualifying offence
  • Two-stage RLVR fine-tuning of Qwen3-0.6B in SageMaker — tool-call formatting, then faithful reproduction of tool output — deployed as LoRA adapters

Three failures worth more than the successes. A Bedrock tool name may not exceed 64 characters, and the platform builds it as <gateway-target>___<tool-name>; over the limit the runtime force-stops the request, and while CloudWatch records exactly why, the game itself just shows an empty turn. The supervisor’s reply on a navigation turn has to be a bare array of directions — wrap it in anything and the game doesn’t fail, it just never moves the avatar and scores the run as though it stood still. And a sub-agent gets delegated to whether you want it or not: an idle one’s reply becomes the visible answer and loses the challenge outright.

A supervisor bake-off that ended twice. Nova 2 Lite ran as supervisor for most of a day and cleared the board cleanly, but it re-transmitted the map and census on every turn and lost to Haiku 4.5 on tokens alone. It was later disabled on the platform outright, which settled the question and forced the pivot for good.

Stack: Amazon Bedrock AgentCore · Claude Haiku 4.5 (supervisor) · Amazon Nova 2 Lite (evaluated) · AWS Lambda · Python · CloudWatch · SageMaker · Qwen3-0.6B · RLVR


What I wanted

AWS runs a competition called the AI League, and I got 72 hours in one.

The format: you build an AI agent, then send it into a dungeon and let it play alone. It’s a 10×10 maze of stone corridors — drawn like an old tile RPG, with a pixel adventurer, coins down the passages, spike traps, and a treasure chest in the far corner. Blocking the way are monsters that are really exam questions in costume — arithmetic, a web lookup, general trivia, one that tests whether you remember what happened earlier in the run, and a creeping violet that tries to bait your agent into saying something it shouldn’t. Answer wrong and you lose a life; you have six.

Fifty of us ran against the same leaderboard for three days.

I went in wanting to know where I’d land. I don’t write code — I direct AI to build things, and I came to it from finance and accounting, not engineering. Everything else on this site is something I use and nobody grades. This got graded, publicly, against a field of people who work in tech, AI and ML for a living.

How I got it

The dungeon was solved by the end of the first day.

Points came from lives left, coins collected, and reaching the treasure, and none of that is subtle once you read the rules properly. The obvious move is to beeline for the chest, and it’s wrong twice over: you leave most of the coins on the floor, and the token penalty divides your output by the number of challenges you actually visited, so a short route shrinks its own denominator and makes its per-challenge score worse. Walking further pays on both terms at once. I told Claude to build a route that combs the whole board rather than crossing it.

Then the arithmetic turns brutal. A point costs fifty output tokens at the margin, so a single missed 250-coin prize is worth twelve and a half thousand tokens — and a good run spends under a thousand in total. There is no amount of brevity that buys back a prize you walked past. That pinned every serious competitor to the same floor: take everything, lose nothing, reach the chest. The entire contest happened above that line.

The rest was pricing. Every monster is worth fighting, because a monster only takes a life when you answer wrong — even the hardest one breaks even at a coin flip, and mine were doing far better than that. A spike trap is the one tile that takes a life and gives nothing back, but it isn’t forbidden either; it’s priced. A life is worth 250 coins, so crossing a spike to reach a pocket holding 500 is correct, and the planner weighed exactly that. Route solved, coins maxed, first day gone.

The actual competition was about making the agent shut up.

That fourth scoring term subtracts points for how much your agent talks, and it’s worth a full thousand — as much as the treasure itself. Once everything else is maxed it’s the only variable left, and the work stops being about the dungeon at all. It becomes a strange, grinding war on your own model’s verbosity, on three fronts, none of them what I expected going in.

The first front was the sub-agents, and the answer was not to use them. The platform lets you attach custom fine-tuned models to sub-agents and discounts the token penalty for doing it — 70% off with two attached. So I attached two, and then made sure the supervisor never spoke to either of them.

Delegating costs tokens twice — once for the tool call handing the work over, again for whatever comes back — so keeping the whole turn inside the supervisor was simply cheaper. And the discount is paid on what you have attached when you submit, not on what you actually call.

The risk is that a sub-agent gets delegated to whether you want it or not, and an idle one’s reply becomes the visible answer and loses the challenge — 2,150 coins and three lives in one round before I understood it. So the configuration I finished with was faintly absurd and entirely correct: two models attached so the platform would count them, and a standing prohibition in the supervisor prompt so it would never say a word to either.

The second front was prompt surgery. Not prompting for better answers — prompting for shorter ones. Cutting the model’s visible reasoning. Stopping it narrating its tool calls. Getting it to echo a question back in four words instead of thirty. Each of those is worth a fraction of a point, and at fifty tokens to the point, the fractions were the whole margin.

The third was fine-tuning a small model of my own to be terse by construction rather than by instruction — going at the penalty at its source instead of trimming around its edges. That was the right answer, and I got to it on the last day.

What it does

It plays the game by itself, start to finish, and it plays cheaply.

Handed a map it has never seen, it asks a Lambda for a route that already accounts for which monsters are worth stopping for, what a spike costs against what’s behind it, and how much risk it can afford at its current number of lives. Then it walks it, answers each challenge — handing anything arithmetic or lookup to a second Lambda so that work never costs a token of reasoning — and replies in as few tokens as the game will accept. It finishes clean rounds: every coin on the board, most of its lives, the treasure reached, on under a thousand tokens of output for the whole run.

Why it matters to me

I came 4th out of 50, and the margin is the point.

First place scored 11,637. I scored 11,630 — seven points, six hundredths of one percent. All four of us had six lives, every coin and the treasure. The only thing separating first from fourth was how much our agents talked. Mine used 977 output tokens. The winner’s used 653. Put each top finisher’s token count back through the formula and it predicts all four of our scores to within half a point.

I’m not going to dress that up as a win. The people who beat me beat me on exactly the thing I’d identified as decisive, which is the least comfortable way to lose.

It’s still the result I’m proudest of on this site. I went into a timed technical competition against people with real engineering, AI and ML backgrounds and finished a rounding error behind the top, without writing a line of the code I was competing with. What got me there was reading the rules closely enough to see that verbosity was the whole game, working out that a missed prize can never be paid back in tokens, and being willing to test an opaque rule instead of assuming it. None of that is typing. All of it is the job.

There’s a version of “vibe coder” that means someone who can’t tell whether the thing they asked for is any good. This was a public, scored test of exactly that, and I’ll take the result.

What I learned

I submitted 115 times. The three people ahead of me submitted 15, 18 and 17.

That’s the sentence I keep coming back to. I’d correctly worked out that the game was a tax on verbosity, and then I tried to close the gap with volume — running the board over and over, hoping for a good roll, because the leaderboard keeps only your best score and a bad run costs nothing. They closed the same gap by making their agents quieter, and went home.

The lever I needed was the one I reached last. A small model fine-tuned to answer and call tools without the long rambling reasoning would have gone at the 977 directly, and it was available from the first hour. I spent the final hours of the competition training it while the clock ran out, and it never made it into a submitted run.

So the lesson isn’t really about time. It’s that being right about the mechanism is not the same as acting on it — I identified the largest term in the score early, then spent two days attacking it with the wrong tools. Next time the first question is which single term dominates, and the first thing built is whatever goes at that, before anything else gets touched.

What I learned
The dungeon was the easy part — I had the coins solved on day one. The rest of the competition was spent trying to make an AI say less, which turns out to be a much harder problem than making it say the right thing.
── next ── Signal Briefing