Skip to content

API reference

Agent factories

deep_memory_agent.agents

Factories for the two memory agents.

The package deliberately ships two agents instead of one. Recall and curation pull in opposite directions: recall wants a narrow, read-only surface it cannot corrupt, while curation needs write access and a prompt about supersession and consolidation. Splitting them also keeps a single writer over the tree, which is what makes a file-based memory safe to share between agents.

Both factories take either memory_dir — the default on-disk wiring — or a ready-made backend, never both.

READ_ONLY_MEMORY_PERMISSIONS module-attribute

READ_ONLY_MEMORY_PERMISSIONS = [
    FilesystemPermission(
        operations=["write"],
        paths=[f"{MEMORY_ROOT}**", MEMORY_ROOT.rstrip("/")],
        mode="deny",
    )
]

Backend-level guard that makes the memory tree read-only.

Withholding the write tools is not enough on its own: the built-in write_file, edit_file and delete tools would still reach /memory/. This rule denies them at the filesystem middleware, so recall stays read-only even if a caller adds tools of their own.

create_memory_search_agent

create_memory_search_agent(
    model: str | BaseChatModel,
    *,
    memory_dir: str | Path | None = None,
    backend: BackendProtocol | None = None,
    system_prompt: str | None = None,
    tools: Sequence[BaseTool] = (),
    name: str = "memory_search_agent",
    **kwargs: Any,
) -> CompiledStateGraph

Build a read-only agent that answers from memory.

The agent gets memory_index, memory_search and memory_read, and is denied every write on /memory/ at the backend level. It is the safe agent to expose to callers who should be able to consult memory but never change it.

Parameters:

Name Type Description Default
model str | BaseChatModel

Chat model, or an identifier resolvable by deepagents.

required
memory_dir str | Path | None

Host directory holding the memory tree. Mutually exclusive with backend; exactly one of the two is required.

None
backend BackendProtocol | None

A ready-made backend serving /memory/. Mutually exclusive with memory_dir.

None
system_prompt str | None

Overrides the built-in recall prompt. Pass one only if you also restate the layout rules the built-in prompt carries.

None
tools Sequence[BaseTool]

Extra tools to expose alongside the recall tools.

()
name str

Name of the compiled graph.

'memory_search_agent'
**kwargs Any

Forwarded to deepagents.create_deep_agent, e.g. checkpointer or interrupt_on.

{}

Returns:

Type Description
CompiledStateGraph

The compiled agent.

Raises:

Type Description
ValueError

If both memory_dir and backend are given, or neither.

create_memory_manager_agent

create_memory_manager_agent(
    model: str | BaseChatModel,
    *,
    memory_dir: str | Path | None = None,
    backend: BackendProtocol | None = None,
    system_prompt: str | None = None,
    tools: Sequence[BaseTool] = (),
    consolidation_model: str | BaseChatModel | None = None,
    name: str = "memory_manager_agent",
    **kwargs: Any,
) -> CompiledStateGraph

Build the agent that curates memory.

It gets the recall tools plus memory_write, memory_update and memory_consolidate, and is meant to be the single writer of the tree: concurrent writers on plain markdown files lose data, and nothing here locks.

Parameters:

Name Type Description Default
model str | BaseChatModel

Chat model, or an identifier resolvable by deepagents.

required
memory_dir str | Path | None

Host directory holding the memory tree. Mutually exclusive with backend; exactly one of the two is required.

None
backend BackendProtocol | None

A ready-made backend serving /memory/. Mutually exclusive with memory_dir.

None
system_prompt str | None

Overrides the built-in curation prompt. Pass one only if you also restate the layout rules the built-in prompt carries.

None
tools Sequence[BaseTool]

Extra tools to expose alongside the memory tools.

()
consolidation_model str | BaseChatModel | None

Model used by memory_consolidate. Defaults to model.

None
name str

Name of the compiled graph.

'memory_manager_agent'
**kwargs Any

Forwarded to deepagents.create_deep_agent, e.g. checkpointer or interrupt_on.

{}

Returns:

Type Description
CompiledStateGraph

The compiled agent.

Raises:

Type Description
ValueError

If both memory_dir and backend are given, or neither.

Store

deep_memory_agent.store

Read and write operations over the memory tree.

MemoryStore is the single place that knows how memory is laid out on the virtual filesystem: which file an entry belongs in, how frontmatter is appended, how a superseded entry is retired and how the router indexes are kept in step. The agent tools in deep_memory_agent.tools are thin wrappers over it, which keeps the file format testable without spinning up a model.

Every operation goes through the deepagents backend. Nothing in this module opens a host path.

MemoryHit dataclass

An entry found by a search, with the file it lives in.

Attributes:

Name Type Description
path str

Absolute virtual path of the file holding the entry.

entry MemoryEntry

The entry itself.

MemoryStore

File-backed store for episodic, semantic and procedural memory.

Parameters:

Name Type Description Default
backend BackendProtocol

Backend serving the /memory/ tree.

required
backend property
backend: BackendProtocol

The backend every operation goes through.

__init__
__init__(backend: BackendProtocol) -> None

Bind the store to a backend.

ensure_tree
ensure_tree() -> list[str]

Create any missing file of the memory tree.

Returns:

Type Description
list[str]

The paths that were created.

read_file
read_file(
    path: str, offset: int = 0, limit: int = 2000
) -> str

Read a memory file.

Parameters:

Name Type Description Default
path str

Absolute virtual path, which must sit under /memory/.

required
offset int

First line to read, 0-indexed.

0
limit int

Maximum number of lines to read.

2000

Returns:

Type Description
str

The file's content.

Raises:

Type Description
ValueError

If the path escapes the memory tree or cannot be read.

write
write(
    category: MemoryCategory,
    body: str,
    *,
    summary: str = "",
    tags: tuple[str, ...] = (),
    source: str = "agent",
    confidence: Confidence = MEDIUM,
    supersedes: str | None = None,
    title: str | None = None,
    when: datetime | None = None,
) -> MemoryHit

Append an entry to the file its category maps to.

The target file is created with a heading if it does not exist yet, the router index of the owning kind is updated, and — when supersedes is given — the replaced entry is retired in place.

Parameters:

Name Type Description Default
category MemoryCategory

Which file family the entry belongs to.

required
body str

Markdown content of the entry.

required
summary str

One-line description, used in the router index.

''
tags tuple[str, ...]

Labels used to narrow later searches.

()
source str

Where the information came from.

'agent'
confidence Confidence

How much the entry is trusted.

MEDIUM
supersedes str | None

Identifier of an entry this one replaces.

None
title str | None

Procedure title; required for procedural entries.

None
when datetime | None

Instant the entry refers to. Defaults to now, in UTC.

None

Returns:

Type Description
MemoryHit

The stored entry and the file it landed in.

Raises:

Type Description
ValueError

If the entry cannot be rendered or the write fails.

get
get(entry_id: str) -> MemoryHit | None

Find an entry by identifier.

Parameters:

Name Type Description Default
entry_id str

Identifier to look for.

required

Returns:

Type Description
MemoryHit | None

The entry and its file, or None if no entry carries that id.

search
search(
    query: str = "",
    *,
    kind: MemoryKind | None = None,
    category: MemoryCategory | None = None,
    tags: tuple[str, ...] = (),
    include_superseded: bool = False,
    limit: int = _DEFAULT_SEARCH_LIMIT,
) -> list[MemoryHit]

Search entries lexically, newest first.

Matching is a case-insensitive substring test over summary, body and tags. It is deliberately simple: the frontmatter is what makes a stronger index — BM25, embeddings — addable later without changing the files themselves.

Parameters:

Name Type Description Default
query str

Text to look for. Empty matches everything.

''
kind MemoryKind | None

Restrict to one memory kind.

None
category MemoryCategory | None

Restrict to one category.

None
tags tuple[str, ...]

Only return entries carrying all of these tags.

()
include_superseded bool

Whether to return entries a newer one replaced.

False
limit int

Maximum number of hits.

_DEFAULT_SEARCH_LIMIT

Returns:

Type Description
list[MemoryHit]

Matching entries, most recent first.

recent_episodes
recent_episodes(
    *, since: datetime | None = None, limit: int = 100
) -> list[MemoryHit]

Return recent episodic entries, oldest first.

Parameters:

Name Type Description Default
since datetime | None

Only return entries created at or after this instant.

None
limit int

Maximum number of entries.

100

Returns:

Type Description
list[MemoryHit]

Episodic entries in chronological order.

Tools

deep_memory_agent.tools

Agent-facing memory tools.

Each tool is a thin wrapper over MemoryStore, bound to a backend by closure. That binding is what enforces the core constraint of this package: tools reach memory only through the deepagents backend, never through the host filesystem, so the same agent works unchanged against a directory on disk, thread state, or a remote store.

Tools are split in two sets on purpose. The recall set is read-only and is all the search agent gets; the write set is what makes the manager agent the single writer of the tree.

build_recall_tools

build_recall_tools(store: MemoryStore) -> list[BaseTool]

Build the read-only memory tools.

Parameters:

Name Type Description Default
store MemoryStore

Store bound to the backend serving /memory/.

required

Returns:

Type Description
list[BaseTool]

The memory_index, memory_search and memory_read tools.

build_write_tools

build_write_tools(
    store: MemoryStore,
    *,
    consolidation_model: str | BaseChatModel | None = None,
) -> list[BaseTool]

Build the memory-writing tools.

Parameters:

Name Type Description Default
store MemoryStore

Store bound to the backend serving /memory/.

required
consolidation_model str | BaseChatModel | None

Model used by memory_consolidate. When None, the tool is not built, since consolidation needs a model to judge what has hardened into durable knowledge.

None

Returns:

Type Description
list[BaseTool]

The memory_write and memory_update tools, plus memory_consolidate

list[BaseTool]

when a model was given.

Consolidation

deep_memory_agent.consolidation

Consolidation: promoting episodes into durable knowledge.

Episodic memory on its own is a log. Without a step that reads it and extracts what turned out to be stable, the agent has to re-read its whole history to learn anything from it — expensive and unreliable. Consolidation is that step: it reads recent episodes, asks a model which of them have hardened into facts, rules or procedures, and writes those as semantic or procedural entries with source: consolidation.

Episodes are never deleted. Consolidation only ever adds durable knowledge and supersedes semantic entries it contradicts, so the raw history stays auditable.

The function is public and takes a plain backend, so it can be scheduled from ordinary code — a cron job, a nightly task — without going through a conversation. The manager agent also exposes it as the memory_consolidate tool.

ConsolidatedItem

Bases: BaseModel

One piece of durable knowledge proposed by consolidation.

ConsolidationProposal

Bases: BaseModel

What the model proposes to promote out of episodic memory.

ConsolidationResult dataclass

Outcome of a consolidation run.

Attributes:

Name Type Description
entries list[MemoryHit]

The durable entries that were written.

episodes_considered int

How many episodic entries were read.

rationale str

The model's explanation for its choices.

consolidate_memory

consolidate_memory(
    backend: BackendProtocol,
    model: str | BaseChatModel,
    *,
    since: datetime | None = None,
    limit: int = _DEFAULT_EPISODE_LIMIT,
) -> ConsolidationResult

Promote stable patterns from episodic into semantic and procedural memory.

Parameters:

Name Type Description Default
backend BackendProtocol

Backend serving the /memory/ tree.

required
model str | BaseChatModel

Chat model, or a model identifier resolvable by init_chat_model, used to judge what has hardened.

required
since datetime | None

Only consider episodes created at or after this instant.

None
limit int

Maximum number of episodes to read.

_DEFAULT_EPISODE_LIMIT

Returns:

Type Description
ConsolidationResult

The entries written, how many episodes were read, and the model's

ConsolidationResult

rationale. Writing nothing is a normal outcome.

Backends

deep_memory_agent.backends

Backend wiring for the memory filesystem.

The agents in this package never touch the host filesystem: every read and write goes through a deepagents BackendProtocol, which is what maps the virtual /memory/ tree onto real storage.

The default wiring is a CompositeBackend that routes /memory/ to a FilesystemBackend rooted at memory_dir, and leaves everything else on an ephemeral StateBackend. Memory therefore lands on disk as plain markdown files — inspectable, diffable, versionable with git — while the agent's scratch files stay in thread state and disappear with it.

That default only holds inside a deep agent. StateBackend reads and writes through LangGraph's config keys and raises outside a graph execution, and CompositeBackend fans unscoped glob/grep calls out to every backend — so a standalone caller such as consolidate_memory hits the default even though all of its paths live under /memory/. Pass for_deep_agent=False to swap the default for an empty scratch directory instead.

build_memory_backend

build_memory_backend(
    memory_dir: str | Path, *, for_deep_agent: bool = True
) -> CompositeBackend

Build the default backend for a memory directory.

The directory is created if it does not exist. Paths under /memory/ are served from it; where anything else goes depends on for_deep_agent.

Parameters:

Name Type Description Default
memory_dir str | Path

Host directory that stores the memory tree.

required
for_deep_agent bool

Whether the backend will be driven by a deep agent. When True, non-memory paths stay in ephemeral thread state, which requires a LangGraph execution context. Set it to False for standalone use — consolidate_memory, MemoryStore, a cron job — and they are served from an empty scratch directory instead.

True

Returns:

Type Description
CompositeBackend

A composite backend with /memory/ routed to disk.

resolve_backend

resolve_backend(
    memory_dir: str | Path | None = None,
    backend: BackendProtocol | None = None,
) -> BackendProtocol

Resolve the backend an agent factory should use.

Exactly one of memory_dir and backend must be given: memory_dir for the default on-disk wiring, backend to plug in your own storage. Passing both would leave it ambiguous which one actually serves /memory/, so it is rejected rather than silently resolved.

Parameters:

Name Type Description Default
memory_dir str | Path | None

Host directory to build the default backend from.

None
backend BackendProtocol | None

A ready-made backend serving the /memory/ tree.

None

Returns:

Type Description
BackendProtocol

The backend to hand to the agent.

Raises:

Type Description
ValueError

If both arguments are given, or neither is.

Layout

deep_memory_agent.layout

Layout of the virtual memory filesystem.

Every path in this module is a virtual path inside the deepagents backend, rooted at MEMORY_ROOT. Nothing here touches the host filesystem: the mapping from /memory/ to real storage is the backend's job (see deep_memory_agent.backends).

The tree deliberately departs from a flat events.md / facts.md layout in two ways:

  • Episodic categories are sharded by month so a single file never grows past what fits in a context window.
  • Every directory owns an index.md that is a router — one line per file — and never holds memory content itself.

MEMORY_ROOT module-attribute

MEMORY_ROOT = '/memory/'

Virtual mount point of the memory tree.

ROOT_INDEX_PATH module-attribute

ROOT_INDEX_PATH = '/memory/index.md'

Top-level router pointing at the three memory kinds.

PREFERENCES_PATH module-attribute

PREFERENCES_PATH = '/memory/preferences.md'

Stable user preferences, kept at the root because they cut across kinds.

KIND_DIRECTORIES module-attribute

KIND_DIRECTORIES: dict[MemoryKind, str] = {
    MemoryKind.EPISODIC: EPISODIC_DIR,
    MemoryKind.SEMANTIC: SEMANTIC_DIR,
    MemoryKind.PROCEDURAL: PROCEDURAL_DIR,
}

Directory that holds each kind, including its index.md.

MemoryKind

Bases: StrEnum

The three memory kinds of the CoALA-style taxonomy.

EPISODIC class-attribute instance-attribute
EPISODIC = 'episodic'

What happened: events, feedback and errors, tied to a moment in time.

SEMANTIC class-attribute instance-attribute
SEMANTIC = 'semantic'

What is true: facts, rules and preferences, detached from any episode.

PROCEDURAL class-attribute instance-attribute
PROCEDURAL = 'procedural'

How things are done: repeatable operating procedures.

MemoryCategory

Bases: StrEnum

A concrete file family inside a memory kind.

EVENTS class-attribute instance-attribute
EVENTS = 'events'

Episodic: things that happened during a session.

FEEDBACKS class-attribute instance-attribute
FEEDBACKS = 'feedbacks'

Episodic: corrections and judgements received from a user.

ERRORS class-attribute instance-attribute
ERRORS = 'errors'

Episodic: mistakes made, so they are not repeated.

FACTS class-attribute instance-attribute
FACTS = 'facts'

Semantic: statements believed to be true right now.

RULES class-attribute instance-attribute
RULES = 'rules'

Semantic: constraints and policies that govern behaviour.

PREFERENCES class-attribute instance-attribute
PREFERENCES = 'preferences'

Semantic: how the user wants the agent to behave.

PROCEDURE class-attribute instance-attribute
PROCEDURE = 'procedure'

Procedural: one file per operating procedure.

index_path

index_path(kind: MemoryKind | None = None) -> str

Return the path of a router index.

Parameters:

Name Type Description Default
kind MemoryKind | None

Memory kind whose index is wanted. None returns the root index.

None

Returns:

Type Description
str

Virtual path of the index.md for that kind.

category_directory

category_directory(category: MemoryCategory) -> str

Return the directory holding a category's files.

Parameters:

Name Type Description Default
category MemoryCategory

Category to locate.

required

Returns:

Type Description
str

Virtual directory path, with a trailing slash.

shard_label

shard_label(when: datetime | None = None) -> str

Return the monthly shard label (YYYY-MM) an entry belongs to.

Parameters:

Name Type Description Default
when datetime | None

Instant to label. Defaults to now, in UTC.

None

Returns:

Type Description
str

The shard label, e.g. "2026-08".

slugify

slugify(text: str) -> str

Turn free text into a filename-safe slug.

Parameters:

Name Type Description Default
text str

Text to slugify, typically a procedure title.

required

Returns:

Type Description
str

A lowercase, hyphen-separated slug.

Raises:

Type Description
ValueError

If text contains no slug-able character.

entry_path

entry_path(
    category: MemoryCategory,
    *,
    when: datetime | None = None,
    title: str | None = None,
) -> str

Return the file an entry of this category must be written to.

Parameters:

Name Type Description Default
category MemoryCategory

Category of the entry.

required
when datetime | None

Instant the entry refers to; selects the monthly shard for episodic categories. Defaults to now, in UTC.

None
title str | None

Procedure title, required for MemoryCategory.PROCEDURE and ignored otherwise.

None

Returns:

Type Description
str

Virtual path of the target file.

Raises:

Type Description
ValueError

If a procedure is requested without a title.

Entries

deep_memory_agent.entry

Memory entries and their YAML frontmatter.

A memory file is an append-only markdown document made of entries. Each entry carries a YAML frontmatter block so that provenance (when, from where, how sure) travels with the content, and so a newer statement can explicitly supersede an older one instead of silently coexisting with it.

---
id: mem_2026-08-24_9f3a1c
created: 2026-08-24T10:15:00+00:00
type: semantic
category: facts
source: user_message
confidence: high
tags: [pricing, acme]
supersedes: mem_2026-06-01_4b2e77
summary: ACME moved to the Enterprise plan
---

ACME switched from the Team plan to Enterprise on 2026-08-24.

The format stays plain markdown on purpose: readable by a human, diffable by git, and cheap to index later with BM25 or embeddings without changing the source of truth.

Confidence

Bases: StrEnum

How much the agent trusts an entry.

MemoryEntry dataclass

A single unit of memory, with its provenance.

Attributes:

Name Type Description
entry_id str

Unique identifier, used by supersedes/superseded_by.

created datetime

Creation instant, always timezone-aware.

category MemoryCategory

Which file family the entry belongs to.

body str

Markdown content of the entry.

summary str

One-line description, used to build router indexes.

source str

Where the information came from, e.g. "user_message".

confidence Confidence

How much the entry is trusted.

tags tuple[str, ...]

Free-form labels used to narrow searches.

supersedes str | None

Identifier of the entry this one replaces, if any.

superseded_by str | None

Identifier of the entry that replaced this one, if any.

kind property
kind: MemoryKind

Memory kind this entry's category belongs to.

is_active property
is_active: bool

Whether the entry still holds, i.e. nothing has superseded it.

replaced_by
replaced_by(entry_id: str) -> MemoryEntry

Return a copy of this entry marked as superseded.

Parameters:

Name Type Description Default
entry_id str

Identifier of the entry that replaces this one.

required

Returns:

Type Description
MemoryEntry

A new entry; the original is left untouched.

new_entry_id

new_entry_id(when: datetime | None = None) -> str

Mint a unique, sortable-by-day entry identifier.

Parameters:

Name Type Description Default
when datetime | None

Instant the entry was created. Defaults to now, in UTC.

None

Returns:

Type Description
str

An identifier such as "mem_2026-08-24_9f3a1c".

render_entry

render_entry(entry: MemoryEntry) -> str

Render an entry as a frontmatter block followed by its body.

Parameters:

Name Type Description Default
entry MemoryEntry

Entry to render.

required

Returns:

Type Description
str

Markdown text ending with a trailing newline.

Raises:

Type Description
ValueError

If the body contains a line that is exactly ---, which would be indistinguishable from the start of the next entry.

parse_entries

parse_entries(text: str) -> list[MemoryEntry]

Parse every well-formed entry out of a memory file.

Parameters:

Name Type Description Default
text str

Full content of a memory file.

required

Returns:

Type Description
list[MemoryEntry]

The entries found, in file order.

split_document

split_document(text: str) -> tuple[str, list[MemoryEntry]]

Split a memory file into its heading preamble and its entries.

Blocks whose frontmatter is unreadable — hand-edited files happen — are skipped rather than raising, so a single malformed entry never blinds the agent to the rest of the file. Skipped blocks are also dropped from the round-trip, so callers that rewrite a file should expect to lose them.

Parameters:

Name Type Description Default
text str

Full content of a memory file.

required

Returns:

Type Description
str

A (preamble, entries) pair. The preamble is everything above the first

list[MemoryEntry]

entry, kept verbatim.

render_document

render_document(
    preamble: str, entries: list[MemoryEntry]
) -> str

Render a whole memory file from its preamble and entries.

Parameters:

Name Type Description Default
preamble str

Heading text to keep above the entries.

required
entries list[MemoryEntry]

Entries to render, in the order they should appear.

required

Returns:

Type Description
str

The full file content, ending with a trailing newline.

Indexes

deep_memory_agent.index

Router indexes.

Every memory directory owns an index.md whose only job is to let an agent decide what to load without loading everything: one row per file, holding a one-line description, the tags seen in it and the date it last changed — never the memory content itself.

The index is a markdown table so it stays readable and diffable:

| File | Description | Tags | Updated |
| --- | --- | --- | --- |
| events/2026-08.md | Session events for August 2026 | acme, pricing | 2026-08-24 |

IndexRow dataclass

One line of a router index.

Attributes:

Name Type Description
path str

File path, relative to the directory holding the index.

description str

One-line summary of what the file contains.

tags tuple[str, ...]

Labels seen across the file's entries.

updated str

Date of the last write, as YYYY-MM-DD.

to_row
to_row() -> str

Render the row as a markdown table line.

index_target

index_target(
    category: MemoryCategory, file_path: str
) -> tuple[str, str]

Return which index tracks a file, and under which relative path.

Parameters:

Name Type Description Default
category MemoryCategory

Category of the entry that was written.

required
file_path str

Absolute virtual path of the file that was written.

required

Returns:

Type Description
tuple[str, str]

A (index_path, relative_path) pair.

parse_index

parse_index(text: str) -> tuple[str, dict[str, IndexRow]]

Split index content into its preamble and its rows.

Parameters:

Name Type Description Default
text str

Full content of an index.md.

required

Returns:

Type Description
str

A (preamble, rows) pair, where rows is keyed by relative path.

dict[str, IndexRow]

The preamble is everything above the table, kept verbatim so a

tuple[str, dict[str, IndexRow]]

hand-written explanation survives updates.

render_index_table

render_index_table(rows: dict[str, IndexRow]) -> str

Render index rows as a markdown table, sorted by path.

Parameters:

Name Type Description Default
rows dict[str, IndexRow]

Rows keyed by relative path.

required

Returns:

Type Description
str

The table, without a trailing newline.

read_index_rows

read_index_rows(
    backend: BackendProtocol, path: str
) -> dict[str, IndexRow]

Read the rows of an index through the backend.

Parameters:

Name Type Description Default
backend BackendProtocol

Backend serving the memory tree.

required
path str

Absolute virtual path of the index.md.

required

Returns:

Type Description
dict[str, IndexRow]

Rows keyed by relative path; empty if the index does not exist yet.

update_index

update_index(
    backend: BackendProtocol,
    *,
    category: MemoryCategory,
    file_path: str,
    description: str = "",
    tags: tuple[str, ...] = (),
    when: datetime | None = None,
) -> str

Record a file in its router index, creating or merging its row.

Tags accumulate across writes so the index keeps working as a lookup table; the description of the most recent write wins, since it is the freshest statement about what the file now holds.

Parameters:

Name Type Description Default
backend BackendProtocol

Backend serving the memory tree.

required
category MemoryCategory

Category of the entry that was written.

required
file_path str

Absolute virtual path of the file that was written.

required
description str

One-line summary of the entry just written.

''
tags tuple[str, ...]

Tags of the entry just written.

()
when datetime | None

Instant of the write. Defaults to now, in UTC.

None

Returns:

Type Description
str

The absolute virtual path of the index that was updated.

Scaffolding

deep_memory_agent.scaffold

Creation of the memory tree.

Scaffolding runs through the backend like everything else, so pointing an agent at a StateBackend, a StoreBackend or a directory on disk all behave the same. It is idempotent: existing files are never overwritten, which is what makes it safe to call on every agent construction.

PROCEDURE_TEMPLATE module-attribute

PROCEDURE_TEMPLATE = "# {title}\n\n## When to use\n\n{when_to_use}\n\n## Preconditions\n\n{preconditions}\n\n## Steps\n\n{steps}\n\n## Tools required\n\n{tools}\n\n## Known failures\n\n{known_failures}\n"

Fixed section layout every procedure file follows.

Known failures is where episodic memory feeds back into procedural memory: a mistake that keeps showing up in errors/ belongs here, so the agent reads the fix at the moment it is about to repeat the mistake.

MEMORY_DIRECTORIES module-attribute

MEMORY_DIRECTORIES = (
    EPISODIC_DIR,
    SEMANTIC_DIR,
    PROCEDURAL_DIR,
)

Directories the tree is made of, for documentation and tests.

ensure_memory_tree

ensure_memory_tree(backend: BackendProtocol) -> list[str]

Create any missing file of the memory tree.

Episodic shards are deliberately not pre-created: they are named after the month they cover and appear the first time something is written to them.

Parameters:

Name Type Description Default
backend BackendProtocol

Backend serving the memory tree.

required

Returns:

Type Description
list[str]

The paths that were created, in a stable order. Empty when the tree was

list[str]

already complete.

Prompts

deep_memory_agent.prompts

System prompts for the memory agents.

The prompts describe the tree and the rules that govern it — sharding, supersession, indexes as routers — because those rules are what keep a file-based memory from degenerating into an append-only log nobody can query.