Skip to main content

Module pipeline

Module pipeline 

Source
Expand description

The ECS pipeline (Phase 2): components + systems that drive every agent through check-input → infer → tools → apply → repeat, entirely as data.

Agents are entities; their execution phase is a marker component (ReadyToInfer, AwaitingInference, …) so systems can query by phase. A system never blocks on I/O: the dispatch systems hand work to the async bridges (inference_bridge, crate::tool_bridge) and the collect systems apply the results on a later tick. This module is built alongside the existing imperative engine; the two are unified in a later phase.

Structs§

AgentBlueprint
The agent’s blueprint (its stage graph), as a component.
AwaitingCompaction
A compaction job (LLM summarization) is in flight; the agent is held out of inference until its summaries land.
AwaitingInference
Inference has been dispatched to the pool; the agent is waiting for its result (which the inference-collect system will apply).
AwaitingTools
The agent’s tool batch has been handed to the tool lane; it is waiting for the results (which the tool-collect system will apply).
AwaitingTransitionChoice
The stage completed with multiple candidate edges (or a single edge the stage may decline); an LLM must choose. Holds the choosable edges for the async transition-choice system.
AwaitingTransitionResponse
A transition-choice inference is in flight (an LLM is picking the next stage); holds the choosable edges so the collect system can match the response back to one. (Ported from the async portion of graph::prompt_llm_transition.)
CompactionResults
The receiving end of the compaction-outcomes channel, as a world resource. (The sending end lives in InferenceStage::compaction_outcomes.)
CompactionSettings
Per-agent compaction configuration; its presence opts the agent into automatic eviction + LLM compaction before each inference (mirrors the imperative loop’s Option<&CompactionConfig>).
ContextToolResults
Context-tool results computed inline by dispatch_tools (the context_* tools mutate the ECS window, so they can’t run on the async lane), held until collect_tools merges them with the lane results. Absent when a batch had no context tools.
DynamicTools
Marker: this agent opted into dynamic_tools. Only such agents are polled by poll_dynamic_tool_refresh for a pending tool re-scan, so the default (static) agent pays nothing.
GateScriptRules
The scripted gate rules (~/.config/leviath/rules/*.rhai), as a world resource. The daemon builds the checker (it owns the Rhai engine); the gate consults it after the static allowlist. Absent ⇒ no scripted rules.
InFlightWork
The cancellation handles for an agent’s currently in-flight async work (its inference request, its tool batch). Attached when the work is dispatched, removed when it lands - so the presence of this component means “there is something running for this agent that a cancel needs to stop”.
InferenceResults
The receiving end of the inference-outcomes channel, as a world resource for the collect system. (The sending end lives in InferenceStage.)
InferenceStage
The plumbing the inference-dispatch system needs: the per-model pools, the channel to report outcomes on, the tick wake handle, and a runtime handle to spawn the (bounded, per-request) worker tasks onto.
MessageIntake
The receiving end of the world’s inbound-message channel. Clients (the control API) send AgentMessages here; the delivery system routes and delivers them.
PendingEdgeCompact
Regions an edge transform asked to LLM-compact after a transition, awaiting the compaction lane (drained by dispatch_edge_compact).
PersistWatermark
Debounce watermark: the (iteration, stage index, status) last persisted for an agent. A snapshot is written only when one of these changes, so the world writes on meaningful progress rather than every tick. None until the first snapshot, so a freshly-spawned agent is always written once.
PersistenceStage
The sending end of the persistence I/O lane (the receiving end is drained by persistence_bridge::persistence_worker).
PolicyGate
The tool allowlist policy (policy.toml), as a world resource. The daemon inserts it; a taint-gated agent’s outbound calls are checked against it. When absent, the gate falls back to an empty policy (deny-by-clearance only).
ProcessResponse
The response has been applied and is ready to be examined for tool calls (or completion) by the process-response system.
Providers
The registered providers, as a world resource.
ReadyForTools
The response had tool calls; the agent is ready for the tool-dispatch system to run them (the calls live on its InferenceResult).
ReadyForTransition
The response had no tool calls; the agent is ready for the empty-response handler to decide finish vs. a “use your tools” nudge.
ReadyToInfer
The agent is active and ready to build a request and (permits allowing) dispatch inference.
RequiredReentries
Counts how many times the current stage has been re-run to satisfy required context regions. Absent ⇒ 0; reset when a new stage is entered.
ResolveTransition
The agent’s current stage is complete; the transition system will resolve the next stage (or completion).
ResolvedStage
A blueprint stage resolved to a concrete provider, model, and effective tool set - the per-stage input to spawn_agent. The caller (CLI / daemon) owns the model-selection policy (overrides, availability, user defaults) and tool filtering; the runtime just turns the result into agent data.
StageCursor
The index of the agent’s current stage within its blueprint.
StageInference
Resolved inference parameters for the agent’s current stage, set when it enters that stage. Pure data - the dispatch system reads it to build the request.
StageInferences
Pre-resolved StageInference for every stage of the agent’s blueprint, built once when the agent is spawned (the CLI resolves each stage’s provider, model, and tool definitions). The transition system swaps the agent’s StageInference to the entry for its new stage by index.
StageIoBuffer
Buffered per-stage output/log lines awaiting the persistence lane. Emitters (collect_inference, collect_tools) push; dispatch_persistence drains and clears, forwarding the lines to stages/<idx>/output.log (readable assistant output) and stages/<idx>/logs.log (tool + token + error events).
StageJustEntered
Transient tag: the agent just entered a stage (index + name). The sync_tool_stages system reads it to notify the ToolService of the stage change, then removes it. Carries the data so the tool service need not query the world.
StageLedger
One StageRecord per blueprint stage, seeded at spawn (names + Pending) and reconciled by dispatch_persistence (status + timestamps), with per-stage tokens accrued by collect_inference. Serialized to stages.json so the dashboard / serve API can show every stage’s real name and status - not just the active one (whose name is the only one carried in meta.json).
StageProgress
Per-stage progress counters, reset when an agent enters a stage.
StageSetup
Pre-resolved per-stage setup, applied by enter_stage when an agent enters a stage: inference parameters, tool-result routing, whether the stage accepts live user input, an optional stage-specific context layout, and an optional system prompt. Built once per stage when the agent is spawned (mirrors StageInferences) so stage entry stays synchronous and query-friendly. (Ported from the imperative loop’s per-stage setup in the CLI executor.)
StageSetups
Pre-resolved StageSetup for every stage of the agent’s blueprint.
ToolResults
The receiving end of the tool-outcomes channel, as a world resource.
ToolSensitivities
Per-tool output sensitivity for an agent, populated by the taint-gate system when taint tracking is enabled. Absent ⇒ taint off ⇒ results tagged Public.
ToolServiceRes
The tool service, as a world resource.
ToolStage
The job sender feeding the tool lane, as a world resource.
ToolsNeedRefresh
Marker: this agent’s advertised tools should be re-resolved before its next turn - mid-run dynamic tool discovery. Consumed by refresh_advertised_tools, which asks the ToolService for the stage’s fresh tool defs and writes them into the live StageInference.
TransitionResults
The receiving end of the transition-choice outcomes channel, as a world resource for the collect system. (The sending end lives in InferenceStage::transition_outcomes.)
VisitCounts
How many times the agent has entered each stage (for max_revisits).
WaitingForChildren
Marks a parent agent held at a requires_children stage boundary until all its spawned sub-agents are terminal. Distinct from FanOutWaiting (which is the fan-out split/merge wait).

Enums§

StageOutcome
How a stage ended, when that governs the transition. Absent ⇒ the stage completed normally. Read by resolve_transition to follow an error/max_iterations/stuck-conditioned edge (e.g. → error_recovery) when the stage errored, hit its iteration cap, or stopped making progress.

Constants§

WORKSPACE_CHECK_INTERVAL
How often (in per-stage iterations) check_workspace_health stats the agent’s working directory. One metadata call every few iterations is far cheaper than the tool failures it replaces.

Traits§

ToolService
Provides a per-agent tool-execution closure. The concrete implementation (in the CLI) holds each agent’s tool registry, workdir, and permission policy; the pipeline stays agnostic to how tools run. exec_for returns a boxed closure the tool worker runs off the tick.

Functions§

abort_terminal_work
Stop the in-flight work of every agent that has reached a terminal state, and drop the handles. Runs before the dispatch systems each tick, so a cancel takes effect on the very next tick rather than whenever the provider or tool happens to answer.
check_workspace_health
Workspace health guard: fail a run whose working directory has disappeared.
collect_compaction
Compaction-collect system: drain finished compaction jobs and apply each summary into its paired CompactHistory region, clearing the summarized source region. A provider error leaves the context untouched (best-effort). Either way the agent returns to ReadyToInfer. (Ported from the storage tail of AgentEngine::compact_region.)
collect_inference
Inference-collect system: drain completed inferences and apply them. A success is stored on the agent (bumping its iteration) and the agent advances to ProcessResponse; an error marks the agent Error. An outcome for an agent that is no longer AwaitingInference (cancelled or despawned between dispatch and now) is dropped.
collect_tools
Tool-collect system: drain finished tool batches and apply them. Results are written into the agent’s context window (routing/truncation/taint honored) and the agent loops back to ReadyToInfer. Outcomes for agents no longer AwaitingTools (cancelled/despawned) are dropped.
collect_transition_choice
Transition-choice collect: drain completed routing inferences, match each to a target stage (or completion), record the decision in context, and either enter the chosen stage (loop to ReadyToInfer) or mark the agent Complete. A provider error marks the agent Error.
deliver_messages
Message-delivery system: route inbound messages to their target agents’ inboxes (by agent id), then deliver each inbox into the agent’s context window - but only for agents whose current stage accepts messages; otherwise the messages wait in the inbox for a stage that does. Ported from AgentEngine::process_messages / deliver_inbox_messages.
detect_stuck_stage
Stuck-detection guard: for each ReadyToInfer agent whose current stage declares a stuck-conditioned edge, evaluate that edge’s thresholds against the stage’s progress. When one trips, write the diagnosis into context and route the agent down the stuck edge (ResolveTransition + StageOutcome::Stuck) instead of running another inference.
dispatch_compaction
Compaction-dispatch system: for each ReadyToInfer agent with CompactionSettings whose window is over the eviction threshold, do the synchronous eviction inline; if that surfaces regions needing LLM summarization (and content to summarize), build one request per region, acquire a permit for the compaction model, spawn the job, and hold the agent as AwaitingCompaction. Anything that can’t proceed (under threshold, nothing to summarize, provider missing, pool full) simply leaves the agent ReadyToInfer so inference proceeds - compaction is best-effort. (Ported from AgentEngine::evict_and_compact.)
dispatch_edge_compact
Edge-compaction dispatch: for each ReadyToInfer agent with a PendingEdgeCompact (an edge transform requested LLM summarization), spawn a compaction job for the named regions (reusing the compaction lane) and hold the agent AwaitingCompaction. If the agent has no compaction config, nothing to summarize, or no provider/permit, the request is dropped and the agent proceeds to inference un-compacted (memory-pressure compaction still applies later).
dispatch_inference
Inference-dispatch system: for every ReadyToInfer agent, resolve its provider and, if a per-model permit is free, build the request, spawn the inference job, and move it to AwaitingInference. If its provider is missing or no slot is free, it stays ReadyToInfer and is retried on a later tick - no blocking, no wasted task.
dispatch_persistence
dispatch_tools
Tool-dispatch system: for each ReadyForTools agent, apply its context_* tool calls inline (they mutate the ECS window) and hand the rest to the sequential tool lane, moving it to AwaitingTools. If a batch is all context tools there is nothing for the lane, so the results are applied immediately and the agent loops straight back to ReadyToInfer. The lane serializes execution, so there is no permit gate - every ready agent is enqueued in turn.
dispatch_transition_choice
Transition-choice dispatch: for each AwaitingTransitionChoice agent, inject the “which stage next?” prompt into its context, build a short deterministic request, acquire a per-model permit, spawn the inference onto the transition lane, and move it to AwaitingTransitionResponse. Provider-missing / pool-full leaves it choosing and retries next tick (same backpressure as dispatch_inference).
enforce_max_iterations
Max-iterations guard: for each ReadyToInfer agent whose per-stage inference count has reached the stage’s max_iterations, end the stage (routing to a max_iterations edge if one exists, else a normal transition) instead of running another inference. Ported from the imperative run_autonomous cap.
force_transition
Force an agent into the stage at target_idx via direct world access - the same effect as resolve_transition’s linear-Next arm, but callable from an exclusive system (e.g. the fan-out collector jumping to its merge_stage) or the daemon (spawning a fan-out worker directly at its worker stage) where no Commands queue is available. On a system-prompt overflow the agent is marked Error, mirroring the transition systems.
gate_requires_children
requires_children gate (exclusive, mirrors the fan-out wait): a stage marked requires_children may not transition while any of the agent’s spawned sub-agents (SubAgentChildren) are still running - the parent is held Waiting (WaitingForChildren) and resumes (re-inserting ResolveTransition, back to Active) once every child is terminal.
handle_empty_response
Empty-response system: for each ReadyForTransition agent decide whether the stage is done. If the agent has already made tool calls, or we’ve nudged the max number of times, the text response is accepted and the agent advances to ResolveTransition. Otherwise (text only, no work yet) the response + a “use your tools” nudge are added to context and the agent loops back to ReadyToInfer. Ported from AgentEngine::loop_handle_empty_tool_calls.
is_terminal_status
Whether an agent status is terminal (the run/child has finished).
poll_dynamic_tool_refresh
Poll each dynamic_tools agent for a pending tool re-scan and, when the tool service reports one, tag it ToolsNeedRefresh so refresh_advertised_tools re-advertises before its next turn. Only agents carrying DynamicTools are queried, so static agents (the default) cost nothing.
process_response
Process-response system: route each ProcessResponse agent by whether its last inference asked for tools. Tool calls present ⇒ ReadyForTools (and the stage’s running tool-call count is bumped); none ⇒ ReadyForTransition. Pure routing - no I/O.
reflect_interaction_status
Persistence-dispatch system: for each agent carrying run metadata whose (iteration, stage, status) has changed since its last snapshot, build the meta.json + context.json value snapshot and hand it to the persistence lane. Fire-and-forget - no result to collect; the single-worker lane keeps a given agent’s writes ordered. Agents without RunMetadata aren’t persisted. Interaction-status reflection system: mirror the shared InteractionHub’s open requests into agent status so a blocked agent shows as Waiting (and the dashboard / lev ps surface its prompt) instead of a silent Active.
refresh_advertised_tools
Re-advertise an agent’s tools mid-run: when tagged ToolsNeedRefresh, ask the tool service for this stage’s freshly-resolved tool defs and, if it returns a set, write it into the live StageInference (what the next inference request advertises, read fresh by build_request) and the matching StageInferences catalog entry (so a later revisit of this stage keeps the updated set). Always consumes the marker. This is the mechanism behind mid-run dynamic tool discovery and lazily-listed MCP tools.
require_context_regions
Required-region gate: before a normally-completed stage transitions, if it can write context and a required region is still empty, inject a nudge and re-run the stage (loop back to ReadyToInfer) instead of transitioning - bounded by the stage’s max_revisits (or a default cap), after which it proceeds with a warning. Skipped when the stage ended on an error / max-iter outcome (those transitions take precedence). Ported from the imperative gate.
resolve_transition
Transition-resolution system: for each ResolveTransition agent, resolve the next stage. Terminal ⇒ mark the agent Complete. A single/linear target ⇒ enter the new stage (swap its StageInference, reset stage progress, bump the visit count) and loop to ReadyToInfer. Multiple candidate edges ⇒ hand off to the async transition-choice system via AwaitingTransitionChoice.
spawn_agent
Spawn a fully-formed agent into world from its blueprint, task, and per-stage resolution, and return its entity. Builds every stage’s StageInference/StageSetup up front (so transitions are pure component swaps), seeds the context window, applies the first stage’s setup (its layout and system prompt), pre-counts the first stage’s visit, and marks the agent ReadyToInfer. Returns Err if the first stage’s system prompt doesn’t fit its region (the same hard failure the imperative loop raises at stage 0).
spawn_agent_seeded
Like spawn_agent, but seeds the context window from a name→content map (caller-input regions filled by the CLI/ACP/API, plus blueprint-resolved seeds) rather than a single task string. spawn_agent is the thin wrapper that seeds only the task key.
sync_tool_stages
Notify the ToolService of every agent that just entered a stage (tagged with StageJustEntered by the transition systems), so it can re-sync that agent’s per-stage tool permissions, then clear the tag. Runs after the transition systems each tick.