types/contracts

The important architecture lives in small contracts. Provider components, protocol drivers, tool definitions, output contracts, plugin hooks, store commits, process admins, trigger operations, read projections, AgentFrames, and observability sinks: each a named seam.

Core Contracts

These abstractions define the system more precisely than crate names do.

AbstractionOwnerRole
TurnMachine, Effect, Response, EffectId, TurnCheckpointlash-sansioPure turn state machine and response protocol. Checkpoints are a sans-IO primitive for machine round-trips and tests; runtime crash recovery is owned by effect hosts and committed state stores.
EffectHost, ExecutionScope, ScopedEffectController, RuntimeEffectEnvelope, RuntimeEffectLocalExecutorlash-coreTyped durable effect boundary for LLM calls, atomic tool attempts, process admin, retry sleeps, RLM exec, checkpoints, and execution-surface sync. Envelopes carry a serialized RuntimeInvocation with scope, subject, optional causal parent, and replay.key; durable hosts such as Temporal, Restate, or another workflow runtime own effect replay and timers.
TurnOutcome, TurnFinish, TurnStoplash-sansioThree-class turn result: Finished{AssistantMessage|FinalValue|ToolValue}, AgentFrameSwitch{frame_key, task}, Stopped{Cancelled|Incomplete|InvalidInput|MaxTurns|ToolFailure|ProviderError|PluginAbort|RuntimeError|SubmittedError{...}|ToolError{...}}.
ProtocolBuildInput, TurnDriverPreamble, ContextProjector, ProtocolDriverHandlelash-core + lash-sansio + protocol cratesProtocolBuildInput carries the effective tool catalog and generic prompt/protocol context from the runtime into mode preamble builders. Protocol-specific prompt surfaces, including RLM's Lashlang host environment, are built by the protocol/runtime crates. TurnDriverPreamble, projectors, and protocol drivers stay mode-agnostic in lash-sansio.
LashCore, SessionBuilder, LashSession, TurnBuilderlashApp-facing facade for shared core configuration, session opening/resume, the stable host-owned session handle, and semantic turn streaming.
Session, AgentFrameRecord, SessionGraphlash-coreSession is the durable work identity; immutable FrameOpen graph nodes record agent assignments, and AgentFrameRecord is a derived ancestry view used for export and debugging.
SessionRelation::{Root, Child}lash-coreHow a new session relates to its parent: top-level root, or child session with optional typed CausalRef. continue_as appends an agent frame inside the same session instead of creating a related session.
PluginOptions, RlmCreateExtras, RlmProjectedSeedSnapshotlash-core + lash-rlm-typesPlugin-owned session-creation payloads. RLM carries a termination policy and an optional projected-binding seed for AgentFrame switches and spawned agents.
PluginSessionContext, SubagentSessionContextlash-corePer-session context handed to plugin factories, plus the marker that identifies a session as a subagent and tracks parent session id, capability, and depth.
SessionSnapshot, RuntimeSessionStatelash-corePublic serializable session snapshots and runtime-private mutable state: graph, derived current frame node id, policy, turn index, usage, store refs, and store head metadata. Frame records are reconstructed from FrameOpen ancestry; execution snapshots are checkpoint/anchor state rather than frame fields.
AgentFrameRun, stream_turn_with_agent_frameslash-coreInternal AgentFrame switch-following runtime primitive used by the lash facade. App hosts normally use TurnBuilder::stream_to, TurnBuilder::run, or pull-style TurnBuilder::stream.
AttemptContext, InternalProcessContext, OrchestrationContextlash-coreThe runtime-session boundary is projected by durable class: leaf bodies get controller-free reads and return intents, owner-bound process bodies get internal process capabilities, and authored orchestration gets replay-safe commands. No leaf body receives the runtime handle or process administration.
TurnBoundary, TurnCommitDraft, TurnGraphEditorlash-coreTurn-scoped typed graph writes, checkpoint, usage, and read-state commit policy.
SessionGraph, SessionReadView, ChronologicalProjectionlash-coreDurable event storage, public read seam, and semantic chronological projection, all in lash-core. A host's timeline projection is a render projection downstream of ChronologicalProjection.
RuntimePersistence, RuntimeCommit, GraphAppendlash-coreRuntime persistence contract for the advisory per-session execution lease, graph/head commits, current AgentFrame metadata, pending turn input, queued work, committed checkpoints, and final turn commit idempotency. Head CAS is the exclusive commit authority.
RuntimePersistence implementationshost / store cratesThe store contract is database-agnostic. First-party implementations include lash-sqlite-store for local durable hosts and lash-postgres-store for shared workers; hosts can provide another database-backed implementation when it preserves the same session-lease, CAS, queue, process, trigger, artifact, and blob semantics.
ProcessStartRequest, ProcessService::start_from_requestlash-coreCanonical process-start request path. Facade, runtime, and tool controls pass a typed request into the service helper; only the service reconstructs the internal ProcessRegistration and ProcessStartOptions.
ProcessService::validate_visible, ProcessService::cancel, ProcessService::signal_possessed, ProcessService::cancel_all_visiblelash-coreUnified process-handle authority surface. Callers validate the run-local-or-visible gate, then use the single cancellation and possessed-signal primitives; cancel-all returns a ProcessCancelReceipt for each visible live process.
ProviderHandle, ProviderComponentslash-coreRuntime-only provider handle split by state, auth, readiness, transport, and model policy. Session persistence records only provider_id and rebinds it to the live handle supplied by the host.
ToolDefinition, ToolCatalog, ToolOutputContract, ToolCallOutput, ToolCallRecordlash-sansioTool catalog membership (a tool is callable iff it is a catalog member), model schema, examples, compact docs, dynamic return contracts, and canonical tool-call output records. App-facing tool implementations return lash::tools::ToolOutcome / lash_core::ToolOutcome, which core converts into this canonical output shape.
PluginFactory, SessionPlugin, PluginRegistrarlash-corePlugin lifecycle and hook registration for tools, prompts, modes, runtime events, and host-callable RPCs.
LlmToolsPluginFactory, DirectCompletionClient::direct_completionlash-llm-tools + lash-coreThe reference ordinary effectful tool: llm_query uses normal tool registration and dispatch, output-schema handling, direct completion inside its atomic attempt, and usage relay.
RlmControlToolsProviderlash-protocol-rlmMode-provided RLM control tools such as continue_as, which produces a TurnOutcome::AgentFrameSwitch.
LashlangHostEnvironment, ModuleArtifact, ProcessDefinitionIdentity, compile_modulelashlang + lash-lashlang-runtime + lash-protocol-rlmThe linked host surface gates resource operations, process declarations/starts, process sleep/signals, trigger registry operations, and optional language features such as @label annotations. Disabled features parse but fail during linking before runtime side effects. Hosts compile modules through the facade/runtime integration to get content-addressed artifact refs, stable introspection, and exported process definition identities. Stored Lashlang process input is an opaque ProcessInput::Engine { kind: "lashlang", payload }; the Lashlang process engine loads the artifact by module_ref before compiling the selected process_ref.
TriggerHostOperation, TriggerRegistrationRequest, ProcessDefinitionIdentitylashlang + lash-lashlang-runtime + lash-coreCanonical trigger register/list/cancel contract. Lashlang owns operation strings, resource operation shapes, request decoding, process-definition identity, trigger compatibility checks, alias resolution, and event/input assignability; the Lashlang runtime bridges those operations to core's durable registration storage and source-key matched trigger delivery.
RlmProjectedBindings, ProjectionRef, ProjectionResolver, ProjectionRegistrylash-protocol-rlmPublic RLM projection API. Inline bindings carry JSON/lashlang values; lazy bindings carry stable refs that resolve to low-level projected values immediately before execution.
ProjectedBindings, ProjectedValue, ProjectedHostDescriptor, ProjectedReadRequest, ProjectedReadResponselashlangLow-level read-only Lashlang projection protocol. ProjectedValue can carry opaque projection-ref metadata for snapshot/seed rehydration; assignment over a projected name is rejected at runtime.
ToolResultProjector, ToolOutputBudgetPluginFactory, ToolOutputBudgetConfiglash-plugin-tool-output-budgetSingle exclusive tool-result projector (registered via reg.tool_results().projector(...)) that derives the budgeted model-facing ModelToolReturn from each completed call's full ToolCallOutput, with ToolOutputBudgetMode::{Bytes, Tokens} limits (defaults: 16 KiB, 400 lines).
ToolDiscoveryIndex, CatalogTool, llm_rerank_requesthost-side MCP discovery exampleHost-owned search/load tool discovery pipeline split across catalog preview, ranking, rerank, and schema-index modules.
TraceSink, TraceEvent::LanguageExecution, OtelTraceSinklash-trace + lash-coreRuntime observability contracts. Ordinary traces flow through the configured trace sink; language execution events carry a producer-stamped language field ("lashlang" for Lashlang), and Lashlang execution graphs use a separate opt-in sink with execution maps, node, branch, and child-link records. Static @label metadata is emitted once in execution-map node label_metadata; OpenTelemetry export is feature-gated.
UiTimelineItem, ActivityBlock, TuiExtensionsexternal host UI layerHost render projection, tool activity display, and host-provided surface slots.

Plugin Registration

Plugins are assembled per session. Each plugin can contribute protocol drivers, native tools, tool-catalog entries, prompt text, lifecycle hooks, host-callable RPCs, and UI activity.

Plugin contract shape
flowchart LR Factory["PluginFactory"] --> SessionPlugin["SessionPlugin"] SessionPlugin --> Registrar["PluginRegistrar"] Registrar --> Mode["mode hooks
session + driver + native tools"] Registrar --> Tools["ToolProvider
ToolCatalogContributor"] Registrar --> Prompt["PromptContributor
context transforms"] Registrar --> Runtime["runtime events
plugin actions"] Registrar --> UI["UI activity / panels"] Mode --> Session["Session"] Tools --> Session Prompt --> Session Runtime --> Session UI --> CLI["external host projection"]

Boundary Rules

The current codebase relies on these separations staying explicit.

  1. No UI vocabulary in core runtime.

    UiTimelineItem and rendering stay in the Host Application.

  2. Provider quirks stay at provider boundary.

    OpenAI-compatible schema normalization belongs in request builders, not canonical tool definitions.

  3. Graph storage is not chronological policy.

    Dedupe and ordering live in projections such as ChronologicalProjection.

  4. Background work is handle-shaped.

    Started tool calls, including spawn_agent fan-out, are rediscovered through processes.list.

  5. Host bindings are projected, not copied.

    RLM exposes history and any host globals to Lashlang via RlmProjectedBindings. Lazy values are passed as ProjectionRefs and resolved at execution time; snapshot restore rehydrates ref-backed projected values instead of copying or materializing them.

read on ·