Recursive QR tarpit lab
A controlled setting for studying recursive QR code chains: each code resolves to a page that embeds the next code, so a vision+tool agent must decode, fetch, and repeat until a terminal page.
Theory
- Recursive structure — The payload is an HTTP URL; the HTML at that URL embeds PNG QR images whose payloads continue the graph (linear, branch, cycle, or self-loop).
- Repetition penalty — Multimodal LLMs often down-rank repeated tokens. If every hop looks identical (same URL string, same black-on-white QR), the model may stall or loop even when the task is solvable. The lab can emit per-node URL query parameters (ignored by the server for routing) and deterministic visual variation (module size, border, colors, error correction) so each hop differs in both text and image channels while the graph semantics stay fixed.
- Mitigations — Hop limits, cycle detection, and no-progress guards are implemented in the harness so you can compare baseline runs against hardened policies.
Live demo
https://ahjc.me/qr — landing page; chain pages are under /qr/g/… (see deploy/qr-nginx.conf.example for nginx).
Use generate-assets --base-url https://ahjc.me/qr and serve --path-prefix /qr so payloads and HTML match this mount.
Experiment workflow
- Define scenarios in
scenarios.json(topology, depth, etc.). - Run
generate-assetswith your public--base-urland optional--variation-seed; omit--no-url-variation/--no-graphics-variationto enable divergence across hops. - Run
serve --path-prefix /qrbehind TLS (see nginx snippet), or--allow-publiconly for isolated testing. - Run the simulator or Ollama agent against manifests and collect JSON reports for analysis.
Implementation lives in the recursive-qr-tarpit-lab repository (Python package qr_tarpit_lab).