From f3b90963b8064179c38526944ac7d9ab754f87c7 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 29 Dec 2025 12:16:03 -0800 Subject: [PATCH] Replace XMLListener stub with real foundation - Minimal, universal base for all capabilities - Required listens_to class attribute - Async handle() with convo_id preservation rule - make_response() helper for thread continuity - Explicit name, config, per-instance logger - Clear documentation and NotImplementedError guard This is the true substrate the entire organism will build on. --- agentserver/listeners/base.py | 35 ++++++++++------- docs/logic and iteration.md | 72 +++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 13 deletions(-) create mode 100644 docs/logic and iteration.md diff --git a/agentserver/listeners/base.py b/agentserver/listeners/base.py index 715a0de..36835ed 100644 --- a/agentserver/listeners/base.py +++ b/agentserver/listeners/base.py @@ -1,11 +1,13 @@ """ -Core base class for all listeners in the organism. +Core base class for all listeners in the xml-pipeline organism. + +All capabilities — personalities, tools, gateways — inherit from this class. """ from __future__ import annotations import logging -from typing import List, Dict, Any, Optional +from typing import List, Optional, Dict, Any from lxml import etree @@ -17,13 +19,14 @@ class XMLListener: Base class for all capabilities (personalities, tools, gateways). Subclasses must: - - Define `listens_to` (list of root tags they handle) - - Implement `async handle()` + - Define `listens_to` as a class attribute (list of root tags they handle) + - Implement `async handle()` method - The `convo_id` received in handle() MUST be preserved in any response payload. + The `convo_id` received in handle() MUST be preserved in any response payload + (via make_response() helper or manually). """ - listens_to: List[str] = [] # Must be overridden in subclass + listens_to: List[str] = [] # Must be overridden in subclass — required def __init__( self, @@ -32,6 +35,11 @@ class XMLListener: config: Optional[Dict[str, Any]] = None, **kwargs, ): + """ + Args: + name: Optional explicit name (defaults to class name) + config: Owner-provided configuration from privileged registration + """ self.name = name or self.__class__.__name__ self.config = config or {} self.logger = logging.getLogger(f"{__name__}.{self.name}") @@ -40,14 +48,14 @@ class XMLListener: self, msg: etree.Element, convo_id: str ) -> Optional[etree.Element]: """ - Handle a message whose root tag matches this listener. + Process an incoming message whose root tag matches this listener. Args: - msg: The payload element (repaired and C14N'd) - convo_id: Thread/conversation UUID — must be preserved in response + msg: The payload element (already repaired and C14N'd) + convo_id: Thread/conversation UUID — must be preserved in any response Returns: - Response payload element with the same convo_id, or None + Response payload element (with convo_id preserved), or None if no response """ raise NotImplementedError( f"{self.__class__.__name__}.handle() must be implemented" @@ -62,8 +70,9 @@ class XMLListener: **attribs, ) -> etree.Element: """ - Helper to create a response element with a preserved convo_id attribute. - Recommended for all listeners. + Convenience helper to create a response element with preserved convo_id. + + Strongly recommended for all listeners to ensure thread continuity. """ elem = etree.Element(tag, convo_id=convo_id, **attribs) if text is not None: @@ -71,4 +80,4 @@ class XMLListener: return elem def __repr__(self) -> str: - return f"<{self.__class__.__name__} listens_to={self.listens_to}>" \ No newline at end of file + return f"<{self.__class__.__name__} name='{self.name}' listens_to={self.listens_to}>" \ No newline at end of file diff --git a/docs/logic and iteration.md b/docs/logic and iteration.md new file mode 100644 index 0000000..2254cef --- /dev/null +++ b/docs/logic and iteration.md @@ -0,0 +1,72 @@ +# Executive Summary: Self-Calling Iteration Framework in xml-pipeline + +**Date**: December 29, 2025 +**Component**: Core reasoning mechanism for LLM personalities + +### Principle + +In xml-pipeline, **multi-step reasoning, planning, tool use, and iteration are implemented through open, auditable self-calls** — not hidden loops or state machines. + +The LLM personality participates in the conversation exactly like any other listener: it can send messages to its own root tag. + +### How It Works + +1. **Conversation thread = memory** + Every message (user, personality, tool) is appended to history keyed by `convo_id`. + +2. **Self-reflection = self-message** + To think step-by-step, the LLM emits its own root tag with the same `convo_id`: + ```xml + + First, let's outline the steps... + + ``` + +3. **MessageBus routes it back** to the same personality instance. + +4. **Personality appends its own message** to history and calls the LLM again. + +5. **LLM sees full context** — including its previous thoughts — and continues. + +6. **Iteration emerges naturally** from repeated self-calls until final response. + +### Key Properties + +- **No hidden state** — the thread history is the only memory +- **No special controller** — MessageBus and `convo_id` do all coordination +- **Fully auditable** — every thought, plan, and intermediate step is a logged message +- **Tool use fits identically** — tool calls are messages to other root tags +- **Termination is natural** — LLM decides when to emit final response tag (e.g., ``) + +### Structured Planning Support + +Personalities are encouraged to use visible structures: + +```xml + + List 2 + List 3 + List 5 + +``` + +This enables: +- Self-coordination (LLM reads its own plan) +- GUI progress rendering +- Explicit termination conditions + +### Owner Control + +- `iteration-capacity` config (`high`/`medium`/`low`/`none`) tunes how strongly the personality is prompted to iterate +- All behavior governed by owner-provided prompts and response templates +- No personality can loop indefinitely without owner consent + +### Result + +The framework turns **conversation into computation**. + +Loops, conditionals, and planning become **visible message patterns** rather than hidden code. + +The organism reasons by talking to itself in the open — producing a complete, transparent trace of thought at every step. + +This is the core iteration mechanism for all LLM personalities in xml-pipeline.