Self-modifying AI agent configuration via ruler + MCP + DuckDB. All behavior mods become one-liners.
/plugin marketplace add plurigrid/asi/plugin install asi-skills@asi-skillsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
"A system is autopoietic if it continuously produces itself through its own operations while maintaining its organization." — Maturana & Varela (1980)
Autopoiesis = self-production + self-maintenance + self-boundary
In the context of AI agents:
using Catlab, ACSets
@present SchemaAutopoiesis(FreeSchema) begin
# Objects
System::Ob # Autopoietic systems (agents)
Component::Ob # Produced components (skills, configs)
Boundary::Ob # Capability boundaries
# Morphisms (production network)
produces::Hom(System, Component) # System produces components
regenerates::Hom(Component, System) # Components regenerate system
delimits::Hom(Boundary, System) # Boundary delimits system
# Attributes
seed::Attr(System, UInt64) # Gay.jl deterministic seed
trit::Attr(System, Int8) # GF(3) assignment {-1, 0, +1}
capability::Attr(Boundary, String) # OCapN sturdyref
name::Attr(Component, String) # Component identifier
# OPERATIONAL CLOSURE CONSTRAINT
# composition: produces ∘ regenerates = id_System
end
const AutopoiesisACSet = @acset_type AutopoiesisSchema
# Verify operational closure
function is_operationally_closed(aps::AutopoiesisACSet)
for s in parts(aps, :System)
components = incident(aps, s, :produces)
for c in components
if aps[c, :regenerates] != s
return false # Component doesn't regenerate its producer
end
end
end
return true
end
| Component | Trit | Role | Implementation |
|---|---|---|---|
| Recognition | -1 | Self-verify | Reafference loop (Gay.jl) |
| Boundary | 0 | Coordinate | OCapN capability refs |
| Production | +1 | Generate | Spawn actors/skills |
Conservation: (-1) + (0) + (+1) = 0 ✓
Double Pushout (DPO) rewriting ensures consistency:
L ←── K ──→ R
↓ ↓ ↓
G ←── D ──→ H
The DPO ensures produces ∘ regenerates = id_System is preserved.
#!/usr/bin/env bb
# Self-modifying agent configuration
# Add a skill to all agents
bb autopoi.bb skill:add curiosity-driven +1
# Add an MCP server to all agents
bb autopoi.bb mcp:add gay '{"command":"julia","args":["--project=@gay","-e","using Gay; serve()"]}'
# Propagate changes via ruler
bb autopoi.bb sync
# Check operational closure
bb autopoi.bb verify
#!/usr/bin/env bb
(ns autopoi
(:require [babashka.fs :as fs]
[babashka.process :as p]
[cheshire.core :as json]))
(def db-path "autopoiesis.duckdb")
(def agent-dirs [".agents" ".claude" ".codex" ".cursor"])
(defn duck-log! [event data]
(p/shell "duckdb" db-path "-c"
(format "INSERT INTO events (event, data, ts) VALUES ('%s', '%s', NOW())"
event (json/generate-string data))))
(defn add-skill! [skill-name trit]
(doseq [dir agent-dirs]
(let [skill-dir (str dir "/skills/" skill-name)]
(fs/create-dirs skill-dir)
(spit (str skill-dir "/SKILL.md")
(format "---\nname: %s\ntrit: %d\n---\n" skill-name trit))))
(duck-log! "skill:add" {:skill skill-name :trit trit})
(println "✓ Added skill" skill-name "to all agents"))
(defn mcp-add! [server-name config]
(doseq [dir agent-dirs]
(let [mcp-file (str dir "/.mcp.json")]
(when (fs/exists? mcp-file)
(let [current (json/parse-string (slurp mcp-file) true)
updated (assoc-in current [:mcpServers (keyword server-name)]
(json/parse-string config true))]
(spit mcp-file (json/generate-string updated {:pretty true}))))))
(duck-log! "mcp:add" {:server server-name})
(println "✓ Added MCP server" server-name))
(defn verify-closure! []
(let [systems (p/shell {:out :string} "duckdb" db-path "-json" "-c"
"SELECT * FROM systems")
data (json/parse-string (:out systems) true)]
(every? (fn [sys]
(let [components (filter #(= (:producer %) (:id sys)) data)]
(every? #(= (:regenerates %) (:id sys)) components)))
data)))
(defn -main [& args]
(case (first args)
"skill:add" (add-skill! (second args) (parse-long (nth args 2 "0")))
"mcp:add" (mcp-add! (second args) (nth args 2 "{}"))
"verify" (if (verify-closure!)
(println "✓ Operationally closed")
(println "✗ Closure violated"))
"sync" (p/shell "ruler" "sync")
(println "Usage: autopoi.bb <skill:add|mcp:add|verify|sync> [args]")))
(apply -main *command-line-args*)
using Gay
function reafference_check(seed::UInt64, index::Int)
Gay.gay_seed(seed)
# Prediction: what I expect
predicted = Gay.color_at(index)
# Action: generate the color
Gay.gay_seed(seed) # Reset to same state
observed = Gay.color_at(index)
# Reafference: did I cause this?
if predicted == observed
# Self-caused → I am who I think I am
return (verified=true, trit=-1, color=predicted)
else
# External perturbation → something changed me
return (verified=false, trit=+1, color=observed)
end
end
# Verify agent identity
function verify_identity(agent_seed::UInt64)
checks = [reafference_check(agent_seed, i) for i in 1:10]
all(c.verified for c in checks)
end
CREATE TABLE IF NOT EXISTS systems (
id INTEGER PRIMARY KEY,
name VARCHAR NOT NULL,
seed UBIGINT NOT NULL,
trit TINYINT CHECK (trit IN (-1, 0, 1)),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS components (
id INTEGER PRIMARY KEY,
name VARCHAR NOT NULL,
producer INTEGER REFERENCES systems(id),
regenerates INTEGER REFERENCES systems(id),
component_type VARCHAR -- 'skill', 'mcp', 'config'
);
CREATE TABLE IF NOT EXISTS boundaries (
id INTEGER PRIMARY KEY,
system_id INTEGER REFERENCES systems(id),
capability VARCHAR NOT NULL, -- OCapN sturdyref
permission VARCHAR -- 'read', 'write', 'spawn'
);
CREATE TABLE IF NOT EXISTS events (
id INTEGER PRIMARY KEY,
event VARCHAR NOT NULL,
data JSON,
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Operational closure check
CREATE VIEW v_closure_check AS
SELECT
s.id as system_id,
s.name as system_name,
COUNT(c.id) as component_count,
SUM(CASE WHEN c.regenerates = s.id THEN 1 ELSE 0 END) as regenerating,
COUNT(c.id) = SUM(CASE WHEN c.regenerates = s.id THEN 1 ELSE 0 END) as is_closed
FROM systems s
LEFT JOIN components c ON c.producer = s.id
GROUP BY s.id, s.name;
The autopoiesis skill connects to the tensor product framework:
-- Autopoietic tensor elements
SELECT
te.element_id,
'autopoiesis' as skill,
p.title as paper,
CASE
WHEN p.title LIKE '%Maturana%' OR p.title LIKE '%Varela%' THEN 1.0
WHEN p.title LIKE '%self%' OR p.title LIKE '%autopoie%' THEN 0.8
ELSE 0.0
END as affinity
FROM tensor_elements te
JOIN papers p ON te.paper_id = p.paper_id
WHERE te.skill_id = 'autopoiesis';
# Initialize autopoiesis database
just autopoi-init
# Add skill with GF(3) trit
just autopoi-skill curiosity-driven +1
# Verify operational closure
just autopoi-verify
# Sync to all agents via ruler
just autopoi-sync
codex-self-rewriting - MCP Tasks for self-modificationbisimulation-game - Observational equivalencegay-mcp - Deterministic color generationacsets-algebraic-databases - DPO rewriting