多智能體協作系列(四):從終端三代理走向自創生閉環
Multi-agent work in three spoonfuls (part IV): from a terminal trident to an autopoietic loop
Cristián Labra 在 penta-agent 中整合多智能體路由、混合記憶與 Harness2,建立以本機驗證和人工審批控制改動的自我改進閉環。混合記憶結合 SQLite FTS5、Qdrant 與 Qwen3-Embedding-0.6B,p95 延遲為 0.07 s。
After benchmarking the models in part I, auditing retrieval in part II, and tracing provenance in part III of this series, I closed my laptop with a sense of victory: I had a trident of agents running from the terminal on Arch Linux. With a couple of zsh aliases, I could invoke Claude Code for architectural reasoning, hand off a task to Codex CLI to edit code, or ask Gemini CLI and Antigravity for a quick second opinion. On paper, orchestration looked solved.
Yet after using that setup every day on real projects inside penta-agent, I hit a silent wall: having three agents talking does not equal having a system that learns. Every time I opened a fresh session, the trident suffered from partial amnesia, repeated commands that had already failed the previous week, burned the quota of the most expensive provider on routine tasks, or marked tests as "verified" when they had never had a chance to fail.
To understand what was missing, it helped to change the question. In a recent systems-theory analysis of artificial intelligence, Benedikt Zönnchen, Mariya Dzhimova, and Gudrun Socher (20251, 2–4) propose setting aside whether a language model "thinks like a human" and asking instead the question posed by Humberto Maturana and Francisco Varela (19872 [1984]) and extended by Niklas Luhmann (19983, 60–69): can the system draw its own boundary with the environment, observe its own failures, and sustain itself through its own operations? In other words, moving from the vague notion of "intelligence" to the concrete mechanism of autopoiesis.
As Zönnchen, Dzhimova, and Socher (20251, 8–10) show, an isolated language model in a chat window neither is nor can be an autopoietic, sense-making system: it lacks what George Spencer-Brown (19694) called re-entry—the capacity to re-introduce the distinction between system and environment (self-reference vs. other-reference) inside its own operations—because it only computes which token is statistically plausible after another, without internal resistance against error. If I want a system that improves without degrading, I have to build a socio-technical harness around the models that couples the probabilistic flexibility of neural networks with the strict coupling and binary code (works / does not work, work / fail) of deterministic technology described by Luhmann (19983, 517–525) and André Reichel (20115, 105–118).
The starting point: what I measured and discarded before making this leap
Before diving into the three spoonfuls of this fourth installment, here is the experiment that forced me to adopt that discipline. When I tried to give the system long-term memory, the obvious temptation was to install the most elaborate architecture available: temporal graphs, heavy extractors, or an 8B-parameter neural judge running on CPU. Instead of following intuition, I built a reproducible benchmark over my real work logs—comparing open alternatives such as GraphRAG, Graphiti, Hindsight, Letta, Mem0, and deja-vu—and set a falsification contract upfront: any candidate exceeding 0.10 s in p95 latency or failing to improve recall by at least 10% would be discarded.
| What I tested in the laboratory | Measured result | Operational decision |
|---|---|---|
Hybrid memory (v3.1) (FTS5 lexical index + semantic neighbors in Qdrant with Qwen3-Embedding-0.6B) |
Latency p95 = 0.07 s (< 0.10 s), 96% overall recall, rescuing 1 in 3 zero-lexical-overlap queries |
Promoted to production as the engine behind experience-memory and recall-context
|
In-memory relational graph (v3.2) for multi-hop entity expansion |
Exact tie in accuracy with v3.1, but nearly double the latency (p95 = 0.13 s > 0.10 s) |
Frozen in the lab; the extra complexity did not earn its keep |
CPU neural judges (4B and 8B) for live answer auditing |
Between 69 s and 197 s per verdict, hitting 180 s timeouts in 2 of 3 runs |
Discarded from the critical path; pruned 36.3 GiB from disk |
Deterministic checks + bounded 0.6B judge for local validation |
Millisecond latency, 0 remote calls, and 100% reproducibility |
Adopted as the standard for control gates and evaluation |
Table 1. Summary of the prior local memory and evaluation laboratory in penta-agent: what survived the 0.10 s threshold and why I pruned 36.3 GiB of local models that added no operational value.
With that foundation in place, I organized this fourth part into three progressive spoonfuls: in the first, I show how I moved from launching standalone agents by hand to governing them with quota budgets, auditable bridges, and a live board in kitty and tmux; in the second, how the nervous system of hybrid memory, MCP tools, and skills works under the hood; and in the third, how I closed the local autopoiesis loop with Harness2 and where both my metrics and systems theory draw the boundary today.
Spoonful 1: From invoking agents by hand to governing agents and models
In plain terms: when I first wired the three agents together, I acted like a traffic officer waving my arms in the middle of an intersection. If I wanted Codex CLI to review a patch written by Claude Code, I copied file paths, opened another tab, and hoped for the best. That works for a five-minute demo, but it falls apart when a task runs for two hours and touches twenty files.
Quota-aware routing and security boundaries
My first deductive inference came from a hard constraint: model subscriptions and APIs have usage limits, different context windows, and credential boundaries that must never blur. By definition, if I delegate a heavy task to an agent whose quota is at 98%, the session will die mid-flight and leave the repository in an inconsistent state.
So I replaced intuitive provider selection with an explicit policy in routing.yaml and a pre-flight sentinel (quota_status.sh, governed by the quota-guard skill). Before launching any expensive job, the system reads cached pressure across every lane without spending tokens:
-
🔍 Claude Code (
Opus/Sonnet): handles architectural design, delicate editing, and long-horizon synthesis when its quota is clear (exit 0). -
🛠️ Codex CLI (
gpt-5.4): steps in as an implementation peer, deep refactoring engine, session rescuer (codex-rescue), and cross-validator. -
🌐 Gemini CLI and Antigravity (
gemini-3-pro/flash): in a direct session (penta-agy) it acts as the primary integrator; when invoked from outside viaagy-bridge, it runs inside a strict sandbox over sanitized public context as an explorer, reviewer, or validator, never inheriting private keys or.envfiles.
Instead of calling a raw binary and depending on whatever it prints to stdout, every cross-agent handoff goes through agy-bridge. The bridge requires declaring who is calling (--caller), in what mode (plan, review, patch, test, or explain), and with what time limit (--timeout), leaving an immutable receipt in .agents/runs/<run_id>/ with request.md, result.md, status.json, and diff.patch.
The live board (plan-board) and decision gates
My second inference was inductive: reviewing dozens of past sessions showed that the biggest waste of time happened at two extremes. Either an agent interrupted me every two minutes to ask permission for trivial, reversible steps, or it silently made a delicate architectural choice and I only discovered at the end that it had gone down the wrong path.
To eliminate both extremes without filling this post with abstract flowcharts, here is how my actual kitty terminal—or minimalist Wayland alternatives like foot on Codeberg—looks today when split into two panes with tmux during a live task:
Watch the full video demo on 3cucharadas.cl.
Figure 1. Daily workflow in my kitty + tmux terminal with the Starship prompt: the top pane runs multi-agent delegation via agy-bridge, the decision-gate brake, and pytest; the bottom pane (watch.mjs) updates each step live ([ ] → [~] → [!] → [x]), along with binding decisions and drift.
What appears in the bottom pane of Figure 1 is the contract that changed how I work:
-
Local autonomy with visual traceability (
plan-board): every reversible, in-scope step proceeds without asking permission, but must be reflected in real time in the bottom table. And no item can be closed as verified ([x]) unless the agent attaches the concrete test, command, or observation reference that backs it. -
Decision gate (
decision-gate): when an irreversible or architectural fork appears (state[!]), the agent halts only that branch and presents the question with the recommended option first, marked(Recommended)and justified with deductive, inductive, and abductive evidence. -
A gate that has never been seen red is not a gate (
gates-falsables): before accepting any new verifier, I require running it against a synthetic failure (--fixture) and proving that it returns a non-zero exit code (exit 1). If a check passes even when I break its input on purpose, it is not a safety net—it is compliance theater.
Spoonful 2: The nervous system — hybrid memory, skills, and MCP tools
If the first spoonful orders who does what and under which rules, the second solves how the system remembers what it has already learned and how it picks the exact tool without bloating the context window.
Here the diagnosis by Zönnchen, Dzhimova, and Socher (20251, 6–7, 9) is decisive again: a neural network maintains a loose coupling with human communication that behaves like a "contingent index-card system (Zettelkasten)" (pp. 7, 9) of semantic associations in vector space, giving rise to what Elena Esposito (20176, 249–265; 20227) calls "virtual double contingency" and "artificial communication." That flexibility lets it connect ideas phrased in very different words, but also makes its outputs inherently probabilistic and devoid of autonomous decision-making. If I want reliable memory and precise execution, I have to couple that vector Zettelkasten with exact indices and deterministic scripts.
Experience memory (experience-memory): the hybrid Zettelkasten in 0.07 s
When I first started keeping logs, my memory was essentially a folder of Markdown files that I read or searched with ripgrep. The obvious problem is that if a month ago I solved a cold-boot screen freeze under the title "Webview failure on autostart" and today I search for "Panel fails to load at login", a purely lexical search can miss it entirely, whereas a purely vector search can bury the exact name of a script like verify_boot_contract.sh.
The solution I validated in Table 1 combines both worlds behind the experience-memory MCP server and the recall-context skill:
-
Exact lexical lane (
SQLite FTS5): instantly catches flag names, error codes, file paths, and invariants (INV-005). -
Dense semantic lane (Qdrant +
Qwen3-Embedding-0.6B): indexes architectural decisions, handoffs, and operational lessons (penta_context_v2) to retrieve conceptual neighbors even when they share zero keywords.
Before designing any non-trivial strategy, the agent queries recall_experience in 70 milliseconds (p95 = 0.07 s). That is how it discovers which command worked previously, which hypothesis was already refuted, and which environment trap to avoid (for instance, knowing that in my shell cp, mv, and rm are aliased to interactive -i, which hangs a headless process unless invoked via command mv -f).
Skills as living procedures and proactive MCP selection
To avoid saturating the initial prompt with thousands of lines of instructions, I adopted the modular pattern of Anthropic Skills enriched with local contracts. In penta-agent, each skill is a self-contained package with four parts: a concise contract in SKILL.md defining when to activate and when not to use it; on-demand deep documentation in references/ (such as the editorial corpus extracted with Docling or diagramming rules with D2); deterministic executables in scripts/ (such as typed pipelines in Nushell, visual automation with Playwright, or forge integration via glab on GitLab); and a telemetry trail.
Similarly, the fleet of MCP servers (plan-board, experience-memory, ideas-rag, paper-search, bibliography-apa, PLAYWRIGHT_LOCAL) is cataloged in specs/mcp-capabilities.json. When a task arrives, triage evaluates which capabilities provide real evidence and records both hits and justified abstentions. And when I found that two older servers (quota status and remote SSH infrastructure) were faster, clearer, and easier to audit as direct scripts (quota_status.sh and remote_exec.sh), I decommissioned them as MCP servers and turned them into lightweight skills. Fewer resident daemons mean a smaller failure surface.
Spoonful 3: The autopoiesis loop (Harness2) — how the system rehearses its own improvements
Here I reach the core of this fourth installment. Having capable agents (Spoonful 1) and fast hybrid memory with skills (Spoonful 2) still leaves a critical question open: what happens when a delegation route ages, a skill starts inducing errors, or a memory tweak degrades accuracy on edge cases? If I rely solely on noticing by eye weeks later, the system degrades through silent drift.
Why a standalone LLM lacks re-entry and internal resistance
In their study on autopoiesis and artificial intelligence, Zönnchen, Dzhimova, and Socher (20251, 8–9) explain with surgical precision why asking a model to "reflect on its own errors" via chain-of-thought (CoT) is not enough. When a model generates intermediate tokens like "Is this step correct?", it exhibits only rudimentary processual self-referentiality (p. 8)—producing the most statistically plausible continuation inside its training distribution—while lacking reflective self-reference and genuine re-entry (Spencer-Brown 19694). If a model takes itself as its sole reference without external contrast, it quickly falls into infinite recursion or collapse; if it depends entirely on a human retraining its weights from outside (RLHF or delayed fine-tuning), it remains an allopoietic artifact determined from the outside (Zönnchen, Dzhimova, and Socher 20251, 4, 8–9).
To escape that trap, Zönnchen, Dzhimova, and Socher (20251, 7) recover a decisive formulation from Niklas Luhmann (19958) on how operational constructivism relocates Kant's "resistance of reality" inside a system:
"I think we should not abandon [Kant's] idea of resistance, but we should relocate it into the system. It is the result of resolving an internal conflict—the result of the system's operations resisting the operations of the same system" (Luhmann 19958, quoted in Zönnchen, Dzhimova, and Socher 20251, 7).
That sentence describes, piece by piece, what I built in penta-agent by adapting and integrating the proactive loop of Harness² proposed by Ruiyao Xu, Yanfei Chen, Zhongying CuiZhu, et al. (20269): making the system's own deterministic verification operations resist and filter change proposals generated from its own operational friction.
In plain terms (ELI5): what is Google's original Harness² and how did I adapt it to my machine?
Imagine your AI agents are very creative chefs, but the recipe book they follow (their rules, memory, and tools) sometimes has confusing steps that make them burn the rice. The original Harness² from Google Research (Xu et al. 2026[^xu2026]) proposes a clever loop called Propose–Probe–Compose: instead of swapping out the chef's brain, it puts several assistants to work rewriting the recipe book, asks them to cook test dishes in the cloud, and keeps the winning recipe. For my daily workflow, the factory setup had two catches: it is designed to burn hundreds of paid cloud model calls (Vertex AI), and when driving CLI agents it unbuckles their seatbelt (--dangerously-bypass-approvals-and-sandbox) with open internet access.
To adapt it to penta-agent without spending an extra cent or opening security holes, I took its recursive search engine (commit 1cfe254e) and locked it inside a "test kitchen" completely unplugged from the internet (unshare -Urn), with a disposable home folder and zero access to my API keys or model CLIs (model_calls = 0). Instead of running cloud benchmarks, my wrapper (penta-harness2 and local-cycle) feeds that test kitchen with the real stumbles my agents suffered during the week (CSI), requires any recipe tweak to first fail the test when broken (red) and then pass every historical case without breaking anything else (green), and finally stages the winning recipe across all three agents (Claude, Codex, and Gemini/Antigravity) with a one-step undo button (rollback-local) in case I do not approve it.
penta-agent + Harness2: relocating internal resistance (Luhmann 1995; Zönnchen, Dzhimova, and Socher 2025) through holdout evaluation with model_calls = 0 prior to any human promotion.
How the closed loop operates across my three domains (routing, memory, skills)
As Figure 2 shows (adapting into a three-column horizontal layout on desktop and a vertical flow on mobile), the loop operates in four strict stages:
-
Observing real friction (
CSI— Continuous Self-Improvement): while I use the system, a collector logs objective friction signals: a task that had to switch agents after a timeout, anexperience-memoryquery that returned too few useful neighbors, or a skill where the user had to correct a command. -
Bridging evidence into reproducible cases (
--from-csi latest): thelocal_cycle.pymodule takes that friction report and automatically translates it into a test specification (CaseSpec) inside an isolated environment, without touching my active configuration. -
Internal resistance without spending tokens (
eval_harnesswithmodel_calls = 0): the harness runs the full suite (--profile autopoiesis-all, currently covering9/9baseline cases acrossrouting,memory, andskills), enforcing two hard conditions: every control case (holdout) must pass (holdout_passed = true), and external API calls must equal zero (model_calls = 0). -
Auditable decision (
KEEPvs.DISCARD) and human promotion: if a candidate degrades even a singleholdoutcase or fails to beat the baseline, the deterministic judge discards it (DISCARD). Only when it improves the score with zero regressions does it receive aKEEPverdict and leave a signed receipt for me to review before promoting it to the main repository.
So this does not remain a theoretical promise, the next mini-video shows penta-harness2-shadow local-cycle --profile autopoiesis-all running in my kitty + tmux terminal, including what happens when I inject a regressive candidate (--fixture) alongside a healthy improvement:
Watch the full video demo on 3cucharadas.cl.
Figure 3. Execution in my kitty + tmux terminal of the local autopoiesis loop (local-cycle --profile autopoiesis-all): it evaluates all 9/9 cases in routing, memory, and skills with model_calls = 0, applies internal resistance to reject the regressor (DISCARD), and preserves the verified improvement (KEEP +0.250) with all 82 harness tests green.
Closing: what my architecture achieves today and where its limits lie
Looking back at the path from part I, part II, and part III, the main difference is no longer which model writes the prettiest reply to an isolated prompt, but the structure that holds the whole system together when I am not watching every line.
Following the rigorous distinction drawn by Zönnchen, Dzhimova, and Socher (20251, 5, 9–10) and by Elena Esposito (20176; 20227; 202410), it would be an epistemic mistake to claim that a language model or a bundle of scripts has on its own achieved the biological autopoiesis of a living cell (Maturana and Varela 19872 [1984]) or the reflective sense-making (Sinn) of human consciousness (Luhmann 19983, 50–69). As Zönnchen, Dzhimova, and Socher (20251, 5, 10) caution when critiquing merely metaphorical invocations of technological autopoiesis, language models remain statistical engines that compute distributions without mental states of their own. Yet—and this is my engineering synthesis for the socio-technical system as a whole—when I couple their capacity for contingent variation with verified hybrid memory, strict delegation contracts, a binary internal-resistance harness (work / fail; Reichel 20115) that filters its own proposals before touching production, and deliberative human oversight, I obtain in practice a loop of governed operational autopoiesis.
To close with full transparency, Table 2 summarizes what is running and measured on my machine today, where the next step points, and under what objective condition I would discard each component if it stopped earning its keep:
| System pillar | What it achieves today (verified in production) | What it aims to achieve next & falsification condition |
|---|---|---|
1. Agent and model routing (routing.yaml, quota-guard, agy-bridge) |
Routes tasks across Claude Code, Codex CLI, and Gemini CLI / Antigravity based on cached quota pressure; isolates handoffs in .agents/runs/ under a strict sandbox and displays live progress in plan-board (Figure 1). |
Goal: reweight routing priorities from historical domain success rates. Discard if: the bridge introduces spurious failures or bureaucratic latency exceeding quota savings. |
2. Hybrid memory (experience-memory, Qdrant + FTS5) |
Resolves lexical and semantic queries in p95 = 0.07 s (< 0.10 s), rescues 33% of zero-keyword-overlap pairs, and saves 36.3 GiB after pruning slow CPU judges (Table 1). |
Goal: add automatic decay for obsolete lessons when a contract changes. Discard if: p95 latency exceeds 0.10 s or semantic noise degrades top-3 precision. |
3. Skills and MCP governance (mcp-fleet, gates-falsables) |
Maintains declarative parity across agents (24/24 checks green), measures MCP usage and abstention, and requires every new gate to fail first against a red canary (--fixture -> exit 1). |
Goal: semi-automatic pruning of skills that accumulate repeated friction in CSI telemetry.Discard if: maintaining a skill's contract takes longer than running the direct command. |
4. Local autopoiesis (Harness2) (local-cycle, eval_harness) |
Converts real CSI friction into reproducible Cases and evaluates candidates across routing, memory, and skills (9/9 cases, 82/82 tests) with model_calls = 0, applying internal resistance (KEEP / DISCARD, Figures 2 and 3). |
Goal: expand the bank of real cases extracted from failed sessions without losing millisecond evaluation. Hard boundary ( INV-004): blind auto-merge is forbidden; final promotion to production always requires human review. |
Table 2. Balance between verified production results in penta-agent today, the design horizon, and the falsification thresholds that keep the system under human control.
If building this fourth stage made one thing clear to me, it is that the maturity of a multi-agent system is not measured by how many new pieces I bolt onto it each week, but by how much unnecessary complexity I can prune and how many of its own mistakes the system can catch before asking for my help.
References
.post3-evidence .page_content > p,
.post3-evidence .pagecontent > ul > li,
.post3-evidence .pagecontent > ol > li,
.post3-evidence .page_content blockquote p {
text-align: justify;
hyphens: auto;
}
@media (max-width: 47.99em) {
.post3-evidence .tabla-desliza {
overflow-x: visible;
}
.post3-evidence .tabla-desliza table,
.post3-evidence .tabla-desliza[data-perfil="narrativa"] table {
width: 100% !important;
max-width: 100% !important;
min-width: 0 !important;
table-layout: fixed;
font-size: 13.5px;
line-height: 1.35;
}
.post3-evidence .tabla-desliza table :is(th, td) {
padding: 0.42rem 0.32rem;
overflow-wrap: anywhere;
word-break: normal;
}
.post3-evidence .tabla-desliza table code {
font-size: 0.85em;
word-break: break-word;
}
}
-
Zönnchen, Benedikt, Mariya Dzhimova, and Gudrun Socher. 2025. "From Intelligence to Autopoiesis: Rethinking Artificial Intelligence through Systems Theory." Frontiers in Communication 10:1585321. DOI · Scholar ↩
-
Maturana, Humberto R., and Francisco J. Varela. 1987 [1984]. El árbol del conocimiento: las bases biológicas del entendimiento humano. Santiago de Chile: Editorial Universitaria. 1st Chilean ed. 1984; 1987 international ed. cited in Zönnchen, Dzhimova, and Socher, From Intelligence to Autopoiesis (2025, 3): DOI · Scholar ↩
-
Luhmann, Niklas. 1998. Die Gesellschaft der Gesellschaft. Frankfurt am Main: Suhrkamp Verlag. https://search.worldcat.org/title/37906965. ↩
-
Spencer-Brown, George. 1969. Laws of Form. London: Allen & Unwin. https://archive.org/details/lawsofform00spen. ↩
-
Reichel, André. 2011. "Technology as System: Towards an Autopoietic Theory of Technology." International Journal of Innovation and Sustainable Development 5 (2–3): 105–118. Scholar ↩
-
Esposito, Elena. 2017. "Artificial Communication? The Production of Contingency by Algorithms." Zeitschrift für Soziologie 46 (4): 249–265. Scholar ↩
-
Esposito, Elena. 2022. Artificial Communication: How Algorithms Produce Social Intelligence. Cambridge, MA: The MIT Press. Scholar ↩
-
Luhmann, Niklas. 1995. "Systems Theory and Postmodernism." University lecture, London. Quoted in Zönnchen, Dzhimova, and Socher, From Intelligence to Autopoiesis (2025, 7): DOI · Scholar ↩
-
Xu, Ruiyao, Yanfei Chen, Zhongying CuiZhu, Bhavana Dalvi Mishra, Yifei Ming, Han Yu, Rujun Han, Chen-Yu Lee, and Tomas Pfister. 2026. "Harness²: Recursive Agent Harnessing for an Open World." arXiv preprint
arXiv:2610.14224(open source at https://github.com/google-research/harness2). arXiv · Scholar ↩ -
Esposito, Elena. 2024. Kommunikation mit unverständlichen Maschinen. Salzburg and Vienna: Residenz Verlag. Review of Kommunikation mit unverständlichen Maschinen by Eric Van der Beek in merz | medien + erziehung: DOI · Scholar ↩
來源:DEV Community · dev.to


