AgentStateGraph / app /src /content /embeds /system-overview.html
seonglae's picture
article: add howpublished to bibtex (+ asg: sync latest, favicon/links)
2db2783
Raw
History Blame Contribute Delete
11.7 kB
<!-- System / data-flow diagram. LEFT->RIGHT: how the machine is BUILT (construction,
offline): raw traces -> phi abstraction -> prefix tree -> one merge -> automaton.
RIGHT: how the machine is USED at runtime by four consumers (what each reads from it).
No result metrics — this shows data flow and execution flow, not numbers.
Self-contained SVG; themed via the article's --asg-* CSS variables (dark-mode safe). -->
<div class="asg-sys" id="asg-sys">
<svg viewBox="0 0 960 460" role="img"
aria-label="Construction pipeline: agent traces are abstracted by phi into activity sequences, accumulated into a prefix tree, and merged once into a single automaton. At runtime the same machine is read by four consumers: workflow memory, next-step prediction, failure prediction, and runtime monitoring.">
<defs>
<marker id="sys-arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M0 1 L9 5 L0 9 z" class="sys-arrowhead"/>
</marker>
</defs>
<!-- ===================== connectors (behind boxes) ===================== -->
<g class="sys-links" fill="none">
<path class="lnk" d="M150 226 H172" marker-end="url(#sys-arrow)"/>
<path class="lnk" d="M276 226 H300" marker-end="url(#sys-arrow)"/>
<path class="lnk lnk-key" d="M416 226 H466" marker-end="url(#sys-arrow)"/>
<!-- fan-out from FSM hub to four consumers -->
<path class="spoke" data-task="0" d="M622 200 C648 200 642 54 664 54"/>
<path class="spoke" data-task="1" d="M622 216 C648 216 642 166 664 166"/>
<path class="spoke" data-task="2" d="M622 236 C648 236 642 278 664 278"/>
<path class="spoke" data-task="3" d="M622 252 C648 252 642 390 664 390"/>
</g>
<!-- operation labels above the construction arrows (clear of the box band) -->
<text class="op-label" x="288" y="181" text-anchor="middle">build trie</text>
<text class="op-label op-key" x="430" y="181" text-anchor="middle">merge states</text>
<!-- ===================== construction spine ===================== -->
<!-- agent traces (input data) -->
<g class="node node-src" data-stage="src">
<rect x="14" y="170" width="136" height="112" rx="10"/>
<text class="n-title" x="82" y="192" text-anchor="middle">Agent traces</text>
<text class="n-sub" x="82" y="208" text-anchor="middle">messages · tool calls</text>
<g class="chips">
<rect x="28" y="220" width="50" height="17" rx="4" class="chip"/>
<text class="chip-t" x="53" y="232" text-anchor="middle">coding</text>
<rect x="86" y="220" width="50" height="17" rx="4" class="chip"/>
<text class="chip-t" x="111" y="232" text-anchor="middle">web</text>
<rect x="28" y="241" width="50" height="17" rx="4" class="chip"/>
<text class="chip-t" x="53" y="253" text-anchor="middle">GUI</text>
<rect x="86" y="241" width="50" height="17" rx="4" class="chip"/>
<text class="chip-t" x="111" y="253" text-anchor="middle">telecom</text>
</g>
</g>
<!-- phi: the one transform (message -> symbol) -->
<g class="node node-phi" data-stage="phi">
<rect x="174" y="194" width="102" height="64" rx="10"/>
<text class="n-glyph" x="225" y="220" text-anchor="middle">&#966;</text>
<text class="n-sub" x="225" y="238" text-anchor="middle">message &#8594; symbol</text>
<text class="n-foot" x="225" y="250" text-anchor="middle">deterministic</text>
</g>
<!-- prefix tree (intermediate data structure) -->
<g class="node node-pta" data-stage="pta">
<rect x="302" y="194" width="114" height="64" rx="10"/>
<text class="n-title" x="359" y="218" text-anchor="middle">Prefix tree</text>
<text class="n-sub" x="359" y="234" text-anchor="middle">PTA</text>
<text class="n-foot" x="359" y="248" text-anchor="middle">one branch per trace</text>
</g>
<!-- FSM hub (the artifact every consumer reads) -->
<g class="node node-fsm" data-stage="fsm">
<rect x="470" y="158" width="152" height="136" rx="14"/>
<text class="hub-eyebrow" x="546" y="182" text-anchor="middle">ONE PER AGENT</text>
<text class="hub-title" x="546" y="206" text-anchor="middle">Automaton</text>
<g class="hub-mini">
<circle cx="508" cy="232" r="8"/>
<circle cx="546" cy="248" r="8"/>
<circle cx="584" cy="232" r="8" class="hub-mini-accept"/>
<path d="M515 234 L539 245" class="hub-edge"/>
<path d="M553 245 L577 234" class="hub-edge"/>
<path d="M516 229 C530 218 562 218 576 229" class="hub-edge"/>
</g>
<text class="hub-foot" x="546" y="274" text-anchor="middle">states +</text>
<text class="hub-foot" x="546" y="286" text-anchor="middle">transition probabilities</text>
</g>
<!-- ===================== four runtime consumers ===================== -->
<g class="task" data-task="0">
<rect x="664" y="8" width="284" height="92" rx="11"/>
<text class="t-title" x="684" y="40">Workflow memory</text>
<text class="t-sub" x="684" y="62">state &#8594; likely next actions,</text>
<text class="t-sub" x="684" y="80">injected into the agent's prompt</text>
</g>
<g class="task" data-task="1">
<rect x="664" y="120" width="284" height="92" rx="11"/>
<text class="t-title" x="684" y="152">Next-step prediction</text>
<text class="t-sub" x="684" y="174">reads P(next action | current</text>
<text class="t-sub" x="684" y="192">state) off the machine</text>
</g>
<g class="task" data-task="2">
<rect x="664" y="232" width="284" height="92" rx="11"/>
<text class="t-title" x="684" y="264">Failure prediction</text>
<text class="t-sub" x="684" y="286">replay a run &#8594; per-state</text>
<text class="t-sub" x="684" y="304">features &#8594; classifier</text>
</g>
<g class="task" data-task="3">
<rect x="664" y="344" width="284" height="92" rx="11"/>
<text class="t-title" x="684" y="376">Runtime monitor</text>
<text class="t-sub" x="684" y="398">online conformance check,</text>
<text class="t-sub" x="684" y="416">flags drift mid-run</text>
</g>
<!-- phase captions -->
<text class="phase" x="300" y="312" text-anchor="middle">CONSTRUCTION &#183; built once, offline</text>
<text class="phase" x="806" y="452" text-anchor="middle">USED AT RUNTIME &#183; per execution</text>
</svg>
</div>
<style>
.asg-sys { width: 100%; font-family: inherit; padding: 6px 0 2px; }
.asg-sys svg { width: 100%; height: auto; display: block; overflow: visible; }
/* boxes */
.asg-sys .node rect {
fill: var(--surface-bg, #f9f9f9);
stroke: var(--border-color, rgba(0,0,0,0.14));
stroke-width: 1.2;
transition: stroke .2s, fill .2s;
}
.asg-sys .node-fsm rect {
fill: color-mix(in srgb, var(--asg-ours, #3d5a80) 9%, var(--page-bg, #fff));
stroke: var(--asg-ours, #3d5a80);
stroke-width: 1.8;
}
/* text */
.asg-sys text { font-family: inherit; }
.asg-sys .n-title { font-size: 13px; font-weight: 650; fill: var(--text-color, #1a1a2e); }
.asg-sys .n-sub { font-size: 10px; fill: var(--muted-color, rgba(0,0,0,0.55)); }
.asg-sys .n-foot { font-size: 9px; fill: var(--muted-color, rgba(0,0,0,0.5)); font-family: var(--font-mono, ui-monospace, monospace); }
.asg-sys .n-glyph { font-size: 23px; font-style: italic; font-weight: 600; fill: var(--asg-ours, #3d5a80); }
.asg-sys .chip { fill: color-mix(in srgb, var(--asg-ours, #3d5a80) 12%, transparent); stroke: none; }
.asg-sys .chip-t { font-size: 9px; fill: var(--text-color, #1a1a2e); font-family: var(--font-mono, ui-monospace, monospace); }
/* operation labels on construction arrows */
.asg-sys .op-label { font-size: 9px; fill: var(--muted-color, rgba(0,0,0,0.6)); font-family: var(--font-mono, ui-monospace, monospace); letter-spacing: .3px; }
.asg-sys .op-key { fill: var(--asg-ours, #3d5a80); font-weight: 600; }
/* FSM hub */
.asg-sys .hub-eyebrow { font-size: 9px; letter-spacing: 1.6px; fill: var(--asg-ours, #3d5a80); font-weight: 600; }
.asg-sys .hub-title { font-size: 16px; font-weight: 700; fill: var(--text-color, #1a1a2e); }
.asg-sys .hub-foot { font-size: 9px; fill: var(--muted-color, rgba(0,0,0,0.6)); font-family: var(--font-mono, ui-monospace, monospace); }
.asg-sys .hub-mini circle { fill: var(--page-bg, #fff); stroke: var(--asg-ours, #3d5a80); stroke-width: 1.4; }
.asg-sys .hub-mini-accept { fill: color-mix(in srgb, var(--asg-ours, #3d5a80) 22%, var(--page-bg, #fff)) !important; }
.asg-sys .hub-edge { stroke: var(--asg-ours, #3d5a80); stroke-width: 1.2; fill: none; opacity: .7; }
/* connectors */
.asg-sys .lnk { stroke: var(--muted-color, rgba(0,0,0,0.45)); stroke-width: 1.4; }
.asg-sys .lnk-key { stroke: var(--asg-ours, #3d5a80); }
.asg-sys .sys-arrowhead { fill: var(--muted-color, rgba(0,0,0,0.55)); }
.asg-sys .spoke {
stroke: color-mix(in srgb, var(--asg-ours, #3d5a80) 38%, transparent);
stroke-width: 1.6;
transition: stroke .2s, stroke-width .2s;
}
/* consumer cards */
.asg-sys .task rect {
fill: var(--surface-bg, #f9f9f9);
stroke: var(--border-color, rgba(0,0,0,0.12));
stroke-width: 1.2;
transition: stroke .2s, fill .2s;
}
.asg-sys .t-title { font-size: 16px; font-weight: 640; fill: var(--text-color, #1a1a2e); }
.asg-sys .t-sub { font-size: 13px; fill: var(--muted-color, rgba(0,0,0,0.6)); }
/* phase captions */
.asg-sys .phase { font-size: 8.5px; letter-spacing: 1.2px; fill: var(--muted-color, rgba(0,0,0,0.45)); font-family: var(--font-mono, ui-monospace, monospace); }
/* hover: light up a spoke + its consumer card */
.asg-sys .task.is-hot rect { stroke: var(--asg-ours, #3d5a80); fill: color-mix(in srgb, var(--asg-ours, #3d5a80) 7%, var(--page-bg, #fff)); }
.asg-sys .spoke.is-hot { stroke: var(--asg-ours, #3d5a80); stroke-width: 2.4; }
/* entrance */
.asg-sys .node, .asg-sys .task, .asg-sys .sys-links, .asg-sys .op-label, .asg-sys .phase { opacity: 0; animation: sys-in .5s ease forwards; }
.asg-sys .sys-links { animation-delay: .05s; }
.asg-sys .node-src { animation-delay: .04s; }
.asg-sys .node-phi { animation-delay: .12s; }
.asg-sys .node-pta { animation-delay: .20s; }
.asg-sys .op-label { animation-delay: .24s; }
.asg-sys .node-fsm { animation-delay: .30s; }
.asg-sys .task[data-task="0"] { animation-delay: .44s; }
.asg-sys .task[data-task="1"] { animation-delay: .52s; }
.asg-sys .task[data-task="2"] { animation-delay: .60s; }
.asg-sys .task[data-task="3"] { animation-delay: .68s; }
.asg-sys .phase { animation-delay: .72s; }
@keyframes sys-in { to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
.asg-sys .node, .asg-sys .task, .asg-sys .sys-links, .asg-sys .op-label, .asg-sys .phase { animation: none; opacity: 1; }
}
</style>
<script>
(function () {
const root = document.getElementById('asg-sys');
if (!root || root.dataset.wired) return;
root.dataset.wired = '1';
const tasks = Array.from(root.querySelectorAll('.task'));
const spokes = Array.from(root.querySelectorAll('.spoke'));
function hot(i, on) {
tasks[i] && tasks[i].classList.toggle('is-hot', on);
const sp = spokes.find(s => s.getAttribute('data-task') === String(i));
sp && sp.classList.toggle('is-hot', on);
}
tasks.forEach((t, i) => {
t.addEventListener('mouseenter', () => hot(i, true));
t.addEventListener('mouseleave', () => hot(i, false));
});
})();
</script>