Stores and Schema
This page presents the core store abstractions and schema controls used by the Oracle Agent Memory SDK.
Store API
Store Write Semantics
Store writes keep a clear separation between the text an application stores and
the payload the store uses for retrieval. Most applications can use the
memory-level and thread-level APIs and let the store prepare the search rows it
needs for vector, keyword, or hybrid retrieval. The lower-level store APIs
expose index_texts, index_text, embeddings, and embedding for
advanced integrations that already know what text or vectors should be used for retrieval.
Think of each write as two related pieces:
contentsinadd()andtextinupdate()control the stored record text returned byget(),list(), and search results.index_textsinadd()andindex_textinupdate()control the text written to the store’s retrieval rows. Search uses those rows, then returns the original logical records.
If no search override or explicit embedding is provided, the store uses the resolved stored text as the retrieval text. Non-empty text is chunked by the store when chunking is configured. Empty text stores the record text but provides no retrieval text.
The table below describes how retrieval text is chosen before explicit vector payloads are considered.
Store-level retrieval payloads
| Input | add() | update() |
|---|---|---|
index_texts or index_text omitted |
Each record uses its resolved contents value for retrieval. |
A replacement text value is used for retrieval. If text is also omitted, embedding-only updates reuse the record’s existing retrieval text rows. |
String index_texts entry or string index_text |
The string replaces the retrieval text for that record. The store may chunk it before writing retrieval rows. | The string replaces the retrieval text for that record. The store may chunk it before writing retrieval rows. |
list[str] index_texts entry or list[str] index_text |
The list is treated as caller-owned chunks. Each non-empty string is written as one retrieval row, and the store does not chunk it again. | The list is treated as caller-owned chunks. Each non-empty string is written as one retrieval row, and the store does not chunk it again. |
None index_texts entry or index_text=None |
None in the outer index_texts list means “use the stored content for this record.” |
index_text=None clears the retrieval rows while leaving stored text unchanged unless text is also supplied. |
| Empty string or empty chunk list | Stores the record text and provides no retrieval text for that record. | Updates the record text when text is supplied and clears retrieval text for that record. |
Explicit embeddings are optional. When they are omitted, the store derives
local vectors from the retrieval text when local vector storage is configured;
keyword or hybrid stores may also use text-only retrieval rows. When explicit
embeddings or embedding values are supplied, the store writes those
vectors directly and does not call its embedder for those vectors.
In add(), embeddings=None behaves like omitting embeddings. In
update(), embedding=None is explicit: the store keeps or rewrites the
retrieval text according to text and index_text, but stores those rows
without local vectors. If text and index_text are both omitted, this
clears vectors from the existing retrieval rows.
The vector shape tells the store how much chunk ownership the caller is taking:
- one vector means one vector for the whole retrieval text. The store does not split that text for the explicit vector. If that retrieval text is empty, the vector can be stored without companion chunk text.
- multiple vectors mean one vector per caller-owned chunk. Provide matching
index_textsorindex_textchunk lists, or use an embedding-onlyupdate()that reuses the record’s existing retrieval text rows. - vector counts must match chunk counts, and all explicit vectors in one
add()call must have the same dimension. - an empty per-record vector payload is allowed only when there are no retrieval text rows to align with it.
Some combinations are rejected so stored text, retrieval text, and vectors do
not drift apart. Passing text=None clears stored text and retrieval rows, so
it cannot be combined with non-null index_text or embedding values;
actor profile records do not support text=None. Passing index_text=None
in update() means “clear retrieval rows”, so non-empty explicit embeddings
are not allowed in the same call. Multiple explicit vectors require explicit
chunk text, unless the update is embedding-only and the existing retrieval rows
already provide the chunk text.
class oracleagentmemory.core.OracleMemoryStore
Bases: IMemoryStore
Common store interface used by OracleAgentMemory.
A store implementation is responsible for persisting text records and performing similarity search over them. Both synchronous and asynchronous entry points are defined so higher-level APIs can expose matching sync/async surfaces without duplicating store-specific logic.
method add
Add records to the store.
- Parameters:
- contents
list[str | None]– Record payloads to persist. Text values are also used for semantic indexing unlessindex_textsorembeddingsare provided. When a text value isNone, implementations may fall back tometadata["content"]. Explicit empty strings are preserved. - record_type
str– Logical record type to create, for example"message","memory","guideline","fact","preference","user_profile", or"agent_profile". - index_texts
list[str | list[str] | None]– Optional alternative payloads used only for semantic indexing. When provided, the outer list must align with the text inputs. Each entry may be a string, which the store may chunk internally, or a list of non-empty strings, which the store treats as caller-owned chunks and must not split again. - embeddings
list[list[float] | ndarray | list[list[float] | ndarray]]– Optional precomputed embedding vectors aligned with the text inputs. Each record entry may be either one embedding vector or a list of chunk embedding vectors for that record. When provided, the store must use these vectors directly instead of invoking its embedder. Multiple vectors for one record require matchingindex_textschunk lists so text and vector chunk boundaries are explicit. If not provided, stores usually derive semantic state from their configured embedder, but implementation-specific text-aware indexing modes may also allow text-only writes without one. - record_ids
str | None | list[str | None]– Optional caller-visible identifiers. A single string may be used for one-record inserts, while lists must align with the text inputs. Generated identifiers are returned when this field is omitted. - thread_ids
str | None | list[str | None]– Optional thread identifiers associated with the inserted records. Scalar values may be broadcast across aligned text inputs. - user_ids
str | None | list[str | None]– Optional user identifiers associated with the inserted records. Scalar values may be broadcast across aligned text inputs. - agent_ids
str | None | list[str | None]– Optional agent identifiers associated with the inserted records. Scalar values may be broadcast across aligned text inputs. - roles
str | None | list[str | None]– Optional message roles such as"user"or"assistant". Scalar values may be broadcast across aligned text inputs. Used only if record_type is"message". - timestamps
str | None | list[str | None]– Optional timestamps to save with the records. Each timestamp represents when the record was created. Scalar values may be broadcast across aligned text inputs. Omitted orNoneentries use the current time. - metadata
dict[str, Any] | None | list[dict[str, Any] | None]– Optional caller-provided metadata dictionaries. Metadata may include"content"as fallback source when a text value is omitted rather than explicitly set to"". - ttl_days
int | None | list[int | None]– Optional time-to-live duration in days for records that support expiration. Omit this argument to use the store default. PassNonefor records that should not expire. Scalar values may be broadcast across aligned text inputs. - ttl_anchor
TimeToLiveAnchor | list[TimeToLiveAnchor]– Optional time-to-live anchor. UseTimeToLiveAnchor.CREATED_ATto expire relative to the stored creation time, orTimeToLiveAnchor.TIMESTAMPto expire relative to each record’s event timestamp. When omitted, implementations useTimeToLiveAnchor.CREATED_AT. - **store_kwargs (Any) – Implementation-specific write options forwarded to the concrete store.
- contents
- Return type: list[str]
Notes
Use add_batches() when the caller already has one or more
PendingRecordBatch objects.
- Returns: Identifiers for the inserted records, in the same logical order as the input.
- Return type: List[str]
- Parameters:
- contents
list[str | None] - record_type
str - index_texts
list[str | list[str] | None] - embeddings
list[list[float] | ndarray | list[list[float] | ndarray]] - record_ids
str | None | list[str | None] - thread_ids
str | None | list[str | None] - user_ids
str | None | list[str | None] - agent_ids
str | None | list[str | None] - roles
str | None | list[str | None] - timestamps
str | None | list[str | None] - metadata
dict[str, Any] | None | list[dict[str, Any] | None] - ttl_days
int | None | list[int | None] - ttl_anchor
TimeToLiveAnchor | list[TimeToLiveAnchor] - store_kwargs
Any
- contents
method add_agent (abstract)
Add an agent profile record.
- Parameters:
- agent_id
str– Stable identifier for the agent profile. - information
str– Free-form text describing the agent. - metadata
dict[str, Any] | None– Optional metadata mapping stored on the agent profile row.
- agent_id
- Returns: Identifier of the created agent profile record.
- Return type: str
method add_async (async)
Asynchronously add row-oriented records to the store.
Accepts the same arguments and returns the same identifiers as
add().
- Parameters:
- contents
list[str | None] - record_type
str - index_texts
list[str | list[str] | None] - embeddings
list[list[float] | ndarray | list[list[float] | ndarray]] - record_ids
str | None | list[str | None] - thread_ids
str | None | list[str | None] - user_ids
str | None | list[str | None] - agent_ids
str | None | list[str | None] - roles
str | None | list[str | None] - timestamps
str | None | list[str | None] - metadata
dict[str, Any] | None | list[dict[str, Any] | None] - ttl_days
int | None | list[int | None] - ttl_anchor
TimeToLiveAnchor | list[TimeToLiveAnchor] - store_kwargs
Any
- contents
- Return type: list[str]
method add_batches
Add caller-prepared logical batches to the store.
- Parameters:
- batches
list[PendingRecordBatch]– Fully prepared logical batches to persist. Each batch should carry its own per-record fields such asrecord_type, scope values, roles, timestamps, and metadata. - **store_kwargs (Any) – Implementation-specific write options forwarded to the concrete store.
- batches
- Returns: Identifiers for the inserted records, in the same logical order as the input batches and rows.
- Return type: List[str]
Examples
store.add_batches(
[
PendingRecordBatch(
texts=["pizza batch"],
record_type="memory",
record_ids="mem-batch-docs",
)
]
)
['mem-batch-docs']
method add_batches_async (async)
Asynchronously add caller-prepared logical batches to the store.
Accepts the same arguments and returns the same identifiers as
add_batches().
- Parameters:
- batches
list[PendingRecordBatch] - store_kwargs
Any
- batches
- Return type: list[str]
method add_user (abstract)
Add a user profile record.
- Parameters:
- user_id
str– Stable identifier for the user profile. - information
str– Free-form text describing the user. - metadata
dict[str, Any] | None– Optional metadata mapping stored on the user profile row.
- user_id
- Returns: Identifier of the created user profile record.
- Return type: str
method delete (abstract)
Delete one stored record by identifier.
- Parameters:
- record_type
str– Logical type of the record to remove. - record_id
str– Identifier of the record to remove. - cascade
bool– WhenTrue, apply any store-supported cascading delete behavior for the requested top-level targets inside the same delete operation. This is primarily used for targets such as actor profiles that own additional scoped records. For example, a user-profile or agent-profile cascade may delete owned threads themselves, the thread-scoped messages and memory-like records removed with those threads, and any remaining directly actor-scoped records such as messages, memories, guidelines, facts, or preferences. For actor-profile deletes, this scoped cleanup may still run when the matching profile row is already absent.
- record_type
- Returns:
Number of requested top-level records deleted, typically
0or1. Cascaded child rows are not counted separately, so this may still be0when a missing actor profile triggers scoped cleanup. - Return type: int
method delete_thread (abstract)
Delete a thread and its associated stored data.
- Parameters:
thread_id
str– Identifier of the thread to remove. - Returns:
Number of deleted thread records, typically
0or1. - Return type: int
Notes
This is the store-level operation for removing a thread and the thread-scoped records managed by the store. Prefer thread deletion when retention requirements call for deleting both source messages and derived thread-scoped memory data, because message-level deletes do not imply that separately persisted derived records are removed.
method get (abstract)
Retrieve one stored record by type and identifier.
- Parameters:
- record_type
str– Logical type of the record to retrieve. - record_id
str– Identifier of the record to retrieve.
- record_type
- Returns:
The stored record when found, otherwise
None. - Return type: Record | None
method list (abstract)
List stored records for one record type.
- Parameters:
- record_type
str– Logical record type to enumerate. - limit
int | None– Optional maximum number of most-recent records to return. When omitted, implementations may apply a safe upper bound such asMAX_LIST_LIMIT. PassNoneto disable that cap and return every matching record. - thread_id
str | None– Exact thread-scope filter. When omitted, no filtering is applied. When set toNone, only records whosethread_idisNoneare returned. Unscoped record types ignore this filter. - user_id
str | None– Exact user-scope filter. When omitted, no filtering is applied. When set toNone, only records whoseuser_idisNoneare returned. Unscoped record types ignore this filter. - agent_id
str | None– Exact agent-scope filter. When omitted, no filtering is applied. When set toNone, only records whoseagent_idisNoneare returned. Unscoped record types ignore this filter. -
metadata_filter
dict[str, Any] | None–Metadata filter. When omitted, no filtering is applied. When set to
None, only records whose metadata isNoneare returned. When set to a dict, entries inmetadata_filterare combined with AND semantics. Entries whose value is not a field-level operator dictionary use exact-match semantics: the requested key must exist in the stored metadata. Nested dictionaries are matched recursively. Scalar and list values are matched by exact equality; list order and length must also match. To test array membership, use a field-level operator dictionary such as{"tags": {"$array_contains": "prod"}}. A list operand for"$array_contains"means all listed values must be present;"$array_contains_any"means at least one listed value must be present. Use"$not"to negate another field-level expression at the same field, including an operator dictionary or raw exact-match value. Negated expressions match when the positive expression would fail, including missing fields; negated array membership also matches non-array fields. Examples includemetadata_filter={"source": "slack"}for a scalar field,metadata_filter={"review": {"status": "open"}}for a nested field, andmetadata_filter={"tags": ["prod", "urgent"]}for an exact list match. Combine conditions to require all of them:metadata_filter={ "source": "slack", "review": {"status": "open"}, "tags": ["prod", "urgent"], }
- record_type
- Returns: Records ordered from oldest to newest within the returned window.
- Return type: List[Record]
method list_thread_messages (abstract)
List the message history stored for one thread.
- Parameters:
- thread_id
str– Identifier of the thread whose messages should be returned. - last_n
int | None– Optional number of most-recent messages to include. When omitted, all stored messages for the thread are returned.
- thread_id
- Returns: Message records ordered from oldest to newest within the returned window.
- Return type: List[MessageRecord]
method search (abstract)
Search records by similarity.
- Parameters:
- query
str | None– Natural language query. Must be provided whenquery_vectoris omitted. - query_vector
list[float] | None– Optional precomputed query embedding. Exactly one ofqueryandquery_vectormust be provided. - k
int– Maximum number of results to return. Explicit values must be at least1. This is an upper bound: the call may return fewer thankresults when filters are too restrictive, when fewer non-expired matching records exist, or because of implementation-specific search behavior. - thread_id
str | None– Optional thread scope. - user_id
str | None– Optional user and agent scope filters. - agent_id
str | None– Optional user and agent scope filters. - exact_user_match
bool– Whether each provided scope identifier must be matched exactly. - exact_agent_match
bool– Whether each provided scope identifier must be matched exactly. - exact_thread_match
bool– Whether each provided scope identifier must be matched exactly. - record_types
set[str] | None– Optional set of record types to include. - metadata_filter
dict[str, Any] | None– Optional metadata filter mapping. Entries inmetadata_filterare combined with AND semantics. Entries whose value is not a field-level operator dictionary use exact-match semantics: the requested key must exist in the stored metadata. Nested dictionaries are matched recursively. Scalar and list values are matched by exact equality; list order and length must also match. To test array membership, use a field-level operator dictionary such as{"tags": {"$array_contains": "prod"}}. A list operand for"$array_contains"means all listed values must be present;"$array_contains_any"means at least one listed value must be present. Use"$not"to negate another field-level expression at the same field, including an operator dictionary or raw exact-match value. Negated expressions match when the positive expression would fail, including missing fields; negated array membership also matches non-array fields.
- query
- Returns:
(record, distance)pairs sorted by increasing distance. The list may contain fewer thankentries. - Return type: list[tuple[Record, float]]
- Raises:
ValueError – If
kis less than1.
Examples
store.add(
["Searchable abstract memory"],
record_type="memory",
record_ids="mem-search-abstract-docs",
)
['mem-search-abstract-docs']
store.search("Searchable", 1, record_types={"memory"})[0][0].id
'mem-search-abstract-docs'
Filter on a scalar metadata value:
store.add(
["pizza release"],
record_type="memory",
record_ids="mem-search-meta-source-docs",
metadata={"source": "slack"},
)
['mem-search-meta-source-docs']
any(
record.id == "mem-search-meta-source-docs"
for record, _ in store.search(
"pizza",
k=3,
metadata_filter={"source": "slack"},
)
)
True
Filter on nested metadata:
store.add(
["pizza review"],
record_type="memory",
record_ids="mem-search-meta-review-docs",
metadata={"review": {"status": "open"}},
)
['mem-search-meta-review-docs']
any(
record.id == "mem-search-meta-review-docs"
for record, _ in store.search(
"pizza",
k=3,
metadata_filter={"review": {"status": "open"}},
)
)
True
Match a list value exactly, including order:
store.add(
["pizza tags"],
record_type="memory",
record_ids="mem-search-meta-tags-docs",
metadata={"tags": ["prod", "urgent"]},
)
['mem-search-meta-tags-docs']
any(
record.id == "mem-search-meta-tags-docs"
for record, _ in store.search(
"pizza",
k=3,
metadata_filter={"tags": ["prod", "urgent"]},
)
)
True
Filter when a metadata array contains a value:
any(
record.id == "mem-search-meta-tags-docs"
for record, _ in store.search(
"pizza",
k=3,
metadata_filter={"tags": {"$array_contains": "prod"}},
)
)
True
Combine multiple metadata conditions. A record must satisfy every key:
store.add(
["pizza rollout"],
record_type="memory",
record_ids="mem-search-meta-combined-docs",
metadata={
"source": "slack",
"review": {"status": "open"},
"tags": ["prod", "urgent"],
},
)
['mem-search-meta-combined-docs']
any(
record.id == "mem-search-meta-combined-docs"
for record, _ in store.search(
"pizza",
k=5,
metadata_filter={
"source": "slack",
"review": {"status": "open"},
"tags": ["prod", "urgent"],
},
)
)
True
method search_async (async)
Asynchronously search records by semantic similarity.
- Parameters:
- query
str | None– Same query text accepted bysearch. - k
int– Same maximum result count accepted bysearch. Explicit values must be at least1. - query_vector
list[float] | None– Same optional precomputed query embedding accepted bysearch. - thread_id
str | None– Same optional scope filters accepted bysearch. - user_id
str | None– Same optional scope filters accepted bysearch. - agent_id
str | None– Same optional scope filters accepted bysearch. - exact_user_match
bool– Same exact-match flags accepted bysearch. - exact_agent_match
bool– Same exact-match flags accepted bysearch. - exact_thread_match
bool– Same exact-match flags accepted bysearch. - record_types
set[str] | None– Same optional record-type filter accepted bysearch. - metadata_filter
dict[str, Any] | None– Same optional metadata filter accepted bysearch, including scalar, nested, exact-list, array-membership, and combined conditions such as{"source": "slack"},{"review": {"status": "open"}},{"tags": ["prod", "urgent"]}, and{"tags": {"$array_contains": "prod"}}.
- query
- Returns:
(record, distance)pairs returned by the underlyingsearchcall. - Return type: List[tuple[Record, float]]
- Raises:
ValueError – If
kis less than1.
method update (abstract)
Update stored record content, embedding data, metadata, timestamp, or expiration.
- Parameters:
- record_type
str– Logical type of the record to update. - record_id
str– Identifier of the record to update. - text
str | None– Optional replacement content. PassNoneto explicitly clear the stored text when the store supports it. Stores may also clear the associated semantic state and reject conflicting non-nullindex_textorembeddingupdates in the same call. Omit the argument to leave content unchanged. - index_text
str | list[str] | None– Optional alternative semantic payload used to recompute or replace the stored search state without changing the persisted text. A string may be chunked internally by the store. A list of non-empty strings is treated as caller-owned chunks and must not be split again. Some implementations may also persist this separately as hybrid-search text. - embedding
list[float] | ndarray | list[list[float] | ndarray] | None– Optional precomputed embedding vector or list of chunk embedding vectors. When provided, this is used directly and no embedder call is made. Multiple vectors require matchingindex_textchunk lists or existing stored chunk text rows. PassNoneto explicitly clear the stored embedding when the store supports it. Stores with text-aware indexing may also allow semantic updates without an embedder or explicit embedding. - metadata
dict[str, Any] | None– Optional replacement metadata mapping. PassNoneto clear metadata when the store supports it. - timestamp
str | None– Optional new timestamp to save with the record. It represents when the record was created. Omit this argument to leave the stored timestamp unchanged. PassNoneto clear the saved timestamp and use the time the record was added to the store when the store supports it. - ttl_days
int | None– Optional expiration refresh in days. Omit this argument together withttl_anchorto preserve the current expiration timestamp. PassNoneto clear expiration. - ttl_anchor
TimeToLiveAnchor– Optional time-to-live anchor for an expiration refresh. UseTimeToLiveAnchor.CREATED_ATfor the record creation time orTimeToLiveAnchor.TIMESTAMPfor the replacementtimestampsupplied in the same update, or the stored event timestamp whentimestampis omitted. Providingttl_anchorwithoutttl_daysuses the store or schema default time-to-live duration. Whenttl_anchoris omitted during a refresh, implementations useTimeToLiveAnchor.CREATED_AT.
- record_type
- Returns:
Number of updated records, typically
0or1. Returns0when no stored record matches the requested logical identifier. - Return type: int
- Raises: ValueError – If the update payload is invalid for the store, such as omitting every optional field or providing conflicting semantic arguments.
Oracle DB Store
class oracleagentmemory.core.OracleDBMemoryStore
Bases: OracleMemoryStore
Database-backed persistence for messages, memories, and actor profiles.
Create an Oracle DB store.
- Parameters:
- embedder
IEmbedder | None– Embedder used when the store needs local vector embeddings. May beNonewhen callers always provide precomputed vectors, or when keyword search is used with text-only writes and text queries.SearchStrategy.HYBRIDrequires anOracleDBEmbedderhere so the managed hybrid index can use this embedder’s in-database model. - pool
Any– Oracle DB connection or pool. Passing a raw connection enables single-session mode for this store instance: concurrent store calls are serialized locally to preserve the row-lock and transaction assumptions used by write operations. Use a connection pool for concurrent requests. - schema_policy
SchemaPolicy | str– Schema setup mode. Defaults to requiring an existing, up-to-date managed schema and performing no DDL changes. UseSchemaPolicy.CREATE_IF_NECESSARYto fill missing objects, orSchemaPolicy.RECREATEto drop and recreate managed objects.SchemaPolicy.CREATE_IF_NECESSARYcan apply supported managed schema-version upgrades, can upgrade a vector schema for keyword search by adding a text index, or for hybrid search by adding the managed search structures and hybrid index. - vector_dim
int | None– Optional embedding dimension for local vector storage. Pass a positive integer to create the managed embedding column and vector index, and to validate existing schema metadata against that dimension. PassNoneor omit the argument when this store does not need local vector storage. Keyword and hybrid search can operate from stored search text without the local embedding column. Vector search requires local vector storage. -
table_name_prefix
str–Optional prefix added to managed table/index names. Pass either this or
memory_store_id, not both.Note: Deprecated since version 26.6.0: This parameter was deprecated in 26.6.0 and will be removed in 27.1. Please use
memory_store_idinstead. - memory_store_id
str– Stable ID for the managed DB memory store. Reuse the same ID to reopen the same managed store. The ID is joined to managed DB object names with an underscore, so it must start with a letter, contain only letters, numbers, and underscores, and be at most 16 characters. Pass either this ortable_name_prefix, not both. If omitted, the store usestable_name_prefixor the unprefixed default whentable_name_prefixis also omitted. - search_strategy
SearchStrategy–SearchStrategyvalue that selects the backend forsearch(). UseSearchStrategy.VECTOR(default) for vector-only retrieval,SearchStrategy.HYBRIDto query a managed Oracle hybrid vector index over the stored search text, orSearchStrategy.KEYWORDto rank by keyword/text matching over the stored search text without vector fusion.KEYWORDdoes not require an embedder.HYBRIDrequiresembedderto be anOracleDBEmbedderso the managed hybrid index uses the same in-database model as the main store embedder. If a keyword client opens an existing hybrid schema, the store can use the text branch of that hybrid index. Startup fails when an incompatible strategy is used with an existing schema because that schema may not contain the stored search state the strategy needs. - search_index_sync
SearchIndexSyncMode–SearchIndexSyncModevalue that selects the managed search-index refresh behavior forSearchStrategy.HYBRIDandSearchStrategy.KEYWORD.SearchIndexSyncMode.ON_COMMITis the default and makes records searchable as soon as the write transaction commits.SearchIndexSyncMode.MANUALleaves refresh to an explicit database-side sync operation.SearchIndexSyncMode.AUTOlets Oracle refresh the managed hybrid index asynchronously and is supported only withSearchStrategy.HYBRID; keyword search rejectsAUTO. - memory_retention_config
MemoryRetentionConfig– Optional memory retention configuration for DB-backed messages and memories.MemoryRetentionConfig.default_ttl_daysis used when a new write omitsttl_days.MemoryRetentionConfig.max_ttl_daysclamps explicit per-record durations above the configured maximum with a warning and, when set, makesttl_days=Noneuse that maximum instead of creating non-expiring rows. WithSchemaPolicy.CREATE_IF_NECESSARY, an explicit configuration refreshes the stored metadata on an existing up-to-date managed schema, but it does not update the existing expiration dates; omitting it keeps the existing setting. If an explicit configuration leavesdefault_ttl_daysormax_ttl_daysatNOT_SET_MARKER, the SDK resolves that attribute to its default value (None) before comparing or storing schema metadata. Choose this configuration based on the expected information stored in records, why the application retains it, and any application or regulatory retention commitments.
- embedder
Warning: SchemaPolicy.CREATE_IF_NECESSARY can be more expensive than normal
store startup because it may apply managed schema DDL and best-effort
data rewrites before initialization succeeds. Plan the first open of
an older managed schema as a migration or maintenance operation when
that schema may contain many rows.
If schema setup must create the managed expired-record purge job but
the database user lacks the scheduler-job privilege, initialization
warns and continues. Expired messages and memories stay hidden from
reads and search, but they are not physically purged until the job is
created by a user with CREATE JOB or an equivalent scheduler
privilege.
When SchemaPolicy.CREATE_IF_NECESSARY first creates a managed
hybrid index over an existing schema, Oracle scans the stored search
text and builds the managed hybrid-index state from the configured
in-database model. Store initialization waits for that DDL to finish,
so plan the first hybrid upgrade as a migration or maintenance
operation for large schemas. SearchIndexSyncMode controls ongoing
maintenance after the index exists; it does not make the first index
build asynchronous.
Creating that managed hybrid index also creates a
DBMS_VECTOR_CHAIN vectorizer preference named by the managed
schema. The preference stores lightweight vectorizer configuration
metadata from the configured OracleDBEmbedder model. It can be
inspected with Oracle Text preference views such as
CTX_USER_PREFERENCES and CTX_USER_PREFERENCE_VALUES.
method add
Add records to the Oracle DB store.
- Parameters:
- contents
list[str | None]– Record payloads to persist. Text values are also used for search text unlessindex_textsare provided. When a text value isNone, the store may fall back tometadata["content"]. Explicit empty strings are preserved. - record_type
str– Logical record type to create, such as"message","memory","guideline","fact","preference","user_profile", or"agent_profile". - index_texts
list[str | list[str] | None]– Optional alternative payloads used as search text. Use this to control what DB-backed keyword or hybrid search indexes. Each outer list entry aligns with one record. A string entry may be chunked by the store. A list entry is treated as caller-owned chunks and written as-is toRECORD_CHUNKS.chunk_text. Whenembeddingsare also provided, list entries require exactly one vector per chunk; string entries accept only a single vector for that record. -
embeddings
list[list[float] | ndarray | list[list[float] | ndarray]]–Optional precomputed embedding vectors aligned with
contents. Each record entry may be either one vector or a list of chunk vectors. When local vector storage is configured, these vectors are stored directly as the record’s vector representation instead of calling the store’s embedder to create local vectors for the write. A single vector represents the whole semantic text, even when the configured chunker would otherwise split it. Multiple chunk vectors require matchingindex_textschunk lists.In
SearchStrategy.VECTOR, vector search ranks against those stored vectors. InSearchStrategy.HYBRIDorSearchStrategy.KEYWORD, DB-backed search ranks through the stored search text and Oracle-managed text or hybrid index state, so add-time embeddings affect only any configured local vector storage, not that active search strategy. If this store was configured without local vector storage, provideindex_textsinstead ofembeddingsto override the text visible to those text-aware indexes. - record_ids
str | None | list[str | None]– Optional caller-visible identifiers. A single string may be used for one-record inserts, while lists must align withcontents. Generated identifiers are returned when this field is omitted. - thread_ids
str | None | list[str | None]– Optional thread identifiers associated with the inserted records. Scalar values may be broadcast across aligned inputs. - user_ids
str | None | list[str | None]– Optional user identifiers associated with the inserted records. Scalar values may be broadcast across aligned inputs. - agent_ids
str | None | list[str | None]– Optional agent identifiers associated with the inserted records. Scalar values may be broadcast across aligned inputs. - roles
str | None | list[str | None]– Optional message roles such as"user"or"assistant". Used only whenrecord_typeis"message". - timestamps
str | None | list[str | None]– Optional timestamps to save with the records. Each timestamp represents when the record was created. Scalar values may be broadcast across aligned inputs. Omitted orNoneentries leave the event timestamp unset. Whenttl_anchorisTimeToLiveAnchor.TIMESTAMP, every affected record must have a concrete ISO-8601 timestamp value. ISO-8601 timestamps without a timezone are treated as UTC. - metadata
dict[str, Any] | None | list[dict[str, Any] | None]– Optional metadata dictionaries. Metadata may include"content"as a fallback source when a text value is omitted rather than set to"". - ttl_days
int | None | list[int | None]– Optional time-to-live duration in days for message and memory-like records. Omit this argument to useMemoryRetentionConfig.default_ttl_daysfrom the managed schema. PassNoneto useMemoryRetentionConfig.max_ttl_dayswhen the retention configuration sets one, or to create a non-expiring record when it does not. Values aboveMemoryRetentionConfig.max_ttl_daysare clamped to that maximum with a warning. Scalar values may be broadcast across aligned inputs. - ttl_anchor
TimeToLiveAnchor | list[TimeToLiveAnchor]– Optional time-to-live anchor. UseTimeToLiveAnchor.CREATED_ATto expire relative to the database creation time, orTimeToLiveAnchor.TIMESTAMPto expire relative to the provided event timestamp. When omitted, expiration usesTimeToLiveAnchor.CREATED_AT. Timestamp-anchored expiration requires a concrete ISO-8601 timestamp for each inserted record. ISO-8601 timestamps without a timezone are treated as UTC. - **store_kwargs (Any) – DB write options.
batch_sizecontrols the executemany batch size and defaults to256.
- contents
- Returns: Identifiers for inserted records, in the same logical order as the input.
- Return type: list[str]
Examples
store.add(
["Index this stored text"],
record_type="memory",
record_ids="mem-db-add-docs",
)
['mem-db-add-docs']
store.add(
["Stored text"],
record_type="memory",
index_texts=["Search this text"],
record_ids="mem-db-index-text-docs",
)
['mem-db-index-text-docs']
store.add(
["Short-lived event"],
record_type="memory",
record_ids="mem-db-ttl-docs",
timestamps="2026-01-01T12:00:00+00:00",
ttl_days=7,
ttl_anchor=TimeToLiveAnchor.TIMESTAMP,
)
['mem-db-ttl-docs']
method add_agent
Add an agent profile record.
- Parameters:
- agent_id
str– Agent identifier. - information
str– Free-form information about the agent. This text is stored as the profile content and used to build the profile’s searchable representation. - metadata
dict[str, Any] | None– Optional metadata mapping stored on the agent profile row.
- agent_id
- Returns: Identifier of the inserted agent profile record.
- Return type: str
Notes
Agent profile records are unscoped. The inserted public record
identifier is the same value passed as agent_id.
Examples
store.add_agent("a-docs-agent", "Support assistant")
'a-docs-agent'
method add_async (async)
Asynchronously add row-oriented records to the store.
Accepts the same arguments and returns the same identifiers as
add().
- Parameters:
- contents
list[str | None] - record_type
str - index_texts
list[str | list[str] | None] - embeddings
list[list[float] | ndarray | list[list[float] | ndarray]] - record_ids
str | None | list[str | None] - thread_ids
str | None | list[str | None] - user_ids
str | None | list[str | None] - agent_ids
str | None | list[str | None] - roles
str | None | list[str | None] - timestamps
str | None | list[str | None] - metadata
dict[str, Any] | None | list[dict[str, Any] | None] - ttl_days
int | None | list[int | None] - ttl_anchor
TimeToLiveAnchor | list[TimeToLiveAnchor] - store_kwargs
Any
- contents
- Return type: list[str]
method add_batches
Add caller-prepared logical batches to the store.
- Parameters:
- batches
list[PendingRecordBatch]– Fully prepared logical batches to persist. Each batch should carry its own per-record fields such asrecord_type, scope values, roles, timestamps, and metadata. - **store_kwargs (Any) – Implementation-specific write options forwarded to the concrete store.
- batches
- Returns: Identifiers for the inserted records, in the same logical order as the input batches and rows.
- Return type: List[str]
Examples
store.add_batches(
[
PendingRecordBatch(
texts=["pizza batch"],
record_type="memory",
record_ids="mem-batch-docs",
)
]
)
['mem-batch-docs']
method add_batches_async (async)
Asynchronously add caller-prepared logical batches to the store.
Accepts the same arguments and returns the same identifiers as
add_batches().
- Parameters:
- batches
list[PendingRecordBatch] - store_kwargs
Any
- batches
- Return type: list[str]
method add_user
Add a user profile record.
- Parameters:
- user_id
str– User identifier. - information
str– Free-form information about the user. This text is stored as the profile content and used to build the profile’s searchable representation. - metadata
dict[str, Any] | None– Optional metadata mapping stored on the user profile row.
- user_id
- Returns: Identifier of the inserted user profile record.
- Return type: str
Notes
User profile records are unscoped. The inserted public record
identifier is the same value passed as user_id.
Examples
store.add_user("u-docs-profile", "Prefers concise answers.")
'u-docs-profile'
method delete
Delete one managed row and its chunk rows by identifier.
- Parameters:
- record_type
str– Record type label to delete. Supported types include"thread","message","memory","guideline","fact","preference","user_profile", and"agent_profile". - record_id
str– Identifier to delete. - cascade
bool– WhenTrue, expand supported top-level targets such as actor profiles to their scoped child rows inside the same transaction. For a user-profile or agent-profile target, this deletes the owned thread rows first, which removes their thread-scoped message and memory-table rows, then deletes any remaining directly actor-scoped messages and memory-like rows (memory,guideline,fact,preference). This scoped cleanup still runs when the matching profile row is already absent.
- record_type
- Returns:
Number of requested top-level targets removed, typically
0or1. Cascaded child rows are not counted separately, so this may still be0when a missing actor profile triggers scoped cleanup. - Return type: int
Notes
The operation runs inside one transaction. When cascade is enabled
for a supported top-level target, the profile delete and all scoped
child deletes are committed or rolled back together.
Examples
store.add(["Delete me"], record_type="memory", record_ids="mem-delete-docs")
['mem-delete-docs']
store.delete("memory", "mem-delete-docs")
1
method delete_thread
Delete a thread and its associated stored rows.
- Parameters:
thread_id
str– Thread identifier whose rows should be removed, including the thread row, dependent child rows, and explicit chunk-row cleanup. - Returns:
Number of deleted thread rows (
0or1). - Return type: int
Notes
Use this operation when you need thread-scoped cascading cleanup. In the DB-backed store, deleting the thread removes the managed thread row together with associated message and memory rows, plus the search data maintained for retrieval. This is broader than a message-level delete, which removes only the raw message row. Thread deletion removes dependent message and memory rows together with their associated retrieval data in the same transaction.
Examples
store.delete_thread("c1")
0
method get
Retrieve a stored record by identifier.
- Parameters:
- record_type
str– Record type label resolving to a managed row, such as"message","memory","guideline","fact","preference","user_profile", or"agent_profile". - record_id
str– Identifier to look up.
- record_type
- Returns:
Populated record with decoded metadata when found, otherwise
None. - Return type: Record | None
Examples
store.add(["Remember this"], record_type="memory", record_ids="mem-get-docs")
['mem-get-docs']
store.get("memory", "mem-get-docs").id
'mem-get-docs'
method list
Enumerate persisted records for a record type.
- Parameters:
- record_type
str– Record type label (e.g."message","memory","guideline","fact","preference","user_profile", or"agent_profile"). - limit
int | None– Optional maximum number of records to return. When omitted, the store uses its default listing cap. PassNoneto disable that cap and return every matching record. - thread_id
str | None– Exact thread-scope filter. When omitted, no filtering is applied. When set toNone, only rows whosethread_idis SQLNULLare returned. Unscoped record types ignore this filter. - user_id
str | None– Exact user-scope filter. When omitted, no filtering is applied. When set toNone, only rows whoseuser_idis SQLNULLare returned. Unscoped record types ignore this filter. - agent_id
str | None– Exact agent-scope filter. When omitted, no filtering is applied. When set toNone, only rows whoseagent_idis SQLNULLare returned. Unscoped record types ignore this filter. -
metadata_filter
dict[str, Any] | None–Metadata filter. When omitted, no filtering is applied. When set to
None, only records with no stored metadata are returned. When set to a dict, entries inmetadata_filterare combined with AND semantics. Entries whose value is not a field-level operator dictionary use exact-match semantics: the requested key must exist in the stored metadata. Nested dictionaries are matched recursively. Scalar and list values are matched by exact equality; list order and length must also match. To test array membership, use a field-level operator dictionary such as{"tags": {"$array_contains": "prod"}}. A list operand for"$array_contains"means all listed values must be present;"$array_contains_any"means at least one listed value must be present. Use"$not"to negate another field-level expression at the same field, including an operator dictionary or raw exact-match value. Negated expressions match when the positive expression would fail, including missing fields; negated array membership also matches non-array fields. Examples includemetadata_filter={"source": "slack"}for a scalar field,metadata_filter={"review": {"status": "open"}}for a nested field, andmetadata_filter={"tags": ["prod", "urgent"]}for an exact list match. Combine conditions to require all of them:metadata_filter={ "source": "slack", "review": {"status": "open"}, "tags": ["prod", "urgent"], }
- record_type
- Returns: Records ordered by insertion order.
- Return type: list[Record]
Notes
"user_profile" and "agent_profile" are unscoped record types.
For those record types, thread_id, user_id, and agent_id
are ignored and actor identity remains in record.id.
Examples
store.add(
["First listed", "Second listed"],
record_type="memory",
record_ids=["mem-list-docs-1", "mem-list-docs-2"],
)
['mem-list-docs-1', 'mem-list-docs-2']
[record.id for record in store.list("memory", limit=2)]
['mem-list-docs-1', 'mem-list-docs-2']
store.add_user("u-list-docs", "Prefers concise answers.")
'u-list-docs'
any(
record.id == "u-list-docs"
for record in store.list("user_profile", user_id=None, limit=10)
)
True
method list_thread_messages
Return persisted messages for a thread.
- Parameters:
- thread_id
str– Thread identifier whose messages should be returned. - last_n
int | None– Optional number of most-recent messages to return.
- thread_id
- Returns: Message records ordered by insertion order.
- Return type: list[MessageRecord]
Examples
store.list_thread_messages("c1")
[]
method search
Search records by similarity.
The active search backend depends on the store’s configured
SearchStrategy. SearchStrategy.VECTOR ranks the query vector
against stored record vectors. SearchStrategy.HYBRID queries
Oracle’s managed hybrid index over the stored search text and its
managed index state. SearchStrategy.KEYWORD ranks only by text
matching over the stored search text.
- Parameters:
- query
str | None– Optional natural-language text used to find matching or similar records. Provide at least one non-whitespace character whenquery_vectoris omitted. Vector search embeds this text; keyword search matches it against stored search text; hybrid search uses it for both text and vector retrieval. - query_vector
list[float] | None– Optional precomputed query embedding. Exactly one ofqueryandquery_vectormust be provided. In vector search, this is compared with stored record vectors. In hybrid search, it is sent to Oracle’s managed hybrid index as the query-side vector input and does not cause the DB store to compare against add-time or update-time stored vectors directly. Keyword search does not acceptquery_vector. The vector must be non-empty, one- dimensional, and contain only finite numeric values. In hybrid search, its dimension must match the configuredOracleDBEmbeddermodel. - k
int– Maximum number of results to return. Explicit values must be at least1. This is an upper bound: the call may return fewer thankresults when filters are too restrictive, when fewer non-expired matching records exist, or because of implementation-specific search behavior. - thread_id
str | None– Optional thread-scope identifier.exact_thread_match=Falseleaves the thread dimension unconstrained.exact_thread_match=Truematches the providedthread_idexactly. Ifthread_id=None, it matches only records unscoped on the thread dimension. - user_id
str | None– Optional user and agent scope identifiers. The correspondingexact_*_match=Falseflag leaves that dimension unconstrained.exact_*_match=Truematches the provided ID exactly. If the ID isNone, it matches only records unscoped on that dimension. - agent_id
str | None– Optional user and agent scope identifiers. The correspondingexact_*_match=Falseflag leaves that dimension unconstrained.exact_*_match=Truematches the provided ID exactly. If the ID isNone, it matches only records unscoped on that dimension. - exact_user_match
bool– Whether each scope identifier must be matched exactly.Falseleaves that dimension unconstrained.Truematches the provided value exactly. If that value isNone, it matches only unscoped records on that dimension. - exact_agent_match
bool– Whether each scope identifier must be matched exactly.Falseleaves that dimension unconstrained.Truematches the provided value exactly. If that value isNone, it matches only unscoped records on that dimension. - exact_thread_match
bool– Whether each scope identifier must be matched exactly.Falseleaves that dimension unconstrained.Truematches the provided value exactly. If that value isNone, it matches only unscoped records on that dimension. - record_types
set[str] | None– Optional set of searchable record types to include. When omitted, the DB search covers messages, memory-table rows, and actor profiles. Actor profiles contribute theirinformationpayload, while message and memory rows contribute theircontentpayload. During search, profile record types use their actor identifier for the applicable scope dimension while the remaining scope dimensions behave asNone. - metadata_filter
dict[str, Any] | None– Optional metadata filter mapping. Entries inmetadata_filterare combined with AND semantics. Entries whose value is not a field-level operator dictionary use exact-match semantics: the requested key must exist in the stored metadata. Nested dictionaries are matched recursively. Scalar and list values are matched by exact equality; list order and length must also match. To test array membership, use a field-level operator dictionary such as{"tags": {"$array_contains": "prod"}}. A list operand for"$array_contains"means all listed values must be present;"$array_contains_any"means at least one listed value must be present. Use"$not"to negate another field-level expression at the same field, including an operator dictionary or raw exact-match value. Negated expressions match when the positive expression would fail, including missing fields; negated array membership also matches non-array fields.
- query
- Returns:
(record, distance)pairs sorted by increasing distance. The list may contain fewer thankentries. - Return type: list[tuple[Record, float]]
- Raises:
ValueError – If
kis less than1, if both or neither ofqueryandquery_vectorare provided, ifqueryis blank, if vector mode cannot resolve a query embedding, ifquery_vectoris invalid, or ifmetadata_filteris invalid.
Examples
store.add(
["pizza preference"],
record_type="memory",
record_ids="mem-search-docs",
thread_ids="c-search-docs",
)
['mem-search-docs']
results = store.search(
"pizza",
1,
thread_id="c-search-docs",
exact_thread_match=True,
record_types={"memory"},
)
results[0][0].id
'mem-search-docs'
Filter on a scalar metadata value:
store.add(
["pizza release"],
record_type="memory",
record_ids="mem-search-meta-source-docs",
metadata={"source": "slack"},
)
['mem-search-meta-source-docs']
any(
record.id == "mem-search-meta-source-docs"
for record, _ in store.search(
"pizza",
k=3,
metadata_filter={"source": "slack"},
)
)
True
Filter on nested metadata:
store.add(
["pizza review"],
record_type="memory",
record_ids="mem-search-meta-review-docs",
metadata={"review": {"status": "open"}},
)
['mem-search-meta-review-docs']
any(
record.id == "mem-search-meta-review-docs"
for record, _ in store.search(
"pizza",
k=3,
metadata_filter={"review": {"status": "open"}},
)
)
True
Match a list value exactly, including order:
store.add(
["pizza tags"],
record_type="memory",
record_ids="mem-search-meta-tags-docs",
metadata={"tags": ["prod", "urgent"]},
)
['mem-search-meta-tags-docs']
any(
record.id == "mem-search-meta-tags-docs"
for record, _ in store.search(
"pizza",
k=3,
metadata_filter={"tags": ["prod", "urgent"]},
)
)
True
Filter when a metadata array contains a value:
any(
record.id == "mem-search-meta-tags-docs"
for record, _ in store.search(
"pizza",
k=3,
metadata_filter={"tags": {"$array_contains": "prod"}},
)
)
True
Combine multiple metadata conditions. A record must satisfy every key:
store.add(
["pizza rollout"],
record_type="memory",
record_ids="mem-search-meta-combined-docs",
metadata={
"source": "slack",
"review": {"status": "open"},
"tags": ["prod", "urgent"],
},
)
['mem-search-meta-combined-docs']
any(
record.id == "mem-search-meta-combined-docs"
for record, _ in store.search(
"pizza",
k=5,
metadata_filter={
"source": "slack",
"review": {"status": "open"},
"tags": ["prod", "urgent"],
},
)
)
True
method search_async (async)
Asynchronously search records by semantic similarity.
- Parameters:
- query
str | None– Same query text accepted bysearch. - k
int– Same maximum result count accepted bysearch. Explicit values must be at least1. - query_vector
list[float] | None– Same optional precomputed query embedding accepted bysearch. - thread_id
str | None– Same optional scope filters accepted bysearch. - user_id
str | None– Same optional scope filters accepted bysearch. - agent_id
str | None– Same optional scope filters accepted bysearch. - exact_user_match
bool– Same exact-match flags accepted bysearch. - exact_agent_match
bool– Same exact-match flags accepted bysearch. - exact_thread_match
bool– Same exact-match flags accepted bysearch. - record_types
set[str] | None– Same optional record-type filter accepted bysearch. - metadata_filter
dict[str, Any] | None– Same optional metadata filter accepted bysearch, including scalar, nested, exact-list, array-membership, and combined conditions such as{"source": "slack"},{"review": {"status": "open"}},{"tags": ["prod", "urgent"]}, and{"tags": {"$array_contains": "prod"}}.
- query
- Returns:
(record, distance)pairs returned by the underlyingsearchcall. - Return type: List[tuple[Record, float]]
- Raises:
ValueError – If
kis less than1.
method update
Update stored record content, search state, metadata, and timestamp values.
- Parameters:
- record_type
str– Record type label of the row being modified (for example"message","memory","guideline","fact","preference","user_profile", or"agent_profile") - record_id
str– Identifier of the stored row to update. - text
str | None– Optional replacement text persisted in thecontentcolumn. PassNoneto clear the stored text and clear the stored embedding. Pass onlyNoneor omitted semantic arguments in the same call. Pass""to preserve explicit empty content while clearing any stored vector representation for that record. When omitted, the existing content is left unchanged. - index_text
str | list[str] | None– Optional semantic-only payload. When omitted,textis used for semantic indexing. On hybrid-capable schemas this also becomes the stored search text used by Oracle’s text component. A string value may be chunked by the store; a list value is treated as caller-owned chunks and written as-is toRECORD_CHUNKS. When onlyembeddingis provided, the existing search text is reused. -
embedding
list[float] | ndarray | list[list[float] | ndarray] | None–Optional precomputed embedding vector or list of chunk embedding vectors. When local vector storage is configured, this is used directly and no embedder call is made. Pass
Noneto clear the stored embedding. A single vector represents the whole replacement text whentextis provided, even when the configured chunker would split that text. Multiple chunk vectors are rejected when replacing text unlessindex_textis a chunk list. When onlyembeddingis provided, the embedding count must match the record’s existing chunk rows.In
SearchStrategy.VECTOR, vector search ranks against the stored embedding. InSearchStrategy.HYBRIDorSearchStrategy.KEYWORD, DB-backed search ranks through the stored search text and Oracle-managed text or hybrid index state, so update-time embeddings affect only any configured local vector storage, not that active search strategy. If this store was configured without local vector storage, provideindex_textinstead ofembeddingto update the text visible to those text-aware indexes. Text-only semantic updates may omitembeddingentirely in those modes. - metadata
dict[str, Any] | None– Optional metadata mapping serialized to JSON and stored inmetadata. - timestamp
str | None– Optional new timestamp to save with the record. It represents when the record was created. When omitted, the existing timestamp is preserved. PassNoneto clear the saved timestamp and use the database creation time for futureTimeToLiveAnchor.CREATED_ATexpiration refreshes. Whenttl_anchorisTimeToLiveAnchor.TIMESTAMP, ISO-8601 timestamps without a timezone are treated as UTC. - ttl_days
int | None– Optional expiration refresh in days. Omit this argument together withttl_anchorto preserve the current expiration timestamp. PassNoneto useMemoryRetentionConfig.max_ttl_dayswhen the retention configuration sets one, or to clear expiration when it does not. Values aboveMemoryRetentionConfig.max_ttl_daysare clamped to that maximum with a warning. Refreshing expiration can make an expired record visible again if it has not been purged yet. - ttl_anchor
TimeToLiveAnchor– Optional time-to-live anchor for an expiration refresh. UseTimeToLiveAnchor.CREATED_ATto count from the stored creation time, orTimeToLiveAnchor.TIMESTAMPto count from the replacementtimestampsupplied in the same update, or the stored event timestamp whentimestampis omitted. Providingttl_anchorwithoutttl_daysrefreshes expiration using the schema’sMemoryRetentionConfig.default_ttl_days. Whenttl_anchoris omitted during a refresh, the store usesTimeToLiveAnchor.CREATED_AT. Timestamp-anchored refreshes require either a replacement ISO-8601 timestamp in the same call or an existing stored event timestamp in that format. ISO-8601 timestamps without a timezone are treated as UTC.
- record_type
- Returns:
Number of updated rows (
0or1). Returns0when no logical record matchesrecord_typeandrecord_id. - Return type: int
- Raises:
ValueError – If
record_typeis unsupported, if no update payload is provided, or if the semantic update arguments are incompatible.
Examples
store.add(["Original note"], record_type="memory", record_ids="mem-update-docs")
['mem-update-docs']
store.update("memory", "mem-update-docs", text="Updated note")
1
store.get("memory", "mem-update-docs").content
'Updated note'
Search Strategy
class oracleagentmemory.core.dbsearch.SearchStrategy
Bases: Enum
Search behavior for Oracle DB stores.
DB store initialization uses the selected strategy to choose the managed
schema search capability. VECTOR search stores local embeddings.
KEYWORD search stores searchable text and a text index. HYBRID
search stores searchable text plus Oracle-managed hybrid vector-index
state. The DB store validates this schema capability at startup so an
incompatible strategy does not silently return incomplete results.
VECTOR- Search by vector similarity only. The store embeds the query with the
configured embedder, or uses a caller-provided
query_vector, and ranks records by distance from the stored vectors. Use this with a DB schema configured for vector search. HYBRID- Search with Oracle’s managed hybrid index. Oracle combines text
matching over stored search text with vector ranking from the
in-database hybrid index. Use this when users may search by natural
language as well as exact identifiers, aliases, or product names. This
strategy requires the store’s main embedder to be an
OracleDBEmbedderso the managed index and store share one in-database model. KEYWORD- Search only by keyword/text matching over stored search text. This mode does not create local query embeddings and does not need an Oracle DB embedder. When opened against an existing hybrid schema, it can use the text branch of that hybrid index without creating a new hybrid index. Use this when exact identifiers, aliases, product names, or short phrases should drive retrieval without vector fusion.
HYBRID = ‘hybrid’
KEYWORD = ‘keyword’
VECTOR = ‘vector’
Search Index Sync Mode
class oracleagentmemory.core.dbsearch.SearchIndexSyncMode
Bases: Enum
Refresh behavior for managed DB search indexes.
This setting controls when Oracle makes new or changed search text visible
to DB-backed text-aware search. SearchStrategy.HYBRID uses Oracle’s
managed hybrid vector index. SearchStrategy.KEYWORD uses an Oracle
Text index. SearchStrategy.VECTOR does not use this setting.
ON_COMMIT- Refresh the index when the write transaction commits. This is the default and the simplest choice for most applications because records are searchable immediately after a successful write. It can add work to write transactions because the index is kept up to date right away.
MANUAL- Do not refresh the index automatically. New or updated records may not appear in keyword or hybrid search until you run the database-side index sync operation yourself. This is useful for bulk loads or maintenance windows where you want to control when refresh work runs.
AUTO- Let Oracle refresh the managed hybrid index asynchronously. Writes can
avoid the immediate refresh cost, but search results may lag behind
recent writes until Oracle completes the background refresh. This mode
is supported only with
SearchStrategy.HYBRID.
Warning: This setting controls ongoing maintenance after the managed search index exists. It does not make the first index build asynchronous. Creating a managed hybrid index over existing stored search text can be long-running because Oracle builds the managed hybrid-index state from that text.
AUTO = ‘auto’
MANUAL = ‘manual’
ON_COMMIT = ‘on_commit’
Time-to-Live
class oracleagentmemory.core.retention.MemoryRetentionConfig
Bases: object
Schema-level retention settings for Oracle DB-backed records.
- Parameters:
- default_ttl_days
int | None– Default time-to-live duration, in days. Leave asNOT_SET_MARKERto use the default ofNone(no maximum). - max_ttl_days
int | None– Optional maximum time-to-live duration, in days. Leave asNOT_SET_MARKERto use the default ofNone. PassNonefor no maximum. When set, this is a hard cap: writes that try to use a largerttl_daysvalue are clamped to this maximum with a warning, and write APIs that passttl_days=Noneuse this maximum instead of creating non-expiring records.
- default_ttl_days
class oracleagentmemory.apis.ttl.TimeToLiveAnchor
Bases: Enum
Anchor used to compute an expiration timestamp from a time-to-live duration.
CREATED_AT- Compute expiration from the record’s database creation timestamp.
This is the default when callers omit
ttl_anchor. TIMESTAMP- Compute expiration from the record’s stored event timestamp. Use this when a message or memory represents an older event and should expire relative to that event time instead of insert time.
CREATED_AT = ‘created_at’
TIMESTAMP = ‘timestamp’
Schema Policy
class oracleagentmemory.core.SchemaPolicy
Bases: str, Enum
Schema creation policy for Oracle DB stores.
REQUIRE_EXISTING
Validate that the full managed schema already exists and is up-to-date. Do not create or modify DB objects.
CREATE_IF_EMPTY
If no managed objects exist, bootstrap schema. If objects already exist, require a complete and up-to-date managed schema.
CREATE_IF_NECESSARY
Create missing managed objects and apply supported managed schema upgrades.
RECREATE
Drop and recreate all managed schema objects. This is destructive.