added rant

This commit is contained in:
dullfig 2026-01-04 22:22:17 -08:00
parent a1ad8b843f
commit 67c77d568e
3 changed files with 104 additions and 73 deletions

View file

@ -11,6 +11,16 @@ These principles are the single canonical source of truth for the project. All d
- Exclusive C14N on ingress and egress. - Exclusive C14N on ingress and egress.
- Malformed XML repaired on ingress; repairs logged in `<huh/>` metadata. - Malformed XML repaired on ingress; repairs logged in `<huh/>` 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): <from> 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 <from> using the executing listener's registered name (e.g., "calculator.add" or "researcher").
- For meta/primitive responses: <from> is injected as "core".
- <thread> is inherited from the incoming message (or assigned/updated for primitives like spawn-thread).
- <to> remains optional and rarely used.
- This ensures every enveloped message has a trustworthy, auditable <from> without handler involvement, preventing spoofing and keeping capability code minimal/testable.
## Configuration & Composition ## Configuration & Composition
- YAML file (`organism.yaml`) is the bootstrap source of truth, loaded at startup. - YAML file (`organism.yaml`) is the bootstrap source of truth, loaded at startup.
- Defines initial listeners, agents, gateways, meta privileges, and OOB channel configuration. - Defines initial listeners, agents, gateways, meta privileges, and OOB channel configuration.
@ -46,6 +56,7 @@ These principles are the single canonical source of truth for the project. All d
- Subthreading natively supported via hierarchical thread IDs and primitives (e.g., reserved payload to spawn "parent.sub1"). - Subthreading natively supported via hierarchical thread IDs and primitives (e.g., reserved payload to spawn "parent.sub1").
- Optional structured constructs like `<todo-until/>` for visible planning. - Optional structured constructs like `<todo-until/>` for visible planning.
- No hidden loops or state machines; all reasoning steps are visible messages. - 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 ## Security & Sovereignty
- Privileged messages (per `privileged-msg.xsd`) handled exclusively on dedicated OOB channel. - Privileged messages (per `privileged-msg.xsd`) handled exclusively on dedicated OOB channel.
@ -73,4 +84,9 @@ These principles are the single canonical source of truth for the project. All d
- Single process, async non-blocking. - Single process, async non-blocking.
- XML is the sovereign wire format; everything else is implementation detail. - 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.
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. 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.

View file

@ -4,25 +4,56 @@ The AgentServer message pump processes individual messages through a single, lin
```mermaid ```mermaid
flowchart TD flowchart TD
A["WebSocket Ingress\n(enqueue to thread buffer)"] --> B["Dispatcher Loop:\nSelect next message\n(per thread_scheduling strategy)"] subgraph MessagePump
B --> C["Repair + Exclusive C14N"] subgraph Init
C --> D["Envelope Validation (lxml)"] start([Start])
D --> E["Extract Payload Tree"] raw[/Optional<br>Raw Bytes/]
E --> F{"Payload Namespace?"} wrapstart["Wrap<br>&ltstart&gt{...}&lt/start&gt"]
F -->|meta/v1| G["Core Meta Handler\n(introspection & reserved primitives)"] end
F -->|capability| H["Route by (namespace, root)"] enq1([QUEUE 1])
H --> I["Validate Payload vs Listener XSD (lxml)"] rawwaiting{Raw<br>Msg<br>Waiting?}
I --> J["Deserialize to Dataclass Instance (xmlable)"] waitRaw([Wait])
J --> K["Call handler(instance) → raw bytes"] subgraph Process
K --> L["Wrap bytes in <dummy></dummy>"] extract["Extract<br>Tree"]
L --> M["Repair/Parse → Extract all top-level payloads"] split["Split<br>Tree"]
M --> N["Wrap each payload in separate envelope\n(enqueue to target thread buffers)"] subgraph foreach [For Each Message]
G --> N getmsg[Get Msg]
N --> O["Exclusive C14N + Sign"] badTo{&ltTo&gt Missing?}
O --> P["WebSocket Egress\n(sequential per connection)"] endnoto([Discard])
P --> B["Continue dispatcher loop if buffers non-empty"] addfrom["Add .from"]
``` repair[Repair + C14N]
validate[Validate]
invalidMsg{Bad<br>Message?}
badmsg([Discard])
more{More?}
end
enqueue([QUEUE 2])
xmlWaiting{XML<br>Waiting?}
waitXml([Wait])
subgraph Async
lookup[Lookup Listener]
route[Route]
wait[await Response]
wrap["Wrap<br>&ltfrom&gt{...}&lt/from&gt"]
end
end
end
start --> raw --> wrapstart --> enq1 --> rawwaiting
rawwaiting --> |NO| waitRaw
rawwaiting ---> |YES| extract
extract --> split --> foreach
getmsg --> badTo
badTo --> |YES| endnoto
badTo --> |NO| addfrom --> repair --> validate --> invalidMsg
invalidMsg ---> |NO| more --> |Yes| getmsg
invalidMsg --> |YES| badmsg
more --> |NO| enqueue
enqueue --> xmlWaiting
xmlWaiting --> |NO| waitXml
xmlWaiting ---> |YES| lookup --> route --> wait --> wrap --> enq1
```
## Detailed Stages (Per-Message) ## Detailed Stages (Per-Message)
1. **Ingress/Enqueue**: Raw bytes → repair → preliminary tree → enqueue to target thread buffer. 1. **Ingress/Enqueue**: Raw bytes → repair → preliminary tree → enqueue to target thread buffer.

View file

@ -1,65 +1,49 @@
# Thread Management in AgentServer v2.0 # Thread Management in AgentServer v2.0
**January 03, 2026** **January 04, 2026**
This document clarifies the thread ID system, subthreading mechanics, and internals. It supplements the Core Architectural Principles — hierarchical dot notation examples there reflect the wire format. ## Overview
Thread IDs are dynamic hierarchical paths that trace the exact call chain through the organism. The message pump builds and maintains them automatically.
Agents, tools, and handlers are **completely oblivious** to thread IDs — they never read, copy, or emit them.
## Wire Format: Hierarchical String IDs No explicit spawn primitives are required. Topology emerges solely from the shape (single vs multiple) and targets of emitted payloads.
- Mandatory `<thread/>` contains a **server-assigned** hierarchical string (dot notation, e.g., "root", "root.research", "root.research.images").
- Root IDs: Short, opaque, server-generated (e.g., "sess-abcd1234").
- Sub-IDs: Relative extensions for readability.
- Benefits: LLM/human-friendly copying, natural tree structure for logs/GUI.
## Server Assignment Only ## Wire Format
The organism assigns all final IDs — agents never invent them. - Mandatory `<thread/>` contains a readable dot-notation string (e.g., `sess-abcd1234.researcher.search.calc`).
- Root segment is an opaque server-generated session identifier.
- Subsequent segments are registered listener short names appended during routing.
- **Root initiation**: Client suggests or server auto-generates on first message; uniqueness enforced. ## Dynamic Call Tracing Rules
- **Subthread spawning**: Explicit reserved payload for intent clarity: 1. **Emission** (from current path `parent.path`):
```xml - After handler execution and multi-payload extraction:
<spawn-thread suggested_sub_id="research"> <!-- optional relative label --> - For each payload, determine target listener name.
<initial-payload> <!-- optional bootstrap fragment --> - Append that name → new path = `parent.path.target_name`.
<!-- any valid payload --> - Single payload → sequential delegation (one deepened path).
</initial-payload> - Multiple payloads → parallel forks (one deepened path per target, each with its own queue).
</spawn-thread>
```
Core handler:
- Appends label (or auto-short if omitted).
- Resolves uniqueness conflicts (append "-1" etc.).
- Creates queue + seeds bootstrap.
- **Always responds** in current thread:
```xml
<thread-spawned
assigned_id="root.research"
parent_id="root"
message="Thread spawned successfully."/>
```
## Error Handling (No Silent Failure) 2. **Response Bubbling**:
- Unknown `<thread/>` ID → no implicit creation. - On emission from path `parent.path.listener_name`:
- **Always inject** system error into parent thread (or root): - Pump removes the last segment.
```xml - Routes all response payloads to `parent.path`.
<system-thread-error - Injects `<from>` as the responding listeners registered name.
unknown_id="root.badname" - Replies land directly in the immediate parents history.
code="unknown_thread"
message="Unknown thread; emit <spawn-thread/> to create or correct ID."/>
```
- LLM sees error immediately, retries without hanging.
- Logs warning for monitoring.
## Internals 3. **Broadcast**:
- Per-thread queues: dict[str, Queue]. - Single payload to a capability with multiple gateways → fanned out.
- Scheduling via `organism.yaml`: - All responses pop to the same parent path, distinguished by their individual `<from>` values.
```yaml
thread_scheduling: "breadth-first" # or "depth-first" (default: breadth-first)
```
- Depth from dot count.
- Optional hidden UUID mapping for extra safety (implementation detail).
## Design Rationale 4. **Internal Uniqueness**:
- Explicit spawn = clear intent + bootstrap hook. - Readable paths are mapped to UUIDs via a bidirectional resolver.
- Mandatory feedback = no LLM limbo. - New unique logical path → new UUID and queue.
- Readable IDs = easy copying without UUID mangling. - Ensures collision-free scheduling while keeping wire paths clean and meaningful.
- Server control = sovereignty + no collisions.
Future: Alias registry, thread metadata primitives. ## Termination
- Paths become idle when their queues empty.
- Detection of `<final-answer>` (meta namespace) in the root path triggers terminal egress to the originating client.
The organism branches reliably, visibly, and recoverably. ## Key Advantages
- Complete thread obliviousness eliminates prompt bloat and copy errors.
- Natural sequential delegation and parallelism without manual management.
- Full provenance via trustworthy `<from>` injection.
- Audit trails are self-documenting call traces built from registered capability names.
The organism owns memory and topology. Threads are the living, transparent traces of computation.