Expand description
ainl-runtime v0.3.5-alpha — orchestration layer for the unified AINL graph (memory substrate + extraction).
This crate does not call LLMs, parse AINL IR, or implement tool adapters. It coordinates
ainl_memory, persona axis state via ainl_persona::EvolutionEngine (shared with
ainl_graph_extractor::GraphExtractorTask), and scheduled graph extraction — with TurnHooks for host
integration (e.g. OpenFang).
Evolution: EvolutionEngine lives in ainl-persona. AinlRuntime::evolution_engine_mut and
helpers (AinlRuntime::apply_evolution_signals, AinlRuntime::persist_evolution_snapshot, …) drive it
without going through the extractor. GraphExtractorTask::run_pass remains one signal producer (graph
extract + recurrence + pattern heuristics), not the only way to evolve persona axes.
Scheduled passes attach ExtractionReport to TurnResult; populated
extract_error / pattern_error / persona_error slots become separate TurnWarning entries
tagged with TurnPhase::ExtractionPass, TurnPhase::PatternPersistence, and TurnPhase::PersonaEvolution.
For a minimal “record episodes + run extractor” path without the full engine, see RuntimeContext.
§Semantic ranking / MemoryContext
compile_memory_context_for(None) no longer inherits previous episode text for semantic
ranking; pass Some(user_message) if you want topic-aware MemoryContext::relevant_semantic.
AinlRuntime::compile_memory_context still calls compile_memory_context_for(None) (empty
message → high-recurrence fallback). AinlRuntime::run_turn always passes the current turn text.
§Episodic tools_invoked (canonical storage)
Raw TurnInput::tools_invoked strings are normalized with ainl_semantic_tagger::tag_tool_names
before the episode row is written: stored values are canonical tool tag values, deduplicated and
sorted. Empty input uses ["turn"]. The emit payload’s tool list matches the persisted episode.
§Episode id in turn results
The returned episode identifier is the graph node row id (AinlMemoryNode::id), not necessarily
EpisodicNode::turn_id. Use it for EMIT_TO edges and store queries keyed by node id.
Async / Tokio: enable the optional async crate feature for AinlRuntime::run_turn_async.
Graph memory is then Arc<std::sync::Mutex<GraphMemory>> (not tokio::sync::Mutex) so
AinlRuntime::new and AinlRuntime::sqlite_store can take short locks on any thread; SQLite
work for async turns is still offloaded with tokio::task::spawn_blocking. See the crate
README.md for rationale; ArmaraOS hub docs/ainl-runtime.md, patch dispatch
docs/ainl-runtime-graph-patch.md, and optional OpenFang embed docs/ainl-runtime-integration.md
cover host integration and registry crates.io pins.
Structs§
- Adapter
Registry - Ainl
Graph Artifact - A loaded, validated AINL graph artifact (memory substrate view for one agent).
- Ainl
Runtime - Orchestrates ainl-memory, persona snapshot state, and graph extraction for one agent.
- Evolution
Engine - Extraction
Report - Result of
GraphExtractorTask::run_pass. Errors are carried per phase; the pass does not returnResultso callers can record partial progress and continue. - Graph
Extractor Task - Graph
Patch Adapter - Reference adapter registered as
Self::NAME. Used as a fallback when no label-specificPatchAdapteris registered for the procedural patch label. - Memory
Context - Compiled memory context for a turn (prompt-side assembly in the host).
- NoOp
Async Hooks - Default async hook implementation (no side effects).
- NoOp
Hooks - Default hook implementation (no side effects).
- Patch
Dispatch Context - Per-patch inputs for
crate::PatchAdapter::execute_patch(procedural patch nodes). - Patch
Dispatch Result - Result of attempting to dispatch one procedural patch node.
- Persona
Snapshot - RawSignal
- Runtime
Config - Configuration for
AinlRuntimeandRuntimeContext. - Runtime
Context - Host context: optional memory plus optional stateful extractor (legacy / lightweight).
- Sqlite
Store Ref - Borrowed view of the backing SQLite store (see
crate::AinlRuntime::sqlite_store). - Turn
Input - Input for a single agent turn (host fills; runtime does not call LLMs).
- Turn
Result - Payload from a finished turn (memory context, episode id, patch dispatch, etc.).
- Turn
Warning - One non-fatal failure recorded during a turn (the turn still returns a usable
TurnResult).
Enums§
- Ainl
Runtime Error - Hard failure for
crate::AinlRuntime::run_turn(store open, invalid graph, invalid compile input, etc.). - Memory
Node Type - Patch
Skip Reason - Persona
Axis - Turn
Outcome - Full success vs partial success after non-fatal write failures.
- Turn
Phase - Non-fatal bookkeeping phase inside [
AinlRuntime::run_turn] (SQLite / export / persona persistence). - Turn
Status - Soft outcome for step caps / disabled graph (not store write failures — those become
TurnWarning).
Constants§
- EMIT_
TO_ EDGE - Edge label for emit routing (matches
ainl_graph_edges.label). - EVOLUTION_
TRAIT_ NAME - Canonical
ainl_memory::PersonaNode::trait_namefor axis-evolution bundles.graph_extractor(Prompt 2) should import this from the crate root when selecting persona rows for domain / formality signals — do not duplicate the string. - INGEST_
SCORE_ EPSILON - Minimum absolute score delta on an axis for a signal to count as “applied” in
EvolutionEngine::ingest_signals.
Traits§
- Graph
Patch Host Dispatch - Optional host hook: receives the same JSON summary as
GraphPatchAdapter::execute_patch. - Patch
Adapter - Label-keyed procedural patch executor. Register via
crate::AinlRuntime::register_adapter. - Turn
Hooks - Hooks for observability and host wiring. Every method has a default empty body.
- Turn
Hooks Async - Async observability hooks for
crate::AinlRuntime::run_turn_async(Tokio-friendly).
Functions§
- default_
axis_ map - infer_
topic_ tags - Deterministic keyword tagging for broad topics. One tag per topic slug; confidence is the max
across that slug’s keyword hits (
0.85exact / phrase,0.70substring for single-token keys). - run_
extraction_ pass - Convenience wrapper for one-off extraction. Creates a fresh
GraphExtractorTaskwith a newcrate::PersonaSignalExtractorStateon each call, so streak-based detectors (brevity, formality) cannot fire across invocations. For long-running agent loops, instantiateGraphExtractorTaskdirectly and callGraphExtractorTask::run_passto preserve streak state between passes.