Skip to main content

Python client library for Oracle AI Database Agent Memory

Project description

Oracle AI Agent Memory

Oracle AI Agent Memory docs License

Persistent memory for enterprise AI agents on Oracle AI Database.

Oracle AI Agent Memory helps agents retain context across interactions, compact active conversations, and retrieve durable user, agent, and thread memories when they matter. It is designed for Python applications that need persistent memory backed by Oracle AI Database.

Get Started

Install the package:

pip install oracleagentmemory

Do you need a local Oracle AI Database for development? See how to run Oracle AI Database locally: https://docs.oracle.com/en/database/oracle/agent-memory/26.4/agmea/run-locally.html

Create a memory client, store a short conversation, and search it back:

from oracleagentmemory.apis.searchscope import SearchScope
from oracleagentmemory.core import OracleAgentMemory
from oracleagentmemory.core.embedders.embedder import Embedder
from oracleagentmemory.core.llms.llm import Llm

embedder = Embedder(model="YOUR_EMBEDDING_MODEL")
llm = Llm(model="YOUR_LLM")
db_pool = ...  # an oracledb connection or connection pool

memory = OracleAgentMemory(connection=db_pool, embedder=embedder, llm=llm)

messages = [
    {
        "role": "user",
        "content": "Orange juice has become my favorite breakfast drink lately. What can I pair it with?",
    },
    {
        "role": "assistant",
        "content": "Try eggs and toast, avocado toast, or a breakfast sandwich.",
    },
]

thread = memory.create_thread(user_id="user_123")
# add_messages will add messages to the DB and extract memories automatically
thread.add_messages(messages)
# add_memory adds memory to the DB
thread.add_memory("The user likes orange juice with breakfast.")

results = memory.search(query="orange juice", scope=SearchScope(user_id="user_123"))
for result in results:
    print(f"- [{result.record.record_type}] {result.content}")

OracleAgentMemory uses your Oracle Database connection or pool as the persistence layer, an embedder for vector retrieval when needed, and an optional LLM for memory extraction, summaries, and context cards. When you know your embedding model's output dimension, you can pass embedding_dimension to Embedder so DB schema setup does not need to infer it with a provider call.

If you want Oracle-managed hybrid search over stored search text instead of vector-only retrieval, opt in when constructing the client:

from oracleagentmemory.core import (
    SearchIndexSyncMode,
    OracleAgentMemory,
    SchemaPolicy,
    SearchStrategy,
)
from oracleagentmemory.core.embedders import OracleDBEmbedder

db_embedder = OracleDBEmbedder(
    connection=db_pool,
    model="YOUR_DB_EMBEDDING_MODEL",
    embedding_dimension=384,
)

hybrid_memory = OracleAgentMemory(
    connection=db_pool,
    embedder=db_embedder,
    llm=llm,
    schema_policy=SchemaPolicy.CREATE_IF_NECESSARY,
    search_strategy=SearchStrategy.HYBRID,
    search_index_sync=SearchIndexSyncMode.ON_COMMIT,
)

SchemaPolicy.CREATE_IF_NECESSARY lets the SDK add the managed search objects needed by the selected strategy. SearchStrategy.HYBRID creates or validates Oracle's managed hybrid vector index and requires the main embedder to be an OracleDBEmbedder; the index uses that embedder's in-database model. search_index_sync controls refresh timing for keyword and hybrid indexes. SearchIndexSyncMode.AUTO is supported only for hybrid search; keyword search supports ON_COMMIT and MANUAL.

Warning: The first creation of a hybrid index over existing data can be long-running because Oracle scans stored search text and builds the managed index state during schema setup. Run that upgrade as a planned migration for large schemas.

SearchStrategy.KEYWORD uses text search over stored search text and does not need an embedder. Keyword schemas created without local vector storage cannot be reopened with SearchStrategy.VECTOR unless you recreate the schema or backfill local embeddings first. They can still be upgraded to hybrid search with an OracleDBEmbedder, because Oracle's managed hybrid index builds from stored search text.

LongMemEval Results

Benchmark Score Correct
LongMemEval 94.4 472 / 500
Knowledge Update 94.0 73 / 78
Multi-session Reasoning 88.0 117 / 133
Temporal Reasoning 98.0 130 / 133
Single-session User 97.0 68 / 70
Single-session Assistant 100.0 56 / 56
Preference 93.0 28 / 30

Configuration note:

LongMemEval full 500-question evaluation. Answering with GPT-5.5 using xhigh reasoning effort. Mean answer LLM total tokens: 29,042; mean thinking tokens: 1,178.

BEAM Results

Score Correct
100K 1M 10M 100K 1M 10M
abstention 71% 65% 62% 28.50 / 40 45.50 / 70 12.50 / 20
contradiction_resolution 76% 69% 54% 30.25 / 40 48.00 / 70 10.88 / 20
event_ordering 22% 25% 24% 8.93 / 40 17.42 / 70 4.77 / 20
information_extraction 88% 83% 62% 35.17 / 40 58.19 / 70 12.50 / 20
instruction_following 81% 79% 70% 32.50 / 40 55.00 / 70 14.00 / 20
knowledge_update 60% 66% 70% 24.00 / 40 46.50 / 70 14.00 / 20
multi_session_reasoning 67% 63% 14% 26.81 / 40 43.93 / 70 2.90 / 20
preference_following 88% 82% 56% 35.33 / 40 57.46 / 70 11.25 / 20
summarization 59% 66% 50% 23.59 / 40 46.42 / 70 10.02 / 20
temporal_reasoning 72% 59% 39% 29.00 / 40 41.08 / 70 7.75 / 20
Total 68.5% 65.6% 50.3% 274.08 / 400 459.50 / 700 100.56 / 200
Metric 100K 1M 10M
Mean Input Tokens 64,936 86,417 93,161
Mean Output Tokens 2,117 2,424 2,216
Mean Thinking Tokens 1,850 2,056 1,979

Answering with GPT-5.5 using xhigh reasoning effort.

Why Oracle AI Agent Memory?

Oracle AI Agent Memory is built for teams that want persistent agent memory on Oracle AI Database. It helps applications move beyond single-turn prompts by storing conversation history, durable memories, and prompt-ready short-term context in Oracle AI Database.

It gives agents a consistent way to:

  • remember useful information across sessions;
  • keep active threads compact and context-rich;
  • retrieve memories by user, agent, and thread scope;
  • use LLM-backed extraction when automatic memory formation is useful;
  • write explicit memories when deterministic application control is preferred;
  • integrate memory into existing Python agent applications.

Core Concepts

Threads

A thread represents an ongoing conversation or task. Threads can store user and assistant messages, return recent messages, and produce short-term context for an agent prompt.

thread = memory.create_thread(user_id="user_123")
thread.add_messages([
    {"role": "user", "content": "Remember that I like morning meetings."},
    {"role": "assistant", "content": "I will keep that in mind."},
])

Durable Memories

A durable memory is information intended to survive beyond the active thread. Applications can add durable memories directly.

thread.add_memory("The user prefers morning meetings.")

When an LLM is configured and memory extraction is enabled, Oracle AI Agent Memory can also extract durable memories from thread messages.

Search Scope

Search is scoped explicitly so applications can control which memories are eligible for retrieval.

thread.add_memory(
    "The user prefers morning meetings.",
    metadata={"source": "support"},
)
results = memory.search(
    query="When does the user prefer meetings?",
    scope=SearchScope(user_id="user_123"),
)

Use record_types and metadata_filter when retrieval should only consider specific kinds of records or records whose stored metadata contains a requested partial mapping. Multiple filter keys are combined with AND semantics, nested dictionaries match nested metadata fields, and list values must match exactly:

results = memory.search(
    query="When does the user prefer meetings?",
    scope=SearchScope(user_id="user_123"),
    record_types=["memory"],
    metadata_filter={"source": "support"},
)

For array membership, put a field-level operator dictionary where an exact value would normally appear. $array_contains with a scalar checks one array value, $array_contains with a list requires all listed values, and $array_contains_any requires at least one listed value. $not negates another field-level operator dictionary; a standalone negated membership filter also matches records where that field is missing or is not an array:

results = memory.search(
    query="When does the user prefer meetings?",
    scope=SearchScope(user_id="user_123"),
    record_types=["memory"],
    metadata_filter={
        "source": "support",
        "tags": {"$array_contains": "support"},
    },
)

Context Cards

For longer conversations, get_context_card() creates prompt-ready short-term context with a summary, relevant durable records, retrieval topics, and recent messages.

context = thread.get_context_card()

Use context cards when a model needs continuity without receiving the full conversation transcript.

Security and Deployment Notes

Oracle AI Agent Memory uses the database connection, model providers, credentials, and network configuration supplied by the integrating application. For production deployments:

  • use encrypted database connections and secure model-provider endpoints;
  • keep secrets out of source code and checked-in configuration;
  • apply end-user authentication and authorization before memory operations;
  • pass correct memory scope values for every request;
  • bound message sizes, retrieval sizes, and provider usage for your workload;
  • review LLM-backed extraction and summarization carefully before using them with sensitive data.

Troubleshooting

If pip install oracleagentmemory or pip install oracleagentmemory==26.4.0 reports No matching distribution found, first check the Python interpreter used by pip:

python --version
python -m pip --version
python -m pip install oracleagentmemory

Oracle AI Agent Memory supports Python 3.10 through 3.13. Python 3.9 can produce a generic resolver error instead of a clear "requires Python >=3.10" message. Create a Python 3.10, 3.11, 3.12, or 3.13 environment and install again.

Oracle AI Agent Memory requires vector memory to be configured in Oracle Database before using vector search or vector-index backed schemas. If the database raises ORA-51962: The vector memory area is out of space for the current container, ask a DBA or privileged administrator to size vector memory for both the root container and the target pluggable database. The exact values depend on your database and workload; this example configures 512M at the root and 256M for the PDB:

ALTER SESSION SET CONTAINER = CDB$ROOT;
ALTER SYSTEM SET vector_memory_size = 512M SCOPE=SPFILE SID='*';
SHUTDOWN IMMEDIATE;
STARTUP;
ALTER PLUGGABLE DATABASE <PDB_NAME> OPEN;
ALTER SESSION SET CONTAINER = <PDB_NAME>;
ALTER SYSTEM SET vector_memory_size = 256M SCOPE=BOTH;
SELECT value FROM v$parameter WHERE name = 'vector_memory_size';

See the Oracle Database error help for ORA-51962.

If you need a read-only runtime database user, create or upgrade the managed schema with an owner account, grant only SELECT on the managed tables, and start the runtime client with SchemaPolicy.REQUIRE_EXISTING. The runtime user also needs the normal database privilege required to connect, such as CREATE SESSION, which usually comes from a DBA or privileged administrator. The example below uses APP_MEMORY_ as table_name_prefix; if you omit that argument, use the unprefixed managed object names in your grants. Then pass schema_owner so runtime clients use the managed objects in the owner schema:

-- Run as a DBA or privileged administrator.
GRANT CREATE SESSION TO memory_r;

-- Run as memory_owner.
GRANT SELECT ON memory_owner.APP_MEMORY_ORACLEAGENTMEMORY_SCHEMA_META TO memory_r;
GRANT SELECT ON memory_owner.APP_MEMORY_THREAD TO memory_r;
GRANT SELECT ON memory_owner.APP_MEMORY_ACTOR_PROFILE TO memory_r;
GRANT SELECT ON memory_owner.APP_MEMORY_MESSAGE TO memory_r;
GRANT SELECT ON memory_owner.APP_MEMORY_MEMORY TO memory_r;
GRANT SELECT ON memory_owner.APP_MEMORY_RECORD_CHUNKS TO memory_r;

The example below assumes embedder is already configured for your application.

import os

import oracledb

from oracleagentmemory.core import OracleAgentMemory, SchemaPolicy

RUNTIME_DB_USER = os.environ.get("ORACLE_MEMORY_RUNTIME_DB_USER", "memory_r")
TABLE_NAME_PREFIX = "APP_MEMORY_"

runtime_pool = oracledb.SessionPool(
    user=RUNTIME_DB_USER,
    password=os.environ["ORACLE_MEMORY_RUNTIME_DB_PASSWORD"],
    dsn=os.environ.get("ORACLE_MEMORY_DB_CONNECT_STRING", "localhost:1521/FREEPDB1"),
    min=1,
    max=4,
    increment=1,
    homogeneous=True,
)

memory = OracleAgentMemory(
    connection=runtime_pool,
    embedder=embedder,
    extract_memories=False,
    schema_policy=SchemaPolicy.REQUIRE_EXISTING,
    schema_owner="memory_owner",
    table_name_prefix=TABLE_NAME_PREFIX,
)

If your installed Oracle AI Agent Memory version cannot qualify managed objects through schema_owner, create private table synonyms in the runtime user's schema. This is a compatibility guideline only; for versions that support schema_owner, keep using the constructor argument shown above.

A table synonym is an Oracle Database alias for a table. It lets the runtime user refer to a local-looking table name such as APP_MEMORY_MEMORY while Oracle resolves that name to the owner schema table, such as memory_owner.APP_MEMORY_MEMORY.

Create synonyms only after the owner schema exists and after the owner has granted the runtime user access to the managed objects. A synonym does not copy the table or grant permissions by itself. Each synonym uses the same local table name that Oracle AI Agent Memory expects from table_name_prefix and points to the table in the owner schema. The example below creates private table synonyms for the read-only runtime user memory_r:

-- Run as a DBA or privileged administrator after granting table privileges.
CREATE SYNONYM memory_r.APP_MEMORY_ORACLEAGENTMEMORY_SCHEMA_META
  FOR memory_owner.APP_MEMORY_ORACLEAGENTMEMORY_SCHEMA_META;
CREATE SYNONYM memory_r.APP_MEMORY_THREAD
  FOR memory_owner.APP_MEMORY_THREAD;
CREATE SYNONYM memory_r.APP_MEMORY_ACTOR_PROFILE
  FOR memory_owner.APP_MEMORY_ACTOR_PROFILE;
CREATE SYNONYM memory_r.APP_MEMORY_MESSAGE
  FOR memory_owner.APP_MEMORY_MESSAGE;
CREATE SYNONYM memory_r.APP_MEMORY_MEMORY
  FOR memory_owner.APP_MEMORY_MEMORY;
CREATE SYNONYM memory_r.APP_MEMORY_RECORD_CHUNKS
  FOR memory_owner.APP_MEMORY_RECORD_CHUNKS;

Repeat the same pattern for each runtime schema, such as memory_rw, that must use the managed objects before schema_owner support is available. When using synonyms, omit schema_owner from the OracleAgentMemory(...) constructor so the database resolves the unqualified table names through the runtime user's private synonyms.

If another agent framework reports dependency conflicts around LiteLLM, OpenAI, or python-dotenv, upgrade to the latest Oracle AI Agent Memory release available to you. Oracle AI Agent Memory 26.5.0 uses litellm>=1.84.0,<2. Avoid installing other packages that pin incompatible LiteLLM ranges in the same environment. For example, if CrewAI's LiteLLM extra selects an incompatible LiteLLM version, install crewai instead of crewai[litellm]; otherwise, isolate the two dependency sets in separate environments.

License

Oracle AI Agent Memory is dual-licensed under:

  • Apache License 2.0
  • Universal Permissive License (UPL) 1.0

You may choose either license.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

oracleagentmemory-26.6.0-cp313-none-any.whl (495.1 kB view details)

Uploaded CPython 3.13

oracleagentmemory-26.6.0-cp312-none-any.whl (493.7 kB view details)

Uploaded CPython 3.12

oracleagentmemory-26.6.0-cp311-none-any.whl (514.8 kB view details)

Uploaded CPython 3.11

oracleagentmemory-26.6.0-cp310-none-any.whl (362.0 kB view details)

Uploaded CPython 3.10

File details

Details for the file oracleagentmemory-26.6.0-cp313-none-any.whl.

File metadata

File hashes

Hashes for oracleagentmemory-26.6.0-cp313-none-any.whl
Algorithm Hash digest
SHA256 083f2eacf0d6094af7f9a2a720a538cb6e541c27ec43719a8942413504db8792
MD5 84a7f227ed8e1fa1e04ee335ae1fb8c9
BLAKE2b-256 14891651f3e3d6151d540f88e064377c369327c1c8e2c1d12e3a653974612838

See more details on using hashes here.

File details

Details for the file oracleagentmemory-26.6.0-cp312-none-any.whl.

File metadata

File hashes

Hashes for oracleagentmemory-26.6.0-cp312-none-any.whl
Algorithm Hash digest
SHA256 a6e4af4423ab1abf3b982ffee1d5c2e732f5097254eac0f161fba21e28da8cc1
MD5 72ee1980cde2f93423fd17463fc69a3c
BLAKE2b-256 3d6cbba8e452d79ddf8f1ab4991cb788201a260fcb51992036a585d72f51ff4f

See more details on using hashes here.

File details

Details for the file oracleagentmemory-26.6.0-cp311-none-any.whl.

File metadata

File hashes

Hashes for oracleagentmemory-26.6.0-cp311-none-any.whl
Algorithm Hash digest
SHA256 bccab0574f16adbab9e73a3fc5c4545caab7822b9c76fdc453829f5fa29ab038
MD5 a2a2d63f09f0bd01fb26a6b4ed16b13f
BLAKE2b-256 7a9ec7f9cfdd9205512563d68465c07b5bc7b9117bf7cbc36d3718af19d7cbfc

See more details on using hashes here.

File details

Details for the file oracleagentmemory-26.6.0-cp310-none-any.whl.

File metadata

File hashes

Hashes for oracleagentmemory-26.6.0-cp310-none-any.whl
Algorithm Hash digest
SHA256 e04443cad0efce33b04d656671366645d8a3cc385a1c3f3085c4f1f9ce60286e
MD5 97678678f9d51f2e0fbf8fe86d34b4b7
BLAKE2b-256 8f39918c1d1e41baff3629603cf0e7bf3d3bce5ef74ebf497d1b75093ce2ca87

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page