A run — timeline, tool calls, meter, stop
Stop is a request, not a fact. Start a run, then press Stop. The panel does
not say "stopped" — it says Stopping… and waits, because the button cannot halt a
process it does not own. This demo plays the part of a host that takes about a second to
wind down, then calls
run.stopped(). Only then does the state change. A panel
that flips to "stopped" on click is lying about work that is very often still running.
The run is a ledger. When it ends, nothing disappears: the steps that never ran are
drawn hollow and dashed and counted in the footer line, the tool calls stay open for
reading, and a failure opens itself so you do not have to go looking. Toggle pricing
to see the other half of that rule — with no rate supplied the meter says
not priced in words rather than inventing a dollar figure.
Event log
waiting for something to happen…
The whole component — two files
<link rel="stylesheet" href="agent-run.css">
<script src="agent-run.js"></script>
<div class="ar-root" data-ar-theme="light"><div id="panel"></div></div>
<script>
var run = AgentRun.mount('#panel', {
title: 'Stage the drop',
sub: 'Ora · claude-opus-5',
steps: ['Read the catalog', 'Write the files', 'Verify', 'Stage'],
rate: { in: 5, out: 25 } // $ per 1M tokens — omit and the meter says "not priced"
});
run.begin();
run.start('s1');
var call = run.tool('s1', { name: 'read_file', args: { path: 'catalog.json' } });
run.toolDone(call, { result: '24 assets' }); // duration is MEASURED, never assumed
run.tokens(1204, 318);
run.done('s1');
// Stop is a request. The panel goes to "stopping" and waits for you.
document.addEventListener('agentrun:stop', function (e) {
killTheWorker(function () { run.stopped(); }); // only you can say it halted
});
run.complete(); // or run.stopped() / run.crashed('reason')
</script>