Watching Agents Work

Watching Agents Work

ai agents claude-code tools engineering

Six agents go off to research something. Twenty minutes pass. You sit there.

The terminal says nothing useful. Two of those agents are stuck on a question only you can answer, and they will either guess or sit there waiting. You find out which when the whole thing finishes.

That is the bad version. I got tired of the bad version.

So I built a dashboard the agents write to but never draw, packaged it as a skill for Claude Code, Codex and grok, and then spent most of the day letting strangers try to kill it.

The one design decision that mattered

Agents are terrible at drawing.

Ask one to produce a status page and you get a wall of markdown, a half-closed div, and a layout that changes every time it reports. Ask six and you get six different walls.

So they do not draw. They write JSON through one command line tool, and that tool owns the schema, the identifiers, the atomic writes and every pixel of the page. An agent’s entire vocabulary is this:

sprint.py log RUN market "pulled six listings"

sprint.py add RUN market evidence \
  --claim "Rate is 14 dollars per square foot" \
  --source "broker-sheet.pdf p.2" \
  --date 2026-09-20

sprint.py add RUN market ask \
  --question "Is a six month gap acceptable?" \
  --option "No gap" --option "Up to 3 months"

The page is a rendered view of a directory. Nothing improvises markup. That one constraint is what keeps a twenty minute run legible instead of a pile of half-formatted output.

What needs you goes first

The first version put the finished answers at the top, because finished answers feel like the deliverable. A reviewer measured it: at a normal laptop window the panel with the questions started 586 pixels down the page. Below the fold. The one thing on the page that needed a human was the one thing a human would not see.

Now it is the first block, and it costs one line when there is nothing waiting.

Three question cards, each with its agent, its options, and what happens if nobody answers

Each question carries what happens if you never answer it. “Assumes no gap, which removes both cheap options.” The agent does not block. It proceeds on the stated default and says so, and if you click something in the next five minutes it uses your answer instead.

That is the whole trick. Not “ask the human”, which is just an interruption with better manners. Ask, state what you will do otherwise, and keep going.

Three rules the tool enforces

Prompts that say “be rigorous” produce agents that say they were rigorous.

So the tool refuses instead:

A default is a decision you would defend, and it must state the cost of being wrong. --cost-if-wrong is required, and a one word answer fails the check. If you cannot state the cost, it is a guess, and a guess gets reported as an unknown.

Evidence needs a source and a date. Both required. And it gets shown, not counted. An early version displayed “1 sourced claim” on the card and put the actual claim, source and quote nowhere at all. A reviewer caught that one and it stung, because I had enforced the rule against the agents and then hidden the result from the person who has to decide.

The evidence table with its claim, quote, source and date, the open unknowns, and the defaults with their cost if wrong

Agents log as they go. An agent that writes one update when it finishes leaves a dead card on screen for twenty minutes, which is worse than no dashboard at all.

Then I let strangers kill it

Here is the part I would repeat on anything that matters.

I gave the zipped package to three fresh agents with no context from me at all. No explanation, no reasoning, no “here is what I was going for”. Just the artifact, and instructions to break it and return a verdict of KILL, WOUND or SURVIVES.

Four reviews. Three of them came back KILL.

The first one found that an agent named ../../escaped wrote files outside the run directory, and that thirty writers working at once kept seven of thirty rows without a single error message. Silent data loss in a tool whose entire reason to exist is many agents writing at once.

The second found that the launch instructions in the documentation were not valid shell. MODEL=<a cheaper model> reads fine to a human and is a syntax error to bash. The fan-out loop never ran.

The third found that the command line built its objects in code and skipped its own validation, so an empty claim and a whitespace verdict both reached disk, and one bad row blanked every answer on the page.

None of these were in my head. I wrote the thing. I had run it. Three separate reviewers with no investment in my reasoning found in an hour what I would not have found in a week, because I was busy admiring the parts that worked.

The fix for the third killing is the one I like: the package now executes its own documentation. Every shell block in every instruction file gets extracted and run in a sandbox with the agent launcher stubbed out. Documentation that does not run is a failing test.

What it cost to be honest

The Codex version of the skill has never completed a real run, because that account is out of credits. The launch command is proven at the shell level and nothing more.

That sentence is in the README, in the release notes, and now here. It was tempting to leave it out. A reader who installs the Codex version and hits a wall deserves to have been told.

Take it

The skill is at github.com/lswank/streaming-sprint-dashboard, MIT licensed, with a release you can unzip and install into Claude Code, Codex or grok in one command. Python 3.10 and up, standard library only, no network access.

Run sprint.py demo and you will see the page in about five seconds.

And when you finish something you are proud of, hand it to someone who has no idea why you made any of the choices you made. Then listen to them tell you it is broken.