Skip to content
AGH RuntimeMemory

Memory System

How AGH stores curated Markdown memory, captures a frozen snapshot at session start, and routes every write through the controller WAL.

Audience
Operators running durable agent work
Focus
Memory guidance shaped for scanability, day-two clarity, and operator context.

AGH memory is curated Markdown that survives across sessions. It is designed for durable facts that future agents should be able to discover without replaying every old transcript.

The current implementation is intentionally hybrid:

  • curated semantic memory (user, feedback, project, reference) is Markdown-authoritative on disk
  • memory_decisions is a per-database write-ahead log: every controller decision lands there before any file mutation
  • memory_events is the canonical observability log for memory operations
  • memory_catalog_entries, memory_chunks, and FTS5 indexes are derived projections
  • memory_recall_signals and memory_consolidations carry live runtime state for dreaming
  • there are three scopes: global, workspace, and agent — agent has two tiers
  • only the frozen startup snapshot is injected into prompts; new writes become visible to the next session

Runtime Flow

Rendering diagram…

Every write — operator, agent, extractor, dreaming — goes through the controller. The WAL is durable before the file lands; the catalog is rebuilt from the file.

Memory is not streamed into an already-running process. When a session starts, AGH captures a frozen snapshot of the resolved scopes, packages a recall block, prepends the assembled memory section to the agent prompt, and hands that prompt to the ACP subprocess. Writes during the session are durable immediately but only become visible to the next session via a fresh snapshot.

Scopes And Authorities

ScopeStorage rootAuthority
global$AGH_HOME/memory/Cross-workspace user-wide facts.
workspace<workspace>/.agh/memory/Workspace-private project facts.
agent (workspace)<workspace>/.agh/agents/<agent>/memory/Default agent tier. Workspace-private agent state.
agent (global)$AGH_HOME/agents/<agent>/memory/Cross-workspace agent state. Explicit --agent-tier global.

Read precedence is agent-workspace ▸ agent-global ▸ workspace ▸ global. Identity is keyed by (type, slug) per scope, and a deeper scope shadows a shallower scope with the same identity. The runtime never silently merges shadowed entries — see Scopes.

Scope is selected explicitly. --scope agent requires --agent <name> and a validated --agent-tier {workspace, global}; the agent tier defaults to workspace when omitted. CLI/HTTP/UDS operator writes that omit --scope fall back to a conservative type-driven default for the non-agent scopes only: user and feedbackglobal, project and referenceworkspace. Agent scope must be explicit.

Workspace Identity

Workspace memory is keyed by a stable ULID stored in <workspace>/.agh/workspace.toml:

workspace_id = "01HXJ9YR4Q..."
created_at   = "2026-05-04T14:30:00Z"
realpath_at_creation = "/Users/you/dev/checkout-api"

The runtime resolves the workspace by walking ancestors for .agh/workspace.toml, reads the ULID, and uses that as the durable identity for catalog rows, events, decisions, dreaming runs, and session ledgers. Path-keyed memory is gone — moving the workspace directory does not orphan its memory because the ULID travels with the directory. See Workspace Resolver for the lookup cascade.

Four Memory Types

Every curated memory file declares one of four types:

TypeUse it forExample
userStable user preferences, working style, or recurring personal context."Prefer concise PR summaries with risk and test notes."
feedbackRepeated corrections, review guidance, and quality signals that apply across work."Do not weaken tests to match broken behavior."
projectDecisions, constraints, active architecture, and local project facts."This repo keeps docs site pages under packages/site/content/runtime/."
referenceExternal references, runbooks, links, or system facts worth re-reading on demand."Production logs live in the hosted provider console, not local files."

The taxonomy is closed. Unsupported types are rejected at the controller boundary.

Memory File Format

Memory files are Markdown with strict YAML frontmatter. The canonical YAML key for the agent name is agent; JSON and HTTP payloads use agent_name.

FieldRequired whenMeaning
nameyesHuman-readable title shown in list output and useful in index entries.
descriptionyesOne concise discovery sentence used by recall and indexing.
typeyesOne of user, feedback, project, or reference.
scopeyesOne of global, workspace, agent.
agentwhen scope = agentProducer agent name.
agent_tierwhen scope = agentOne of workspace, global.
provenanceoptionalSource actor, source sessions, confidence, supersession, timestamps.

Example feedback memory written through the controller:

---
name: Test Integrity
description: Production bugs must be fixed instead of weakening tests
type: feedback
scope: global
provenance:
  source_actor: extractor
  source_sessions:
    - 01J7VR2Q8MZ4FXWZ8WB7M2A4S0
  confidence: high
  created_at: 2026-04-12T14:32:11Z
  updated_at: 2026-04-12T14:32:11Z
---

If a test reveals incorrect behavior, fix the production code. Do not relax assertions just to make
the suite green.

Storage Layout

Each scope has a MEMORY.md index next to its memory documents and a structurally-excluded _system/ namespace for machine-managed artifacts:

$AGH_HOME/memory/
  MEMORY.md
  user_review-style.md
  feedback_test-integrity.md
  _inbox/                        # extractor staging (operator-quiet)
  _system/
    dreaming/
    extractor/
    extractor/failures/
    ad_hoc/

<workspace>/.agh/memory/
  MEMORY.md
  project_runtime-docs.md
  reference_session-events.md
  _system/
    dreaming/
    ...

<workspace>/.agh/agents/<agent>/memory/
  MEMORY.md
  user_pedro-style.md
  _system/
    ...

_system/ is reserved. Curated indexing skips it, recall filters it out by default, and the controller rejects any write that would land directly in a top-level _system_*.md file. Operators can browse _system/ artifacts explicitly with --include-system on list/show/search/etc.

The Write Controller

Every write — CLI, HTTP, UDS, native tool, extractor, dreaming, file-watcher, provider — passes through the controller:

  1. Caller submits a Candidate { workspace_id, scope, agent, agent_tier, origin, frontmatter, content, ... }.
  2. The controller computes a deterministic decision with rule-first lexical+entity-slot logic; an LLM tiebreaker runs only when the rule trace falls in the configured ambiguity band.
  3. The decision is persisted to memory_decisions (per-database WAL) before any file mutation, carrying full replay material: target_filename, frontmatter, post_content, post_content_hash, prior_content (for update/delete), idempotency_key, and the rule/LLM trace.
  4. The file mutation lands atomically; the catalog reindexes the affected file; a canonical memory_events row is appended.
  5. On crash, daemon boot replays unapplied decisions in decided_at order. Replay is idempotent by idempotency_key and post_content_hash.

There is exactly one write path. Controller-bypassing tools are forbidden; provider-supplied tools that collide with reserved names are rejected at registration with a memory.provider.collision event.

Frozen Snapshot And Recall

At session start, AGH captures a frozen snapshot of the resolved memory context (global, workspace, and the agent's two tiers when applicable). The snapshot includes:

  • the per-scope MEMORY.md index after staleness banners
  • a packaged recall block produced by the deterministic recall pipeline (FTS5 unicode + trigram, scope shadow, top-K) when a contextual query is available
  • a freshness banner for entries whose age exceeds memory.recall.freshness.banner_after_days

The snapshot is captured once per session and does not mutate mid-session. Sub-agent sessions inherit the parent snapshot read-only. Manual writes during the session land in the WAL and on disk, but the running session keeps its captured prompt; the next session sees a fresh snapshot.

_system/ artifacts are never injected into the prompt by default. Recall skips ledger files, extractor inbox/DLQ artifacts, and dreaming output unless the caller explicitly opts in.

Operator And Agent Surfaces

Memory is reachable from CLI, HTTP, UDS, and native tools with parity. The Slice 1 verbs are:

CapabilityCLIHTTP / UDSNative tool
List entriesagh memory listGET /api/memoryagh__memory_list
Show one entryagh memory show <filename>GET /api/memory/{filename}agh__memory_show
Search recallagh memory search <query>POST /api/memory/searchagh__memory_search
Operator writeagh memory writePOST /api/memoryn/a
Editagh memory edit <filename>PATCH /api/memory/{filename}agh__memory_propose
Deleteagh memory delete <filename>DELETE /api/memory/{filename}agh__memory_propose
Agent proposaln/acontroller-backed via POST /api/memory / PATCH /api/memory/{filename}agh__memory_propose
Ad-hoc noten/aPOST /api/memory/ad-hocagh__memory_note
Dream triggeragh memory dream triggerPOST /api/memory/dreams/triggeragh__memory_dream_trigger
Dream listingagh memory dream show <date-or-run-id>GET /api/memory/dreams, GET /api/memory/dreams/{dream_id}agh__memory_dream_list, agh__memory_dream_show
Dream retryagh memory dream retry <run_id>POST /api/memory/dreams/{dream_id}/retryagh__memory_dream_retry
Dream statusagh memory dream statusGET /api/memory/dreams/statusagh__memory_dream_status
Decisions listagh memory decisions listGET /api/memory/decisionsagh__memory_decisions_list
Decision detailagh memory decisions show <id>GET /api/memory/decisions/{decision_id}agh__memory_decisions_show
Decision revertagh memory decisions revert <id>POST /api/memory/decisions/{decision_id}/revertagh__memory_decisions_revert
Recall traceagh memory recall trace <session_id> <turn_seq>GET /api/memory/recall-traces/{session_id}/{turn_seq}agh__memory_recall_trace
Historyagh memory historyGET /api/memory/historyagh__memory_admin_history
Healthagh memory healthGET /api/memory/healthagh__memory_health
Config metadatan/aGET /api/memory/confign/a
Reindexagh memory reindexPOST /api/memory/reindexagh__memory_reindex
Promoteagh memory promote --from <scope[:tier]> --to <scope[:tier]>POST /api/memory/promoteagh__memory_promote
Resetagh memory resetPOST /api/memory/resetagh__memory_reset
Reload snapshotagh memory reloadPOST /api/memory/reloadagh__memory_reload
Scope inspectoragh memory scope-showGET /api/memory/scope-showagh__memory_scope_show
Daily logsagh memory daily lsGET /api/memory/dailyagh__memory_daily_list
Extractor statusagh memory extractor statusGET /api/memory/extractor/statusagh__memory_extractor_status
Extractor failuresagh memory extractor list-pendingGET /api/memory/extractor/failuresagh__memory_extractor_failures
Extractor replayagh memory extractor replay --session <id>POST /api/memory/extractor/retryagh__memory_extractor_retry
Extractor drainagh memory extractor drainPOST /api/memory/extractor/drainagh__memory_extractor_drain
Provider listagh memory provider listGET /api/memory/providers, GET /api/memory/providers/{provider_name}agh__memory_provider_list, agh__memory_provider_get
Provider selectn/aPOST /api/memory/providers/selectagh__memory_provider_select
Provider enableagh memory provider enable <name>POST /api/memory/providers/{provider_name}/enableagh__memory_provider_enable
Provider disableagh memory provider disable <name>POST /api/memory/providers/{provider_name}/disableagh__memory_provider_disable
Session ledgern/aGET /api/workspaces/{workspace_id}/memory/sessions/{session_id}/ledgeragh__memory_session_ledger
Session replayn/aPOST /api/workspaces/{workspace_id}/memory/sessions/{session_id}/replayagh__memory_session_replay
Session prunen/aPOST /api/memory/sessions/pruneagh__memory_sessions_prune
Session repairn/aPOST /api/memory/sessions/repairagh__memory_sessions_repair

Entry writes from agents still route through agh__memory_propose and agh__memory_note; both go through the controller. The operational tools live in the separate agh__memory_admin toolset and mirror the daemon CLI/API surfaces. There is no agh__memory_read, no agh__memory_history, no raw agh__memory_write, no raw agh__memory_edit, no raw agh__memory_delete, no agh memory read, and no agh memory consolidate in this slice — the renamed verbs above own the same intent.

CLI verbs accept -o json and -o jsonl for structured output. Errors are deterministic {code, message, details} payloads with stable codes such as memory.scope.invalid, memory.controller.timeout, and memory.provider.collision.

MEMORY.md Indexes

The per-scope MEMORY.md is the prompt-safe table of contents. AGH reads it inside the snapshot, caps it at [memory.file] max_lines = 200 and max_bytes = 25600, and includes the entries that fit. Useful index entries are short and point to one file:

- [Review Style](user_review-style.md) — User wants concise review findings with file references first.
- [Runtime Docs Location](project_runtime-docs.md) — Runtime docs live under `packages/site/content/runtime/`.
BehaviorCurrent implementation
Missing MEMORY.mdAGH synthesizes an index from memory-file frontmatter for that scope and warns when an existing index is stale.
Prompt limitsIndex injection is capped by [memory.file] max_lines and max_bytes.
Write behaviorController writes the file, updates the WAL, reindexes the catalog, and re-renders the scope index so new entries are discoverable.
Delete behaviorDeleting a memory file also removes index lines that link to that filename and emits memory.write.committed with op delete.
Full entry contentNot injected. Agents fetch full entries on demand with agh memory show <filename> or agh__memory_show.

Observability

Every controller decision and recall outcome is observable.

SurfaceUse it for
agh memory healthEnabled state, controller backlog, provider circuit state, dreaming gate status, and per-scope catalog/file counts.
agh memory decisions listThe Slice 1 truthful audit log: every committed/rejected/shadowed/reverted controller decision with redaction-safe traces.
agh memory recall trace <session_id> <turn_seq>The deterministic recall pipeline trace for a specific session turn: candidate set, scoring weights, freshness banners, and shadow-by-id outcomes.
agh memory extractor statusQueue and useful-work diagnostics: queued/in-flight sessions, active provider sessions, backpressured sessions, coalesced/dropped turns, skipped empty turns, and failure count.
GET /api/memory/healthSame data as agh memory health over HTTP/UDS.
GET /api/memory/decisionsSame data as agh memory decisions list with redaction-safe payloads (no post_content, prior_content, or raw LLM responses on the wire).
GET /api/memory/recall-traces/{session_id}/{turn_seq}Same data as agh memory recall trace over HTTP/UDS.
GET /api/memory/extractor/statusSame extractor queue and useful-work diagnostics over HTTP/UDS.

memory_events rows have stable canonical op names (memory.write.committed, memory.write.rejected, memory.recall.executed, memory.dream.run.promoted, memory.extractor.completed, memory.provider.collision, etc.). They are queryable through the event store and feed agh memory health and the web Memory inspector.

Skipped empty extractor turns are recorded as memory.extractor.dropped with metadata.reason = "empty_snapshot" and redaction-safe counters only. Extractor completion events carry candidate_count, and controller write decisions remain under memory.write.*.

agh memory history returns the same audit material in the legacy summary shape as a thin compatibility view over memory_events. Use agh memory decisions list when you need controller-level detail.

Basic Usage

Write a global preference (operator-only):

agh memory write \
  --scope global \
  --type user \
  --name "Review Style" \
  --description "User wants concise review findings with file references first" \
  --content "Put blocking findings first. Cite file paths and symbols."

Write a workspace decision in the current workspace:

agh memory write \
  --scope workspace \
  --type project \
  --name "Runtime Docs Location" \
  --description "Runtime docs live in the Fumadocs runtime collection" \
  --content 'Runtime docs are authored under `packages/site/content/runtime/` and build to `/runtime/*`.'

Write to a specific agent tier:

agh memory write \
  --scope agent \
  --agent reviewer \
  --agent-tier global \
  --type feedback \
  --name "Reviewer Tone" \
  --description "Reviewer keeps findings short and actionable" \
  --content "Lead with the blocker. Cite file:line. Keep lists tight."

List and show:

agh memory list
agh memory show project_runtime-docs.md --scope workspace

Search recall:

agh memory search "review tone" --scope agent --agent reviewer --agent-tier global

Trigger a gated dreaming pass:

agh memory dream trigger
  • Scopes explains scope selection, agent-tier rules, and shadowing.
  • Dream explains gates, signals, and what dream trigger actually changes.
  • Memory Best Practices gives concrete writing and hygiene guidance.
  • Memory CLI Reference lists every generated memory command.

On this page