Skip to content

hylo-memory

Hylo memory layer: episodic/spatial stores, action memory, lessons, skills

Repository hylo-harness, packages/hylo-memory. Licence: Apache-2.0. Depends on: hylo-core.

Registered entry points
Group Name Object
memory action_bank hylo.memory.action_bank:ActionBank
memory lesson_book hylo.memory.lessons:LessonBook
memory skill_library hylo.memory.skills:SkillLibrary
memory sqlite hylo.memory.sqlite:SQLiteMemoryStore
Module Summary
hylo.memory Hylo memory backends
hylo.memory.action_bank ActionBank: an in-memory, numpy-backed ActionMemory (RFC-0003)
hylo.memory.lessons LessonBook: language lessons from the agent's own experience, curated by delta operations (RFC-0003 M4)
hylo.memory.skills SkillLibrary: verified, versioned procedures for task families (RFC-0003 M3)
hylo.memory.sqlite SQLite episodic/spatial memory store (reference backend for the core MemoryStore protocol)

hylo.memory

Hylo memory backends.

META module-attribute

META = {'contracts': {'memory': 'hylo.memory/v0.1'}, 'maturity': 'implemented', 'plugins': {'memory/lesson_book': {'maturity': 'unverified', 'notes': 'experience campaigns not yet run'}, 'memory/skill_library': {'maturity': 'unverified', 'notes': 'experience campaigns not yet run'}, 'memory/sqlite': {'maturity': 'unverified'}}}

hylo.memory.action_bank

ActionBank: an in-memory, numpy-backed ActionMemory (RFC-0003).

Keys are L2-normalised vectors stored as float16 (cosine similarity = dot product); chunks keep their own length. Capacity is enforced FIFO (Retrieve-then-Steer: a 5k FIFO bank matches an unlimited one). A saved bank is bank.npz + bank.json (no pickle) and is frozen when loaded for evaluation: add raises, and snapshot() is the content digest that goes into the agent spec.

memory: {type: action_bank, params: {path: "artifact:l10-v1@<digest>"}}   # a store id (core.store) or a path

FrozenMemoryError

Bases: RuntimeError

ActionBank

ActionBank(path: str | None = None, capacity: int = 50000, frozen: bool | None = None)

capacity instance-attribute

capacity = capacity

frozen instance-attribute

frozen = path is not None if frozen is None else frozen

add

add(segments: Sequence[ActionSegment]) -> int

query

query(key: ndarray, *, task_id: str | None = None, k: int = 10) -> list[tuple[ActionSegment, float]]

snapshot

snapshot() -> str

save

save(path: str | Path) -> str

hylo.memory.lessons

LessonBook: language lessons from the agent's own experience, curated by delta operations (RFC-0003 M4).

After ExpeL (ADD / UPVOTE / DOWNVOTE / EDIT insight lists) and ACE (itemised playbook with helpful / harmful counters, incremental deltas instead of rewrites, which avoids "context collapse"). An LLM reflector proposes operations; this class applies them deterministically: - ADD whose title is near-identical (ratio >= dedup) to an active lesson in the same scope becomes an UPVOTE; - UPVOTE / DOWNVOTE move the counters (outcome feedback: candidates that cited a lesson and were promoted or refuted); - EDIT replaces the content and keeps the counters; RETIRE removes it from retrieval; - a lesson with harmful >= helpful + retire_margin retires itself. Every applied operation is appended to ops.jsonl (audit trail); lessons.json is the current state.

lessons: {type: lesson_book, params: {path: runs/lessons/libero10, frozen: true}}

OPS module-attribute

OPS = ('ADD', 'UPVOTE', 'DOWNVOTE', 'EDIT', 'RETIRE')

LessonBook

LessonBook(path: str, frozen: bool = False, dedup: float = 0.9, retire_margin: int = 2)

apply

apply(ops: Sequence[dict[str, Any]], *, source: str = '') -> list[dict[str, Any]]

Apply operations in order; returns what was actually done (invalid operations are reported, not raised).

query

query(scopes: Sequence[str] = ('global',), *, kind: str | None = None, top_k: int = 8) -> list[Lesson]

Active lessons in any of scopes, best net votes first (ties: most evidence).

sources

sources() -> set[str]

Sources of applied operations (lets writers stay idempotent across resumed campaigns).

all

all(status: str | None = None) -> list[Lesson]

snapshot

snapshot() -> str

hylo.memory.skills

SkillLibrary: verified, versioned procedures for task families (RFC-0003 M3).

A skill is data, never code: a plan template, a steering or recovery config patch, or a weights reference. Lifecycle: proposed -> verified (only through the RSI gate, with its statistics as evidence) | refuted; verified -> deprecated. match returns verified skills only, with the slot bindings captured by the trigger's instruction pattern. Usage feedback (useful / misleading / not_applicable) accumulates per version.

Storage: /@.json, one file per skill version. A library opened with frozen=True (evaluation) refuses every write, and snapshot() is the content digest recorded in the agent spec. export_skill_md writes one SKILL.md per verified skill (name + description front matter, body below) so an LLM can scan the index and read bodies on demand.

skills: {type: skill_library, params: {path: runs/skills/libero10, frozen: true}}

TRANSITIONS module-attribute

TRANSITIONS = {'proposed': {'verified', 'refuted'}, 'verified': {'deprecated'}, 'refuted': set(), 'deprecated': set()}

SkillLibrary

SkillLibrary(path: str, frozen: bool = False)

root instance-attribute

root = Path(path)

frozen instance-attribute

frozen = frozen

add

add(skill: Skill) -> str

transition

transition(skill_id: str, status: str, evidence: dict[str, Any] | None = None) -> Skill

annotate

annotate(skill_id: str, evidence: dict[str, Any]) -> Skill

Attach evidence without a status change (e.g. an underpowered gate result on a proposed skill).

record_verdict

record_verdict(skill_id: str, verdict: str) -> None

get

get(skill_id: str) -> Skill

all

all(status: str | None = None) -> list[Skill]

match

match(instruction: str, *, task_tags: tuple[str, ...] = (), env: str | None = None, kinds: tuple[str, ...] | None = None) -> list[tuple[Skill, dict[str, str]]]

Verified skills whose trigger fits, most specific first (pattern > tags > env), then most useful.

snapshot

snapshot() -> str

index

index(status: str | None = 'verified', *, with_stats: bool = False) -> list[dict[str, Any]]

What a proposer or planner may see. Gate numbers are withheld by default: a proposer that reads effect sizes and p-values can adaptively overfit the gate split, so it gets the status (a verdict) only.

export_skill_md

export_skill_md(out_dir: str) -> int

normalise_instruction

normalise_instruction(text: str) -> str

hylo.memory.sqlite

SQLite episodic/spatial memory store (reference backend for the core MemoryStore protocol).

SQLiteMemoryStore

SQLiteMemoryStore(path: str | Path = ':memory:')

Episodic + spatial store. Spatial queries use a bounding-box index then an exact radius check; a production spatial backend (Spark-DSG) would replace this behind the same interface.

db instance-attribute

db = sqlite3.connect(str(path))

write

write(items: Sequence[MemoryItem]) -> WriteResult

query

query(q: MemoryQuery) -> list[Hit]

forget

forget(q: MemoryQuery) -> int

snapshot

snapshot() -> str