# AgentServer v2.0 — Core Architectural Principles **January 03, 2026** **Architecture: Autonomous Schema-Driven, Turing-Complete Multi-Agent Organism** These principles are the single canonical source of truth for the project. All documentation, code, and future decisions must align with this file. ## Identity & Communication - All traffic uses the universal `` envelope defined in `envelope.xsd` (namespace `https://xml-pipeline.org/ns/envelope/v1`). - Mandatory `` and `` (convo_id string, supports hierarchical dot notation for subthreading, e.g., "root.1.research"). - Optional `` (rare direct routing; most flows use payload namespace/root). - Exclusive C14N on ingress and egress. - Malformed XML repaired on ingress; repairs logged in `` metadata. ## Identity Injection & Handler Purity - Handlers are pure, stateless functions with no knowledge of routing, thread context, or their own registered name. - On ingress (external or gateway messages): is provided and authenticated by the client/gateway (enforced by envelope validation). - On response generation (after handler execution and multi-payload extraction): - The dispatcher injects using the executing listener's registered name (e.g., "calculator.add" or "researcher"). - For meta/primitive responses: is injected as "core". - is inherited from the incoming message (or assigned/updated for primitives like spawn-thread). - remains optional and rarely used. - This ensures every enveloped message has a trustworthy, auditable without handler involvement, preventing spoofing and keeping capability code minimal/testable. ## Configuration & Composition - YAML file (`organism.yaml`) is the bootstrap source of truth, loaded at startup. - Defines initial listeners, agents, gateways, meta privileges, and OOB channel configuration. - Runtime structural changes (add/remove listeners, rewire agents, etc.) via local-only privileged commands on the dedicated OOB channel (hot-reload capability). - No remote or unprivileged structural changes ever. ## Autonomous Schema Layer - Listeners defined by `@xmlify`-decorated dataclass (payload contract) + pure handler function. - Mandatory human-readable description string (short "what this does" blurb for tool prompt lead-in). - Registration (at startup or via hot-reload) automatically generates: - XSD cached on disk (`schemas//v1.xsd`) - Example XML - Tool description prompt fragment (includes description, params with field docs if present, example input) - All capability namespaces under `https://xml-pipeline.org/ns///v1`. - Root element derived from payload class name (lowercase) or explicit. ## Message Pump - Single linear pipeline on main port: ingress → repair → C14N → envelope validation → payload routing. - Routing key = (payload namespace, root element); unique per listener. - Meta requests (`https://xml-pipeline.org/ns/meta/v1`) handled by privileged core handler. - User payloads: - Validated directly against listener's cached XSD (lxml) - On success → deserialized to typed dataclass instance (`xmlable.from_xml`) - Handler called with instance → returns raw bytes (XML fragment, possibly dirty/multi-root) - Bytes wrapped in `` → repaired/parsed → all top-level payload elements extracted - Each extracted payload wrapped in separate response envelope (inherits thread/from, optional new subthread if primitive used) - Enveloped responses buffered and sent sequentially - Supports single clean response, multi-payload emission (parallel tools/thoughts), and dirty LLM output tolerance. ## Reasoning & Iteration - LLM agents iterate via open self-calls (same root tag, same thread ID). - Conversation thread = complete memory and audit trail (all messages logged). - Subthreading natively supported via hierarchical thread IDs and primitives (e.g., reserved payload to spawn "parent.sub1"). - Optional structured constructs like `` for visible planning. - No hidden loops or state machines; all reasoning steps are visible messages. - Thread management follows the dynamic call tracing model (see thread-management.md). Paths are built by appending target listener names on emission, with automatic popping on responses. Agents remain oblivious, enabling natural delegation and parallelism. ## Security & Sovereignty - Privileged messages (per `privileged-msg.xsd`) handled exclusively on dedicated OOB channel. - OOB channel bound to localhost by default (safe for local GUI); separate port/socket from main bus. - Main MessageBus and pump oblivious to privileged operations — no routing or handling for privileged roots. - Remote privileged attempts impossible (channel not exposed); any leak to main port logged as security event and dropped. - Ed25519 identity key used for envelope signing, federation auth, and privileged command verification. - No agent may modify organism structure, register listeners, or access host resources beyond declared scope. - “No Paperclippers” manifesto injected as first system message for every LLM-based listener. ## Federation - Gateways declared in YAML with trusted remote public key. - Remote tools referenced by gateway name in agent tool lists. - Regular messages flow bidirectionally; privileged messages never forwarded or accepted. ## Introspection (Meta) - Controlled via YAML flags (`allow_list_capabilities`, `allow_schema_requests`, etc.). - Supports `request-schema`, `request-example`, `request-prompt`, `list-capabilities`. - Remote meta queries optionally allowed per YAML (federation peers). ## Technical Constraints - Mandatory WSS (TLS) + TOTP on main port. - OOB channel WSS or Unix socket, localhost-default. - Internal: lxml trees → XSD validation → xmlable deserialization → dataclass → handler → bytes → dummy extraction. - Single process, async non-blocking. - XML is the sovereign wire format; everything else is implementation detail. ## Scheduled Computation - Timers and delays implemented as normal listeners using async sleeps. - Caller idles naturally; wakeup messages bubble back via standard tracing. - Enables recurrent tasks (e.g., periodic monitoring) without blocking or external schedulers. ## Bounded Stateful Listeners - Pure tools remain stateless. - Stateful capabilities (e.g., calculator memory, game state) store data per thread path UUID. - Ensures isolation across conversations, automatic cleanup on idle, and minimal mutable state. - Handler closes over or receives UUID for access — still oblivious to readable path. These principles are now locked. All existing docs will be updated to match this file exactly. Future changes require explicit discussion and amendment here first.