DEV Community

Charlie Zhu
Charlie Zhu

Posted on

The Gauge Block Workshop

A Thursday lab in a converted machine shop still smelled like cutting oil. Twelve laptops sat on a steel table that once held mill vises. An agent in a browser window announced it had paid invoice inv_2044. The chat log was confident. The ledger on disk had not moved.

The instructor opened a wooden drawer and set a 25 mm gauge block on the table. Hardened steel. One size. No opinions. Students were told the next ninety minutes would copy that habit into software: a fixture that does not drift while a model talks around it.

Modern coding agents outrun the quizzes people paste under them. A prompt can be rewritten until the paragraph looks finished. A JSON contract cannot. The workshop treats that gap as a shop-floor problem, not a philosophy seminar. Students leave with a tiny HTTP fixture, a caliper script, and a stubborn rule: the block is edited only between sessions, never during a demo.

What the ninety minutes are for

The class is built for people who already ship small services and now let an agent touch them. It is not a model bake-off. It is a dress rehearsal for the moment a teammate asks whether the agent actually called the endpoint it described.

The first ten minutes stay at the table. The instructor tells the invoice story once, then forbids anyone from opening a chat panel. Students copy two files onto disk and start a local listener. The next twenty minutes are spent reading the fixture the way a machinist reads an etching: path, cents, status, conflict code. Nothing in that file is clever. That is the point.

Minutes thirty through fifty belong to the caliper. Students run assertions against known-good bytes before any model is invited into the room. If the caliper fails, the block is wrong or the port is wrong. The agent is not yet a suspect. The last forty minutes put a deliberately weak client beside a slightly less weak one, then hang the same fixture on a shared loaner host so two laptops can argue about the same steel.

The block that does not move

Save the following as gauge_block.py. Students do not edit it during the first hour. The numbers are arbitrary. They are also law.

#!/usr/bin/env python3
"""gauge_block.py — known-good invoice fixture for a 90-minute lab."""
from http.server import BaseHTTPRequestHandler, HTTPServer
import json

INVOICE = {
    "id": "inv_2044",
    "currency": "USD",
    "cents": 1299,
    "status": "open",
}

class GaugeBlock(BaseHTTPRequestHandler):
    def log_message(self, fmt, *args):
        # Access logs become a second lesson later. Silence keeps the first hour honest.
        return

    def _send(self, code, body):
        raw = json.dumps(body, separators=(",", ":")).encode("utf-8")
        self.send_response(code)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(raw)))
        self.end_headers()
        self.wfile.write(raw)

    def do_GET(self):
        if self.path == "/invoice/inv_2044":
            self._send(200, INVOICE)
            return
        self._send(404, {"error": "unknown_block"})

    def do_POST(self):
        length = int(self.headers.get("Content-Length", "0"))
        payload = json.loads(self.rfile.read(length) or b"{}")
        if self.path == "/invoice/inv_2044/pay":
            if payload.get("cents") != INVOICE["cents"]:
                self._send(409, {
                    "error": "amount_mismatch",
                    "expected_cents": INVOICE["cents"],
                })
                return
            paid = dict(INVOICE)
            paid["status"] = "paid"
            self._send(200, paid)
            return
        self._send(404, {"error": "unknown_block"})

if __name__ == "__main__":
    HTTPServer(("127.0.0.1", 8044), GaugeBlock).serve_forever()
Enter fullscreen mode Exit fullscreen mode

Start it in one terminal and leave it running like a mill that has already been trammed.

python3 gauge_block.py
Enter fullscreen mode Exit fullscreen mode

A second file, caliper.py, is the measuring tool. It never prints poetry. It either holds or it does not.

#!/usr/bin/env python3
"""caliper.py — three touches against the gauge block."""
import json
import os
import urllib.error
import urllib.request

BASE = os.environ.get("GAUGE_BASE", "http://127.0.0.1:8044")

def get(path):
    with urllib.request.urlopen(BASE + path) as res:
        return res.status, json.loads(res.read().decode("utf-8"))

def post(path, body):
    req = urllib.request.Request(
        BASE + path,
        data=json.dumps(body).encode("utf-8"),
        headers={"Content-Type": "application/json"},
        method="POST",
    )
    try:
        with urllib.request.urlopen(req) as res:
            return res.status, json.loads(res.read().decode("utf-8"))
    except urllib.error.HTTPError as exc:
        return exc.code, json.loads(exc.read().decode("utf-8"))

def main():
    status, invoice = get("/invoice/inv_2044")
    assert status == 200, status
    assert invoice["cents"] == 1299, invoice
    assert invoice["status"] == "open", invoice

    status, conflict = post("/invoice/inv_2044/pay", {"cents": 1200})
    assert status == 409, status
    assert conflict["error"] == "amount_mismatch", conflict

    status, paid = post("/invoice/inv_2044/pay", {"cents": 1299})
    assert status == 200, status
    assert paid["status"] == "paid", paid
    print("gauge blocks hold")

if __name__ == "__main__":
    main()
Enter fullscreen mode Exit fullscreen mode
python3 caliper.py
Enter fullscreen mode Exit fullscreen mode

If that print never appears, the workshop stops. Nobody prompts a model to explain a downed port. The steel is checked first.

Two clients, one size

The next exercise is a pair of scripts that stand in for agent tools. Label them as lab stand-ins. They are not production payment code and they are not a claim about any vendor's hidden chain of thought.

guess_pay.py is the student who skipped the drawing. It posts a remembered number.

#!/usr/bin/env python3
"""guess_pay.py — lab stand-in for an agent that skips the GET."""
import json
import os
import urllib.request

BASE = os.environ.get("GAUGE_BASE", "http://127.0.0.1:8044")
body = json.dumps({"cents": 1300}).encode("utf-8")
req = urllib.request.Request(
    BASE + "/invoice/inv_2044/pay",
    data=body,
    headers={"Content-Type": "application/json"},
    method="POST",
)
try:
    urllib.request.urlopen(req)
    print("guess_pay: unexpected success")
except Exception as exc:
    print(f"guess_pay: blocked as designed ({exc})")
Enter fullscreen mode Exit fullscreen mode

measure_pay.py is the apprentice who uses the block. It reads, then pays the cents the fixture actually holds.

#!/usr/bin/env python3
"""measure_pay.py — lab stand-in for an agent that measures first."""
import json
import os
import urllib.request

BASE = os.environ.get("GAUGE_BASE", "http://127.0.0.1:8044")

with urllib.request.urlopen(BASE + "/invoice/inv_2044") as res:
    invoice = json.loads(res.read().decode("utf-8"))

body = json.dumps({"cents": invoice["cents"]}).encode("utf-8")
req = urllib.request.Request(
    BASE + "/invoice/inv_2044/pay",
    data=body,
    headers={"Content-Type": "application/json"},
    method="POST",
)
with urllib.request.urlopen(req) as res:
    paid = json.loads(res.read().decode("utf-8"))
print(json.dumps({"read_cents": invoice["cents"], "status": paid["status"]}))
Enter fullscreen mode Exit fullscreen mode

Run them in that order on a fresh server process. The guess should strike the 409. The measured client should print paid. Students who reverse the order learn a second shop rule: this particular block is a teaching size, not a ledger. Restart gauge_block.py between full passes so status does not leak from one pair into the next.

A short agent-loop sketch can sit beside those scripts. Keep it labeled as pseudocode for the last third of class. The loop is allowed to choose a tool name. It is not allowed to invent the cents.

# Lab sketch only — not executed as a networked agent in the first hour.
# for step in range(max_steps):
#     observation = get_invoice()
#     if observation["status"] == "open":
#         result = pay(cents=observation["cents"])
#     else:
#         break
# caliper_must_still_pass()
Enter fullscreen mode Exit fullscreen mode

The instructor watches for a familiar cheat: a student pastes the JSON into the prompt and asks the model to recite it back. Recitation is not measurement. The caliper still has to hit the socket.

Hang the same steel on a loaner bench

Localhost is a private vise. A class of twelve needs one object they can all close around. That is where a free shared host earns its keep, and where MonkeyCode belongs in this method rather than in the title of the hour.

Disclosure: This article was prepared as part of MonkeyCode's product outreach. MonkeyCode is an open-source project that offers free model access and a free server option. Those two facts are the only product claims this lab needs. The fixture above does not care which editor started the process. It cares that GAUGE_BASE points at one listener every laptop can reach.

Bind the workshop copy to a reachable interface on that loaner, keep the path names identical, and export the base URL as an environment variable. Students rerun the same caliper without rewriting assertions. The model, if used at all, is asked only to choose between guess_pay and measure_pay while the instructor reads the HTTP status line out loud.

export GAUGE_BASE="http://127.0.0.1:8044"   # replace with the loaner URL in class
python3 caliper.py
python3 guess_pay.py
# restart the block before the next line if status is already paid
python3 measure_pay.py
Enter fullscreen mode Exit fullscreen mode

The free server is a bench, not a promise about uptime, region, or hardware. The free model access is a way to draft the tool-choice prose after the caliper is green. If the caliper is red, the chat window stays closed. That single gate is the whole pedagogy.

Failure notes students should expect

A 409 on the measured client usually means a previous pair already paid the invoice. Restart the fixture. A hang on urlopen is almost always the wrong host or a firewall on the loaner. A 404 with unknown_block means a student pluralized /invoices because the model likes REST textbooks more than the drawing on the table.

Pretty-printed JSON will also break careless string compares. The fixture emits compact separators on purpose. Students who pretty-print the body in an editor are changing the block. The workshop treats that as filing steel off a gauge and starting over.

Limits, and who should skip the hour

The gauge block does not score reasoning, tone, or whether a refund policy was wise. It scores three HTTP touches. Teams that need load profiles, authn, idempotency keys, or multi-currency ledgers will outgrow this file in an afternoon, which is healthy. Harden a real service instead of stretching a teaching size until it looks like one.

Skip the format if the class cannot restart a process, if invoices in the org are not allowed to live in plaintext fixtures, or if someone expected a ranked model leaderboard. Skip it if the only available host would mix this lab with production secrets. A loaner bench that holds student homework should hold nothing else.

The steel on the table still helps after the laptops close. Write the size down. Run the caliper before the story. Let the agent talk only after the block holds. Classes that want that loop on a shared machine can park the same two files on MonkeyCode's free server and keep the models for the sentences that remain once the numbers are already true.

Top comments (1)

Collapse
 
mthburnsbarberweb profile image
mthburnsbarber-web

The gauge block metaphor is doing a lot of work here and it earns it. The whole insight — that a JSON contract cannot be prompted into a different answer — is exactly what makes this a structural approach rather than a testing philosophy.

The guess_pay vs measure_pay distinction is the clearest distillation I've seen of the "agent that reads before acting" principle. Running them in order on a fresh server and watching guess_pay hit the 409 is a lesson that sticks in a way that no amount of explanation would.

"If the caliper is red, the chat window stays closed" — this should be on a poster. The tendency to ask the model to explain away a failure rather than fix the underlying service is one of the most consistent anti-patterns in teams building with agents right now.

The note about the 404 with unknown_block coming from a student who pluralized /invoices because "the model likes REST textbooks more than the drawing on the table" is painfully accurate. Great workshop design.