- Input/Output/Memorizer nodes with OpenRouter (Gemini Flash) - Zitadel OIDC auth with PKCE flow, service token for Titan - SSE event stream + poll endpoint for external observers - Identity from Zitadel userinfo, listener context in Input prompt - Trace logging to file + SSE broadcast - K3s deployment on IONOS with Let's Encrypt TLS - Frontend: chat + trace view, OIDC login Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
484 lines
27 KiB
HTML
484 lines
27 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Cognitive Runtime — Design Exploration</title>
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body { font-family: system-ui, sans-serif; background: #0a0a0a; color: #d4d4d4; line-height: 1.6; }
|
|
.page { max-width: 1400px; margin: 0 auto; padding: 2rem; }
|
|
h1 { color: #f59e0b; font-size: 1.6rem; margin-bottom: 0.5rem; }
|
|
h2 { color: #60a5fa; font-size: 1.2rem; margin: 2rem 0 0.75rem; border-bottom: 1px solid #222; padding-bottom: 0.3rem; }
|
|
h3 { color: #34d399; font-size: 1rem; margin: 1.2rem 0 0.5rem; }
|
|
p, li { font-size: 0.9rem; }
|
|
ul { padding-left: 1.2rem; margin: 0.3rem 0; }
|
|
li { margin: 0.2rem 0; }
|
|
.subtitle { color: #888; font-size: 0.85rem; margin-bottom: 2rem; }
|
|
code { background: #1a1a2e; padding: 0.1rem 0.4rem; border-radius: 0.2rem; font-size: 0.85rem; color: #a78bfa; }
|
|
|
|
/* Three-column sections */
|
|
.three-col { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 1rem; margin: 1rem 0; }
|
|
.card { background: #111; border: 1px solid #222; border-radius: 0.5rem; padding: 1rem; }
|
|
.card h3 { margin-top: 0; }
|
|
.card.amber { border-color: #f59e0b33; }
|
|
.card.blue { border-color: #60a5fa33; }
|
|
.card.green { border-color: #34d39933; }
|
|
.card.purple { border-color: #a78bfa33; }
|
|
.card.red { border-color: #ef444433; }
|
|
|
|
/* Graph visualization */
|
|
.graph { background: #0f0f1a; border: 1px solid #222; border-radius: 0.5rem; padding: 1.5rem; margin: 1rem 0; font-family: monospace; font-size: 0.8rem; white-space: pre; line-height: 1.4; overflow-x: auto; }
|
|
.graph .sensor { color: #f59e0b; }
|
|
.graph .controller { color: #60a5fa; }
|
|
.graph .effector { color: #34d399; }
|
|
.graph .memory { color: #a78bfa; }
|
|
.graph .feedback { color: #f472b6; }
|
|
.graph .arrow { color: #555; }
|
|
|
|
/* Test cases table */
|
|
table { width: 100%; border-collapse: collapse; margin: 1rem 0; font-size: 0.85rem; }
|
|
th { text-align: left; padding: 0.5rem; background: #1a1a2e; color: #60a5fa; border-bottom: 2px solid #333; }
|
|
td { padding: 0.5rem; border-bottom: 1px solid #1a1a1a; }
|
|
tr:hover td { background: #111; }
|
|
.tag { display: inline-block; padding: 0.1rem 0.4rem; border-radius: 0.2rem; font-size: 0.7rem; font-weight: 600; }
|
|
.tag.now { background: #22c55e22; color: #22c55e; }
|
|
.tag.next { background: #f59e0b22; color: #f59e0b; }
|
|
.tag.later { background: #60a5fa22; color: #60a5fa; }
|
|
.tag.node { background: #a78bfa22; color: #a78bfa; }
|
|
|
|
/* Roadmap */
|
|
.phase { display: flex; gap: 1rem; align-items: flex-start; margin: 0.75rem 0; padding: 0.75rem; background: #111; border-radius: 0.5rem; border-left: 3px solid #333; }
|
|
.phase.active { border-left-color: #22c55e; }
|
|
.phase.planned { border-left-color: #f59e0b; }
|
|
.phase.future { border-left-color: #60a5fa; }
|
|
.phase-num { font-size: 1.5rem; font-weight: 700; color: #333; min-width: 2rem; }
|
|
.phase.active .phase-num { color: #22c55e; }
|
|
.phase.planned .phase-num { color: #f59e0b; }
|
|
.phase.future .phase-num { color: #60a5fa; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="page">
|
|
|
|
<h1>Cognitive Agent Runtime — Design Exploration</h1>
|
|
<div class="subtitle">Node graph architecture grounded in cybernetics, Cynefin, actor-network theory, and signal processing</div>
|
|
|
|
<!-- ================================================================== -->
|
|
<h2>Theoretical Grounding</h2>
|
|
|
|
<div class="three-col">
|
|
<div class="card amber">
|
|
<h3>Cybernetics (Wiener, Ashby, Beer)</h3>
|
|
<p><strong>Core idea:</strong> systems that regulate themselves through feedback loops.</p>
|
|
<ul>
|
|
<li><strong>Ashby's Law of Requisite Variety</strong> — the controller must have at least as much variety as the disturbance. One monolithic agent fails because it can't match the variety of all inputs. Specialized nodes CAN.</li>
|
|
<li><strong>Viable System Model (Beer)</strong> — every viable system has 5 subsystems: Operations (Output), Coordination (Router), Control (Input), Intelligence (Thinker), Policy (human/config). Our graph maps directly.</li>
|
|
<li><strong>Homeostasis</strong> — the system maintains stability through feedback. The I/O Feedback node IS the homeostatic loop — detecting drift, repeated failures, frustration.</li>
|
|
<li><strong>Circular causality</strong> — output affects input. The user's next message is shaped by the response. The graph must be a loop, not a pipeline.</li>
|
|
</ul>
|
|
<p style="margin-top:0.5rem;color:#f59e0b;font-size:0.8rem;"><strong>Design takeaway:</strong> Every node is either a sensor, controller, or effector. Missing any breaks the feedback loop.</p>
|
|
</div>
|
|
|
|
<div class="card blue">
|
|
<h3>Cynefin (Snowden)</h3>
|
|
<p><strong>Core idea:</strong> different problem domains need different response strategies.</p>
|
|
<ul>
|
|
<li><strong>Clear</strong> — "what time is it?" → sense-categorize-respond. Input routes directly to Output, no Thinker needed. Fast.</li>
|
|
<li><strong>Complicated</strong> — "how do I deploy to K3s?" → sense-analyze-respond. Input routes to Thinker with tools. Expert knowledge.</li>
|
|
<li><strong>Complex</strong> — "should we use microservices?" → probe-sense-respond. Thinker explores, Memorizer tracks evolving understanding. No single right answer.</li>
|
|
<li><strong>Chaotic</strong> — system is down, user panicking → act-sense-respond. Output responds FIRST (acknowledge), then Input figures out what happened.</li>
|
|
<li><strong>Confused</strong> — unclear what domain we're in → Input's primary job! Classify before routing.</li>
|
|
</ul>
|
|
<p style="margin-top:0.5rem;color:#60a5fa;font-size:0.8rem;"><strong>Design takeaway:</strong> Input node IS the Cynefin classifier. Different domains = different graph paths.</p>
|
|
</div>
|
|
|
|
<div class="card green">
|
|
<h3>Actor-Network Theory (Latour)</h3>
|
|
<p><strong>Core idea:</strong> capability emerges from the network, not individual actors.</p>
|
|
<ul>
|
|
<li><strong>Actants</strong> — both human and non-human entities have agency. Each node is an actant. The user is an actant. The LLM API is an actant.</li>
|
|
<li><strong>Translation</strong> — messages change form as they pass through the network. User text → envelope → command → LLM prompt → stream → display. Each node translates.</li>
|
|
<li><strong>Irreducibility</strong> — you can't reduce the system to one actor. No single node "is" the agent. The GRAPH is the agent.</li>
|
|
<li><strong>Enrollment</strong> — new nodes join the network as needed. Tool nodes, sensor nodes, human-in-the-loop nodes. The graph grows.</li>
|
|
</ul>
|
|
<p style="margin-top:0.5rem;color:#34d399;font-size:0.8rem;"><strong>Design takeaway:</strong> The graph IS the intelligence. Nodes are replaceable. Edges are where meaning happens.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ================================================================== -->
|
|
<h2>Node Taxonomy (from signal processing + cybernetics)</h2>
|
|
|
|
<div class="three-col">
|
|
<div class="card amber">
|
|
<h3>Sensors (perceive)</h3>
|
|
<ul>
|
|
<li><strong>Input</strong> — user message sensor</li>
|
|
<li><strong>Timer</strong> — periodic trigger (cron, polling)</li>
|
|
<li><strong>Webhook</strong> — external event sensor</li>
|
|
<li><strong>FileWatch</strong> — filesystem change sensor</li>
|
|
<li><strong>SystemProbe</strong> — health/load sensor</li>
|
|
</ul>
|
|
<p style="color:#888;font-size:0.75rem;margin-top:0.5rem;">Like a webcam node in TouchDesigner. Always on, emits when something happens.</p>
|
|
</div>
|
|
|
|
<div class="card blue">
|
|
<h3>Controllers (decide + transform)</h3>
|
|
<ul>
|
|
<li><strong>Classifier</strong> — categorize input (Cynefin domain, intent, tone)</li>
|
|
<li><strong>Router</strong> — direct to different paths based on classification</li>
|
|
<li><strong>Thinker</strong> — deep reasoning, tool use</li>
|
|
<li><strong>Filter</strong> — reduce, summarize, extract</li>
|
|
<li><strong>Accumulator</strong> — aggregate over time (topic tracker)</li>
|
|
</ul>
|
|
<p style="color:#888;font-size:0.75rem;margin-top:0.5rem;">Like filter/transform nodes in Max/MSP. Shape the signal.</p>
|
|
</div>
|
|
|
|
<div class="card green">
|
|
<h3>Effectors (act)</h3>
|
|
<ul>
|
|
<li><strong>Output</strong> — stream text to user</li>
|
|
<li><strong>Feedback</strong> — emit HUD/status events</li>
|
|
<li><strong>ToolExec</strong> — execute external tools</li>
|
|
<li><strong>Writer</strong> — persist to storage</li>
|
|
<li><strong>Notifier</strong> — push to external systems</li>
|
|
</ul>
|
|
<p style="color:#888;font-size:0.75rem;margin-top:0.5rem;">Like output nodes in Unreal Blueprints. Make something happen in the world.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card purple" style="margin:1rem 0;">
|
|
<h3>Memory (special: both reads and writes)</h3>
|
|
<ul>
|
|
<li><strong>Memorizer</strong> — working memory, session history, user facts (SQLite/JSON)</li>
|
|
<li><strong>TopicTracker</strong> — maintains list of active conversation topics</li>
|
|
<li><strong>ContextBuilder</strong> — assembles the right context for each node on demand</li>
|
|
</ul>
|
|
<p style="color:#888;font-size:0.75rem;margin-top:0.5rem;">Memory nodes are unique: they're called BY other nodes, not just wired in sequence. They're shared state — the "blackboard" in classic AI.</p>
|
|
</div>
|
|
|
|
<!-- ================================================================== -->
|
|
<h2>Graph Architecture — Full Vision</h2>
|
|
|
|
<div class="graph">
|
|
<span class="arrow"> ┌─────────────────────────────────────────────────┐</span>
|
|
<span class="arrow"> │ │</span>
|
|
<span class="arrow"> ▼ │</span>
|
|
<span class="sensor"> [User WS] ──► [Input/Classifier]</span><span class="arrow"> ──┬──────────────────────────┐ │</span>
|
|
<span class="arrow"> │ │ │ │</span>
|
|
<span class="arrow"> │ ┌─────────┘ │ │</span>
|
|
<span class="arrow"> │ │ </span><span class="feedback">Cynefin routing</span><span class="arrow"> │ │</span>
|
|
<span class="arrow"> │ │ │ │</span>
|
|
<span class="arrow"> </span><span class="feedback">Clear:</span><span class="arrow"> │ │ </span><span class="controller">Complicated/Complex:</span><span class="arrow"> │ │</span>
|
|
<span class="arrow"> (skip │ │ ▼ │</span>
|
|
<span class="arrow"> thinker) │ ▼ </span><span class="memory">[Memorizer]</span><span class="arrow"> │</span>
|
|
<span class="arrow"> │ </span><span class="controller">[Thinker]</span><span class="arrow"> ◄── context ──────── </span><span class="memory"> │ </span><span class="arrow"> │</span>
|
|
<span class="arrow"> │ │ │ </span><span class="memory"> ▲ </span><span class="arrow"> │</span>
|
|
<span class="arrow"> │ │ └──── memory updates ──────── </span><span class="memory"> │ </span><span class="arrow"> │</span>
|
|
<span class="arrow"> │ │ │ │ │</span>
|
|
<span class="arrow"> │ │ └──► </span><span class="effector">[ToolExec]</span><span class="arrow"> ─── results ──► │ │</span>
|
|
<span class="arrow"> │ │ │</span>
|
|
<span class="arrow"> ▼ ▼ │</span>
|
|
<span class="arrow"> </span><span class="effector">[Output]</span><span class="arrow"> ──► [User WS] (stream delta/done) │</span>
|
|
<span class="arrow"> │ │</span>
|
|
<span class="arrow"> └──► </span><span class="feedback">[Feedback]</span><span class="arrow"> ──► [User WS] (hud events) │</span>
|
|
<span class="arrow"> │ │</span>
|
|
<span class="arrow"> └──► </span><span class="feedback">[I/O Monitor]</span><span class="arrow"> ── hints ──────────┘</span>
|
|
<span class="arrow"> │</span>
|
|
<span class="sensor"> [Timer] ──────────────────────────────►│</span>
|
|
<span class="sensor"> [Webhook] ────────────────────────────►│</span>
|
|
<span class="sensor"> [SystemProbe] ────────────────────────►│</span>
|
|
<span class="arrow"> │</span>
|
|
<span class="arrow"> ▼</span>
|
|
<span class="arrow"> </span><span class="memory">[TopicTracker]</span><span class="arrow"> ──► [UI: topic list, action buttons]</span>
|
|
</div>
|
|
|
|
<!-- ================================================================== -->
|
|
<h2>Node-Based Programming Analogy</h2>
|
|
|
|
<div class="three-col">
|
|
<div class="card">
|
|
<h3>TouchDesigner / Max/MSP</h3>
|
|
<ul>
|
|
<li>Webcam → filter → skeleton detector → output display</li>
|
|
<li><strong>Always running</strong> — not request/response</li>
|
|
<li>Nodes have typed inputs/outputs</li>
|
|
<li>Graph is the program</li>
|
|
</ul>
|
|
</div>
|
|
<div class="card">
|
|
<h3>ComfyUI (Stable Diffusion)</h3>
|
|
<ul>
|
|
<li>Prompt → CLIP → sampler → VAE → image</li>
|
|
<li>Each node: one model, one job</li>
|
|
<li>Swap nodes to change behavior</li>
|
|
<li>Visual graph = full transparency</li>
|
|
</ul>
|
|
</div>
|
|
<div class="card">
|
|
<h3>Our Cognitive Runtime</h3>
|
|
<ul>
|
|
<li>User msg → classify → think → stream → display</li>
|
|
<li>Each node: one LLM (or none), one job</li>
|
|
<li>Swap models per node via config</li>
|
|
<li><strong>Three-column view = our visual debugger</strong></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<p style="color:#f59e0b;margin:1rem 0;">Key insight: like node-based visual programming, the graph runs <strong>continuously</strong>. Sensors fire, signals propagate, effectors act. The chat is just ONE sensor. Timer events, webhooks, system probes — all feed the same graph.</p>
|
|
|
|
<!-- ================================================================== -->
|
|
<h2>10 Test Use Cases</h2>
|
|
|
|
<table>
|
|
<tr><th>#</th><th>Use Case</th><th>Tests</th><th>Nodes Needed</th><th>Phase</th></tr>
|
|
<tr>
|
|
<td>1</td>
|
|
<td><strong>Greeting</strong> — "hey!"</td>
|
|
<td>Input classifies casual, Output responds warmly. Verify command + context visible in panels.</td>
|
|
<td><span class="tag node">Input</span> <span class="tag node">Output</span></td>
|
|
<td><span class="tag now">NOW</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>2</td>
|
|
<td><strong>Technical question</strong> — "how does asyncio.Queue work?"</td>
|
|
<td>Input classifies knowledge-needed. Output gives detailed answer. Context panel shows history growth.</td>
|
|
<td><span class="tag node">Input</span> <span class="tag node">Output</span></td>
|
|
<td><span class="tag now">NOW</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>3</td>
|
|
<td><strong>Multi-turn follow-up</strong> — ask, then "tell me more"</td>
|
|
<td>Input sees follow-up pattern. Output uses history for continuity. Watch context grow in both panels.</td>
|
|
<td><span class="tag node">Input</span> <span class="tag node">Output</span></td>
|
|
<td><span class="tag now">NOW</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>4</td>
|
|
<td><strong>Tone shift</strong> — friendly then frustrated "this is broken!"</td>
|
|
<td>Input detects tone change, adjusts command. Output shifts from casual to empathetic/helpful.</td>
|
|
<td><span class="tag node">Input</span> <span class="tag node">Output</span></td>
|
|
<td><span class="tag now">NOW</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>5</td>
|
|
<td><strong>Memory persistence</strong> — "my name is Nico" ... later ... "what's my name?"</td>
|
|
<td>Memorizer stores user fact. On later question, provides context to Thinker. Output answers correctly.</td>
|
|
<td><span class="tag node">Input</span> <span class="tag node">Memorizer</span> <span class="tag node">Output</span></td>
|
|
<td><span class="tag next">NEXT</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>6</td>
|
|
<td><strong>Background monitoring</strong> — "watch CPU load, alert if >80%"</td>
|
|
<td>Timer/SystemProbe sensor fires periodically. Input classifies as monitoring. Feedback emits to UI without chat message.</td>
|
|
<td><span class="tag node">Timer</span> <span class="tag node">SystemProbe</span> <span class="tag node">Feedback</span></td>
|
|
<td><span class="tag later">LATER</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>7</td>
|
|
<td><strong>System unresponsive</strong> — LLM takes 30s+</td>
|
|
<td>Feedback node shows "thinking..." immediately. Timeout handling. User sees activity, not silence.</td>
|
|
<td><span class="tag node">Input</span> <span class="tag node">Feedback</span> <span class="tag node">Output</span></td>
|
|
<td><span class="tag next">NEXT</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>8</td>
|
|
<td><strong>Cynefin: Clear domain</strong> — "what's 2+2?"</td>
|
|
<td>Input classifies as Clear, skips Thinker, routes directly to Output. Faster response, cheaper.</td>
|
|
<td><span class="tag node">Input</span> <span class="tag node">Router</span> <span class="tag node">Output</span></td>
|
|
<td><span class="tag later">LATER</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>9</td>
|
|
<td><strong>Topic tracking</strong> — conversation covers 3 topics, user says "back to the first thing"</td>
|
|
<td>TopicTracker accumulates topics. UI shows topic list. User can click to refocus. Memorizer provides relevant context.</td>
|
|
<td><span class="tag node">TopicTracker</span> <span class="tag node">Memorizer</span> <span class="tag node">UI</span></td>
|
|
<td><span class="tag later">LATER</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td>10</td>
|
|
<td><strong>UI action</strong> — button in top bar triggers "summarize this conversation"</td>
|
|
<td>Non-chat input (button click) enters the graph as a sensor event. Input classifies, routes to Thinker+Memorizer. Output renders summary.</td>
|
|
<td><span class="tag node">UI Sensor</span> <span class="tag node">Thinker</span> <span class="tag node">Memorizer</span></td>
|
|
<td><span class="tag later">LATER</span></td>
|
|
</tr>
|
|
</table>
|
|
|
|
<!-- ================================================================== -->
|
|
<h2>Build Roadmap — What To Validate</h2>
|
|
|
|
<div class="phase active">
|
|
<div class="phase-num">1</div>
|
|
<div>
|
|
<h3 style="color:#22c55e;margin:0;">Input + Output (NOW — we're here)</h3>
|
|
<p><strong>Validates:</strong> Two-node communication works. LLM-to-LLM command passing. Context isolation visible. Streaming through graph.</p>
|
|
<p><strong>Test cases:</strong> #1-4 (greeting, technical, follow-up, tone shift)</p>
|
|
<p><strong>Success = </strong> You can see Input's reasoning and Output's execution as separate contexts. The command is meaningful, not just pass-through.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="phase planned">
|
|
<div class="phase-num">2</div>
|
|
<div>
|
|
<h3 style="color:#f59e0b;margin:0;">+ Feedback Node (pure Python, no LLM)</h3>
|
|
<p><strong>Validates:</strong> Non-LLM nodes in the graph. Real-time status. Parallel event emission (HUD fires while Output streams).</p>
|
|
<p><strong>Test cases:</strong> #7 (unresponsive system — user sees "thinking..." not silence)</p>
|
|
<p><strong>Success = </strong> User always sees activity within 200ms. Feedback panel in the UI shows event timeline.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="phase planned">
|
|
<div class="phase-num">3</div>
|
|
<div>
|
|
<h3 style="color:#f59e0b;margin:0;">+ Memorizer Node (LLM: Gemini Flash + SQLite)</h3>
|
|
<p><strong>Validates:</strong> Persistent state across the graph. Node-to-node context requests (Thinker asks Memorizer for context). Three LLM calls per turn, each with different context.</p>
|
|
<p><strong>Test cases:</strong> #5 (memory persistence — "what's my name?")</p>
|
|
<p><strong>Success = </strong> Conversation survives page reload. Memorizer panel shows what it stores vs what it provides.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="phase future">
|
|
<div class="phase-num">4</div>
|
|
<div>
|
|
<h3 style="color:#60a5fa;margin:0;">+ Timer Sensor + SystemProbe (always-on)</h3>
|
|
<p><strong>Validates:</strong> The graph runs without user input. Sensor-driven processing. Background monitoring. The system is ALIVE, not just reactive.</p>
|
|
<p><strong>Test cases:</strong> #6 (background CPU monitoring)</p>
|
|
<p><strong>Success = </strong> UI shows activity without chat. Alerts appear. The graph is a living system, not a request/response pipe.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="phase future">
|
|
<div class="phase-num">5</div>
|
|
<div>
|
|
<h3 style="color:#60a5fa;margin:0;">+ Router + Cynefin Classification</h3>
|
|
<p><strong>Validates:</strong> Multi-path graph. Input classifies domain, routes differently. Clear = fast path (skip Thinker). Complex = deep path (Thinker + tools + Memorizer). The graph adapts to the problem.</p>
|
|
<p><strong>Test cases:</strong> #8 (Clear domain — fast path)</p>
|
|
<p><strong>Success = </strong> Simple questions are 3x faster. Complex questions get deeper treatment. Visible in the graph view.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="phase future">
|
|
<div class="phase-num">6</div>
|
|
<div>
|
|
<h3 style="color:#60a5fa;margin:0;">+ UI Extensions (topic list, action buttons, productivity)</h3>
|
|
<p><strong>Validates:</strong> The graph doesn't just do chat. Non-chat inputs (buttons, lists) enter the graph. Non-chat outputs (topic sidebar, action bar) exit the graph. Full cybernetic loop with rich UI.</p>
|
|
<p><strong>Test cases:</strong> #9 (topic tracking), #10 (UI button triggers graph)</p>
|
|
<p><strong>Success = </strong> The agent is a workspace tool, not just a chatbot.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ================================================================== -->
|
|
<h2>Viable System Model (Beer) — The Graph as Organism</h2>
|
|
|
|
<div class="three-col">
|
|
<div class="card green">
|
|
<h3>System 1 — Operations</h3>
|
|
<p>The worker nodes doing actual work.</p>
|
|
<ul>
|
|
<li><strong>Thinker</strong> — reasoning, tool calls</li>
|
|
<li><strong>Output</strong> — response generation</li>
|
|
<li><strong>ToolExec</strong> — external actions</li>
|
|
</ul>
|
|
</div>
|
|
<div class="card blue">
|
|
<h3>System 2 — Coordination</h3>
|
|
<p>Prevents conflicts between System 1 nodes.</p>
|
|
<ul>
|
|
<li><strong>Router</strong> — sequencing, dedup</li>
|
|
<li><strong>ContextBuilder</strong> — shared context</li>
|
|
<li>Message queue ordering</li>
|
|
</ul>
|
|
</div>
|
|
<div class="card amber">
|
|
<h3>System 3 — Control</h3>
|
|
<p>Monitors performance, enforces policies.</p>
|
|
<ul>
|
|
<li><strong>Feedback</strong> — quality gates</li>
|
|
<li>Token budget manager</li>
|
|
<li>Rate limiter, safety filter</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="three-col">
|
|
<div class="card purple">
|
|
<h3>System 4 — Intelligence</h3>
|
|
<p>Looks outward + forward. Adapts.</p>
|
|
<ul>
|
|
<li><strong>I/O Monitor</strong> — pattern detection</li>
|
|
<li>Learns from failures</li>
|
|
<li>Adapts routing rules over time</li>
|
|
</ul>
|
|
</div>
|
|
<div class="card red">
|
|
<h3>System 5 — Identity</h3>
|
|
<p>What the graph IS and won't do.</p>
|
|
<ul>
|
|
<li>System prompts, persona</li>
|
|
<li>Safety boundaries</li>
|
|
<li><code>graph.md</code> config</li>
|
|
</ul>
|
|
</div>
|
|
<div class="card" style="border-color:#55555533;">
|
|
<h3>The Human Node</h3>
|
|
<p>User isn't outside the system — they're an actant (ANT).</p>
|
|
<ul>
|
|
<li>Messages = sensor signals</li>
|
|
<li>Approvals = gate controls</li>
|
|
<li>Corrections = feedback loops</li>
|
|
<li>The graph includes the human</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ================================================================== -->
|
|
<h2>Design Principles (Synthesis)</h2>
|
|
|
|
<div class="three-col">
|
|
<div class="card amber">
|
|
<h3>1. Three-Layer Architecture</h3>
|
|
<p><em>From cybernetics</em></p>
|
|
<p>Perception (sensors, classifiers) → Decision (routers, controllers) → Action (processors, effectors). Feedback from action back to perception. Missing any layer breaks the loop.</p>
|
|
</div>
|
|
<div class="card blue">
|
|
<h3>2. Invest in Translations</h3>
|
|
<p><em>From ANT</em></p>
|
|
<p>Message schemas and inter-node protocols matter MORE than individual node intelligence. A mediocre LLM with excellent routing outperforms a brilliant LLM with bad routing. Capability is emergent from topology.</p>
|
|
</div>
|
|
<div class="card green">
|
|
<h3>3. Mixed Compute</h3>
|
|
<p><em>From signal processing</em></p>
|
|
<p>Only Processor nodes need LLMs. Classifiers, routers, filters, accumulators can be lightweight models or pure code. Keeps cost and latency sane. Reserve expensive calls for where reasoning matters.</p>
|
|
</div>
|
|
</div>
|
|
<div class="three-col">
|
|
<div class="card purple">
|
|
<h3>4. Typed Event-Driven Connections</h3>
|
|
<p><em>From Max/MSP, Blueprints</em></p>
|
|
<p>Distinguish <strong>trigger</strong> inputs (fire processing) from <strong>context</strong> inputs (available but passive). Type the message wires. Dampen every feedback cycle (max iterations, circuit breakers).</p>
|
|
</div>
|
|
<div class="card red">
|
|
<h3>5. Requisite Variety</h3>
|
|
<p><em>From Ashby</em></p>
|
|
<p>Classifier/router layer must distinguish at least as many input types as you have processing strategies. Under-classification = wasted capability. Over-classification = premature complexity.</p>
|
|
</div>
|
|
<div class="card" style="border-color:#55555533;">
|
|
<h3>6. Domain-Aware Routing</h3>
|
|
<p><em>From Cynefin</em></p>
|
|
<p>Clear = shallow/fast (skip Thinker). Complicated = specialist path. Complex = parallel probes. Chaotic = hardcoded fallback, act first. Different domains = different graph depths.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ================================================================== -->
|
|
<h2>The Key Insight</h2>
|
|
|
|
<div class="card amber" style="margin:1rem 0;border-width:2px;">
|
|
<p style="font-size:1rem;color:#f59e0b;font-weight:600;">The graph IS the agent. Not a single LLM with a prompt. Not a chain of API calls. A living, always-on, multi-model network of specialized processors — exactly like a signal processing graph, but for language and reasoning.</p>
|
|
<p style="margin-top:0.5rem;">Each phase adds a node. Each node validates one architectural claim. If any claim fails, we learn something. If they all hold, we have a new kind of agent runtime.</p>
|
|
<p style="margin-top:0.5rem;color:#888;">The network is the capability (ANT). The variety must match the disturbance (Ashby). The domain determines the strategy (Cynefin). The organism needs all five systems to be viable (Beer).</p>
|
|
</div>
|
|
|
|
</div>
|
|
</body>
|
|
</html>
|