TL;DR
Ten Trillion Triangles TPipe nests mutable state across four layers. MultimodalContent holds the typed state object. Pipe encloses the content inside one LLM call. Pipeline composes Pipes into a sequence. Container (Manifold, Junction, PumpStation) composes Pipelines into an agent hierarchy. State flows outward-in: each layer mutates the content and passes it to the next. Cells need membranes; agents need substrates. The membrane holds at every level.
MultimodalContent is the mutable form of state
A string at the LLM level is consumed. The LLM produces tokens once; the previous tokens are gone. Ten Trillion Triangles TPipe treats the LLM call as one transformation function applied to a typed state object.
The state object lives at Pipe/BinaryContent.kt:118:
@Serializable
data class MultimodalContent @OptIn(ExperimentalSerializationApi::class) constructor(
var text: String = "",
var binaryContent: MutableList<BinaryContent> = mutableListOf(),
var terminatePipeline: Boolean = false,
var context: ContextWindow = ContextWindow(),
var miniBankContext: MiniBank = MiniBank(),
var tools: PcPRequest = PcPRequest(),
var modelReasoning: String = "",
var useSnapshot: Boolean = false,
var pipeError: PipeError? = null
)
That is the mutable form of state for the substrate. The content object carries text, binary payloads, the context window, the mini-bank, model reasoning, snapshot flags, termination flags, and a metadata scratchpad. It is @Serializable so it survives serialization boundaries. It carries a currentPipe reference so branch functions know which pipe is processing the content. It carries repeatPipe, passPipeline, interuptPipeline, and skipReasoningPipe as control flags the substrate reads to determine what happens next.
The LLM call is a transformation function applied to that object. The LLM output goes back into the content as text, into modelReasoning, into the contextWindow, or into binaryContent, depending on which DITL hook fires. The next pipe sees the object with the LLM contribution appended. The object survives across the entire agent hierarchy.
The Pipe encloses the content inside one LLM call
The Open-Autogenesis player agent demonstrates the nesting at the Pipe level. agent/builders/playerAgent/playerAgent.kt:48-121 constructs a single BedrockMultimodalPipe and threads the content object through every transformation:
val analysisPipe = BedrockMultimodalPipe().apply {
useConverseApi()
setRegion("us-west-2")
setModel(BedrockConfig.qwenCoder30B)
setTokenBudget(BedrockConfig.generativeBudgetSettings)
setPreValidationMiniBankFunction { context, content ->
val world = WorldManager.world
context.contextMap["world"] = ContextWindow().apply { contextElements.add(serialize(world)) }
context.contextMap["valid_territories"] = ContextWindow().apply {
contextElements.add("--- VALID TERRITORIES ON MAP ---\n" + world.mapTiles.joinToString("\n"))
}
context.contextMap["geopoliticalAssessment"] = ContextWindow().apply {
contextElements.add(WorldManager.geopoliticalAssessment)
}
context.contextMap["overtonWindow"] = ContextWindow().apply {
contextElements.add(WorldManager.overtonWindow)
}
context.contextMap["history"] = ContextWindow().apply {
contextElements.add(serialize(GameHistoryList(WorldManager.getRecentHistory(3))))
}
return@setPreValidationMiniBankFunction context
}
setTransformationFunction { content ->
val window = ContextWindow().apply { contextElements.add(content.text) }
com.TTT.Context.ContextBank.emplaceWithMutex("strategic_analysis", window)
return@setTransformationFunction content
}
}
The Pipe receives a MultimodalContent as the second parameter of each DITL hook. The hook reads the content, mutates its contextMap, and returns it. The setTransformationFunction writes the LLM’s text output into the ContextBank under a key — emplaceWithMutex("strategic_analysis", window) — and returns the content. The content survives the LLM call. The substrate applies the transformation.
The Pipeline composes Pipes through a shared context
The Pipeline takes the content object and chains it across multiple Pipes. The Open-Autogenesis player agent builds a three-stage pipeline:
val pipeline = Pipeline()
pipeline.add(analysisPipe) // synthesis
pipeline.add(strategicPlanningPipe) // planning
pipeline.add(executionPipe) // execution
Each Pipe adds to the MultimodalContent. Each Pipe’s output becomes the next Pipe’s input. The content object threads through the entire pipeline. The Pipeline context holds the shared state across the sequence.
Pipeline.kt:43 declares class Pipeline : P2PInterface. The same interface contract that a single Pipe implements, a multi-Pipe Pipeline implements. The encapsulation boundary scales. The substrate’s guarantees — typed contracts, kill switch, persistent memory, deterministic control — apply at both the leaf level and the composition level.
The Pipeline’s kill switch propagates inward. Setting a kill switch on the Pipeline propagates to every contained Pipe. The same propagation pattern operates at the Container level.
The Container encloses Pipelines into an agent hierarchy
The Container is the highest layer. A Container holds one or more Pipelines and runs them as manager-worker dispatchers.
Manifold.kt:242 declares the working content object that survives across loop iterations:
@RuntimeState
private var workingContentObject = MultimodalContent()
The comment above it is explicit: “Most critical property in this class. This is the content object that will be worked on by every llm agent inside the manifold.”
The Container’s manager pipeline reads the working content, decides which worker pipeline to invoke, and the transformationFunction applies the worker’s output back to the working content:
private var transformationFunction: (suspend (content: MultimodalContent) -> MultimodalContent)? = null
The kill switch on a Container propagates to every contained Pipeline. Manifold.kt:393-399:
override var killSwitch: com.TTT.P2P.KillSwitch?
get() = _killSwitch
set(value) {
_killSwitch = value
managerPipeline.killSwitch = value
for (workerComponent in workerComponents) {
workerComponent.killSwitch = value
}
}
A token limit set at the Container level bounds the entire agent hierarchy underneath. A trip terminates the Manager pipeline and every worker pipeline absolutely.
Junction and PumpStation are Containers that apply the same nesting principle to different shapes of agent hierarchy. Junction selects a worker from a strategy. PumpStation applies a runtime harness with intervention points. Both hold a working content object that survives across iterations.
The nesting is the encapsulation principle
Four layers. Each layer encloses the layer below it. Each layer applies the same encapsulation commitment:
- MultimodalContent holds the typed state. Text, binary, context window, mini-bank, model reasoning, snapshot flags, termination flags, metadata. Serialization-ready. Survives across LLM calls, pipes, pipelines, and containers.
- Pipe encloses the content inside one LLM call. The DITL hooks mutate the content. The transformationFunction applies the LLM output back to the content. The content survives the LLM call.
- Pipeline composes Pipes through a shared context. The output of one Pipe becomes the input of the next. The kill switch on the Pipeline propagates inward.
- Container composes Pipelines into an agent hierarchy. The Manager reads the working content, the worker transforms it, the transformationFunction applies the work. The kill switch on the Container bounds every contained pipeline.
The state object threads through every layer. The cell membrane is the encapsulation principle at every level.
The substrate is biological
The hierarchy from atom to molecule to cell to complex lifeform maps onto Ten Trillion Triangles TPipe’s nesting. Cells solve the same problem agents solve: how to keep state coherent under load. The substrate’s encapsulation layers are the architectural commitment that lets an agent survive the long horizon.
The atom is the typed field. Atoms are the smallest unit of matter that retains chemical identity. The substrate’s smallest unit of state is the typed field — String, BinaryContent, ContextWindow, MiniBank, TokenBudgetSettings, PipeSettings. Each typed field has a single, well-defined shape. An atom on its own is inert. A typed field on its own is a single value with no behavior.
The molecule is the typed state object. A molecule is two or more atoms bonded together into a unit with chemical properties. MultimodalContent is the smallest unit of substrate state. It bonds typed fields together — text + binary + context + mini-bank + model reasoning + metadata + control flags — into one object with substrate behavior. Molecules have properties their atoms do not. The content object has a merge() function; its atoms do not. The content object is composable across the substrate hierarchy; its atoms are not. Pipe/BinaryContent.kt:118:
data class MultimodalContent(
var text: String = "",
var binaryContent: MutableList<BinaryContent> = mutableListOf(),
var context: ContextWindow = ContextWindow(),
var miniBankContext: MiniBank = MiniBank(),
var tools: PcPRequest = PcPRequest(),
...
)
The cell is the Pipe. A cell is the smallest unit of life. It has a membrane that controls what crosses in and what crosses out. A Pipe is the smallest unit of agent activity. It has a kill switch membrane that bounds cost, a token budget membrane that meters fuel, a lorebook membrane that selects context, a JSON contract membrane that types state mutations. One LLM call runs inside the cell membrane. The cell can be paused, inspected, and resumed. The cell can be killed absolutely.
The complex lifeform is the Container. A multicellular lifeform is composed of specialized cells organized into organs organized into systems. A Container — Manifold, Junction, PumpStation — is composed of specialized pipelines organized into a manager-worker hierarchy. The Manifold holds a working content object that survives across loop iterations. The Junction selects a worker by strategy. The PumpStation runs a runtime harness with intervention points. The Container has a kill switch that propagates to every contained pipeline.
The argument is structural. Less encapsulation produces a less successful agent. An atom-only agent has typed fields but no state object; it loses coherence immediately because no substrate manages the bonds between fields. A molecule-only agent has state but no LLM-call membrane; it leaks tokens because no substrate bounds the call. A cell-only agent has a single LLM call but no multi-step composition; it cannot do work that requires multiple coordinated calls. A lifeform-only agent has multi-pipeline dispatch but no state object; its loops cannot preserve working state across iterations.
More encapsulation produces a more successful agent. The atom ensures the state is typed. The molecule ensures the state is composable. The cell ensures the state is bounded by a membrane and a lifecycle. The lifeform ensures the state survives across iterations of work. Cells survive long-term workloads because each level of encapsulation protects the level below it. Ten Trillion Triangles TPipe produces surviving agents for the same reason. The architecture is older than any framework. The substrate is what makes the long horizon survivable.
How context and memory thread through the nesting
Context and memory are the substrate’s runtime services. They thread through every layer of the nesting the same way MultimodalContent does. Each layer binds the same services to a different scope.
At MultimodalContent — the state object carries two context surfaces directly. var context: ContextWindow = ContextWindow() is the per-pipe context: lorebook entries, prior-pipe outputs, system-prompt injection, and the LLM’s view of the working memory for this call. var miniBankContext: MiniBank = MiniBank() is the keyed-context surface: a small map of named entries that pipes read from and write to by key. Both surfaces are typed fields on the content object. The substrate’s merge() function (Pipe/BinaryContent.kt:395-402) joins two MultimodalContent instances by combining their context, miniBankContext, and metadata. The state is composable.
At Pipe — the pipe binds its own context window to its own context budget. pipe.contextMap["world"], pipe.contextMap["valid_territories"], pipe.contextMap["geopoliticalAssessment"] — each pipe populates its context window in a setPreValidationMiniBankFunction hook before the LLM call. The LLM call reads from that context. The pipe’s setTransformationFunction writes its LLM output back to the context bank. The pipe’s context window is per-pipe. The pipe’s mini-bank is keyed and shared with sibling hooks on the same pipe.
At Pipeline — the pipeline owns the lifecycle of the shared context across pipes. The pipeline context holds the ContextWindow that every Pipe reads from and writes to. Pipes in the same pipeline read the same ContextWindow. The pipeline’s emplaceWithMutex writes propagate to subsequent pipes in the sequence. The pipe at agent/builders/writingAgent/writerAgent.kt:656-680 writes to the pipeline’s ContextBank under a key after the LLM call; the next pipe reads from that same key on its pre-validation hook. The pipeline-level context is the wire between pipes.
The emplaceWithMutex pattern at agent/builders/writingAgent/writerAgent.kt:674-676:
val storyData = ContextBank.getContextFromBank("story")
storyData.contextElements.add(it.text)
ContextBank.emplaceWithMutex("story", storyData)
The getContextFromBank reads the keyed context. The emplaceWithMutex writes it back under a mutex. Concurrent pipe executions serialize on the mutex, so two pipes writing to “story” do not race. The lorebook agent at agent/builders/lorebook/lorebookAgent.kt:166-282 applies the same pattern across six entity types (characters, events, locations, items, factions, relationships), each reading the “story” context, mutating it, and writing it back under the mutex. The mutex is the only thing keeping the lorebook consistent across concurrent writes.
At Container — the container holds a working content object that survives across loop iterations. Manifold.kt:242:
@RuntimeState
private var workingContentObject = MultimodalContent()
The @RuntimeState annotation tells the substrate the field persists across execution boundaries. The Manifold’s manager pipeline reads the working content, dispatches a worker pipeline, and applies the worker’s transformation through transformationFunction. The Container’s working context threads through every iteration of the manager-worker loop. The kill switch on the Container bounds every contained pipeline’s context budget. A pipeline running inside the Container has its own context window; the Container holds the running summary across the iteration.
The three-tier memory model — ContextWindow (per-pipe), ContextBank (per-pipeline, keyed), LoreBook (weighted recall with alias keys and dependency links) — operates at every nesting layer with a consistent surface. A pipe’s ContextWindow is its working memory for one LLM call. A pipeline’s ContextBank is the shared state across pipes in the sequence. A container’s working content object is the running state across loop iterations. The LoreBook lives inside the ContextBank as weighted entries with alias keys.
The substrate’s principle: context and memory are typed runtime services, not implicit globals. Every read and write happens through the substrate’s APIs. Every nested layer applies the same APIs with a different scope. The pipe’s ContextWindow, the pipeline’s ContextBank, the container’s working content, and the lorebook’s weighted entries all share one substrate-managed contract.
What the substrate applies at each layer
- At MultimodalContent — typed contracts on what crosses the LLM boundary. The content’s text, binary, context, mini-bank, model reasoning, and metadata are explicit fields. A pipe can read any field, mutate any field, return the mutated object. The substrate validates the object at every boundary.
- At Pipe — one LLM call inside one membrane. The pre-validation hook runs before the LLM. The LLM call produces the output. The transformation hook runs after. The validation hook decides pass / fail / branch. The Pipe returns the content to the Pipeline.
- At Pipeline — a sequence of membranes wired through a shared context. The Pipeline owns the lifecycle: init, compose, execute, finalize. The Pipeline pauses, resumes, and jumps between pipes via explicit control flow rather than unpredictable model decisions.
- At Container — a manager pipeline dispatching worker pipelines through a working content object. The Container owns the loop: iterate, dispatch, transform, accumulate, complete. The kill switch bounds the loop. The transformationFunction applies the worker’s contribution back to the working content.
Each layer adds a new boundary. Each boundary applies the same commitment: the membrane holds. The framework wires. The category is named by what it does to its contents.
The structural commitment
Cells solve leakage with a membrane. Ten Trillion Triangles TPipe solves leakage in an agent runtime with a substrate. The architecture nests. The LLM call is one transformation function applied to a typed state object. The state object threads through Pipes, Pipelines, and Containers. The kill switch on the outermost layer bounds every layer underneath. The snapshot flag preserves the state across failure. The transformation hook applies the worker’s contribution. The membrane holds at every level.
The framework literature talks about wiring handlers together. The substrate literature talks about what stays inside the membrane once it is wired. Cells need encapsulation. Agents need the same architectural commitment.
Related categories
- Substrate Architecture — the cluster page for substrate design, runtime encapsulation, and what distinguishes a substrate from an orchestration framework.
- Long-Horizon AI Agents — the cluster page for agents that run for hours, days, or weeks. The substrate is what makes the long horizon survivable.
- Deterministic AI Agents — the cluster page for agents whose behavior is reproducible turn to turn. Encapsulation is what makes determinism an architectural property rather than an emergent one.
Related posts
- Introducing TPipe: The Agent Operating Substrate — the original TPipe announcement. The architecture argument for why TPipe ships as an agent operating substrate rather than a callable library.
- What Is an Agent Substrate and Why Use One? — the conceptual expansion. What the category means and why frameworks stop where substrates start.
- Reasoning Pipes Explained: How TPipe Stops Prompting and Starts Programming — the JSON-schema contract that encapsulation enforces at pipe boundaries. Where the substrate principle meets the language.
- Orchestration Matters More Than Model Intelligence — the orchestration thesis. The substrate carries the work; the model carries the inference.
- You Cannot Build an Agent Substrate in Python — why the substrate cannot be retrofitted onto a Python library. The architectural constraints that make the substrate necessary in the first place.
Next steps
- Read the Pipe Class documentation for the encapsulation contract surface in detail.
- Understand the three-tier memory model — ContextWindow, ContextBank, and LoreBook as substrate services.
- Study the Manifold pattern — the runtime container that holds the working content object across loop iterations.
- Build your first encapsulated pipeline and run it under a token budget.
The substrate is named by what it does to its contents. The framework is named by what it lets you call. The cell membrane is older than both.