← The Loop
· WEEK 31 · 5 min

Building Spectroscope, part 3: one core, many faces, one stream

TL;DR

A ten-stage teaching workshop built a harness from scratch, and one design decision carried the whole course: a typed JSONL event stream that is API, storage format, UI protocol and audit log at once.

The request I typed on day one was concrete: an agent harness from scratch, as a graded teaching workshop, with CLI, desktop and web faces, cron, sub-agents, "a cool graph view to see the interaction with the LLM." The answer was a ten-stage workshop (plus six bonus stages) in which every stage ends with something runnable. Stage 2, the agentic loop, is called the heart in the course material. Stage 8, the graph view, is the showcase.

the one decisionstdout
RunEvent stream — typed JSONL, append-only

  the same stream is:
    the API           faces subscribe to it
    the storage       a session IS its file
    the UI protocol   every view renders from it
    the audit log     nothing happens off-stream

  8 blocks of a harness: context/sessions · sub-agents · hooks ·
  skills · MCP · tools · providers · permissions
fig. 01 — The workshop README's own claim: this single design decision carries the entire course.

Then the harness grew past the course. A web face with a design switcher and live mid-session provider swaps. Sub-agents, each modelled as its own agent loop and streamed into the same JSONL. A one-day completion pack landed the real tools (edit_file, grep, glob, web_fetch) plus prompt caching and pre/post tool hooks. The gate closed green at 309 JUnit and 152 vitest tests.

the shapeimage
One core five faces architecture diagram
fig. 02 — One core, many faces: every surface is a subscriber of the same event stream.

The moment that mattered most was a single chat message I sent in the middle of it: build an interactive mode, like a Petri net, where you can see which JSONL message is being made right now. That request became the Lab: chat on the left, a live graph of app, bash, permissions and LLM on the right, a JSONL trace you step through one line at a time. The Lab's documentation contains my favourite line of the whole project: "the net literally counts the session file." The animation is not a mock-up of a run. It is the run, replayed from its own log. That one feature is the direct conceptual ancestor of the product this series is about.

One more thing, because it proves the thesis better than any demo. For the story writeup, the archived workshop repo was checked out at its early-July commit and compiled, and the sessions in its sidebar were still replayable, tool cards unfolding with their real inputs and outputs. Software from week one, reading its own history. I did not expect that to feel as good as it did.

day one, replayedimage
Screenshot of the day-one permission gate
fig. 03 — The permission gate on day one: run_command allowed for ls, denied for rm. The gate spectroscope now answers across a fleet started as this single amber box.

What I'd do differently

Replay archived sessions in CI. Rebuilding the old commit surfaced a graph-view crash that only triggered on archived sessions. Live ones were fine, which is exactly why it shipped. The fix existed weeks later, but nobody had written the bug down. A replay test over stored sessions would have caught it the same day.