Interactive lab · Claude API · Agents

Thin Ice

An interactive lab that shows what an AI agent actually does. Claude has to guide an ice-fishing sled across a frozen Michigan lake to where the fish are biting, without going through the ice. It can't see the lake. All it can do is call tools and read what comes back. Watch it work, take its place, or run the real Claude with your own API key.

Audience

Developers and technical teams who are starting to build agents with the Claude API.

What it teaches

The agent loop: tool use, parallel tool calls, error recovery, growing context and stop reasons.

Tools

JavaScript, three.js with a custom shader, Claude API (Anthropic TypeScript SDK), Claude Code

Thin Ice // agent loop lab
Thin IceLoading the lake
Turn 0ready
Loop

This lab needs JavaScript to run. The write-up below explains how it works.

Input tokens per request

SEC. 01The Problem

Agents feel like magic until you see the loop. A lot of training jumps straight to frameworks, and learners end up copying code they can't reason about when something goes wrong.

The idea underneath is small. The model never does anything itself. It asks for a tool, your code runs it, and the result goes back to the model as text. Then you do it again, until the model stops asking. I wanted a way to make that loop visible, and to give it a little tension, so people remember it.

SEC. 02The Design

The lab has three modes, and they run in the order I'd teach them:

  1. Watch. A worked example. A scripted agent crosses the lake while every message, the loop code and the token count update in step, with a caption explaining each move in plain language.
  2. You're the model. The roles flip. The lake turns to fog, and you get only what a model gets: a system prompt, five tool definitions and a growing list of messages. It's the fastest way I know to feel why tool descriptions and error messages matter.
  3. Live with Claude. The real thing. Paste an API key and the same loop calls Claude from your browser, with the real requests, thinking summaries and token usage on screen.

Five concepts light up along the bottom as you meet them: tool use, parallel calls, error recovery, growing context and stop reasons. They work like learning objectives you can watch fill in.

SEC. 03Design Decisions

SEC. 04How It's Built

It's a static page with no server behind it. The lake is a single plane in three.js, and one custom fragment shader draws nearly everything on it: the ice, snow, cracks, open water, drill holes, sonar pings and the fog over whatever the agent hasn't learned yet. On devices without WebGL, it switches to a lighter 2D view.

The agent loop is about forty lines of plain JavaScript, and it's the same loop in every mode. Only the function that produces the model's turn changes:

// loop.js, with the page's animation hooks taken out
for (let turn = 1; turn <= maxTurns; turn++) {
  const response = await callModel({ system: SYSTEM_PROMPT, tools: TOOLS, messages });
  messages.push({ role: "assistant", content: response.content });
  if (response.stop_reason !== "tool_use") return { stop: response.stop_reason, messages };

  const results = [];
  for (const block of response.content) {
    if (block.type !== "tool_use") continue;
    const out = runTool(lake, block.name, block.input);
    results.push({ type: "tool_result", tool_use_id: block.id, content: out.text,
                   ...(out.isError ? { is_error: true } : {}) });
  }
  messages.push({ role: "user", content: results });
}

Live mode loads the Anthropic TypeScript SDK only when you use it. It calls Claude Opus 5.5 by default with adaptive thinking, low effort and prompt caching, and opts into Anthropic's server-side fallback in case a request is declined. The key stays in the tab's memory and goes only to api.anthropic.com. I built the whole thing with Claude Code.

SEC. 05The Code

Every source file is readable on this site.

The 4 inch rule is a game rule, loosely based on common ice safety guidance. Always check local conditions before you go out on real ice.