Metadata-Version: 2.4
Name: oracleagentmemory
Version: 26.6.0
Summary: Python client library for Oracle AI Database Agent Memory
Author: Oracle
License-Expression: Apache-2.0 OR UPL-1.0
License-File: LICENSE-APACHE.txt
License-File: LICENSE-UPL.txt
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Requires-Python: <3.14,>=3.10
Requires-Dist: aiohttp<4,>=3.14.1
Requires-Dist: anyio<5,>=4.0
Requires-Dist: cryptography<50,>=46.0.7
Requires-Dist: exceptiongroup<2,>=1.3
Requires-Dist: litellm<2,>=1.84.0
Requires-Dist: numpy<3,>=1.23
Requires-Dist: oracledb<5,>=3.4.2
Requires-Dist: pydantic<3,>=2.12.5
Requires-Dist: typing-extensions<5,>=4.0
Requires-Dist: urllib3<2.8.0,>=2.7.0
Description-Content-Type: text/markdown

# Oracle AI Agent Memory

[![Oracle AI Agent Memory docs][badge-docs]][docs] [![License][badge-license]](#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:

```bash
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:

```python
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:

```python
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.

```python
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.

```python
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.

```python
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:

```python
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:

```python
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.

```python
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:

```bash
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:

```sql
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](https://docs.oracle.com/error-help/db/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:

```sql
-- 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.

```python
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`:

```sql
-- 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.

[badge-docs]: https://img.shields.io/badge/documentation-Oracle%20AI%20Agent%20Memory-orange
[badge-license]: https://img.shields.io/badge/license-apache_2.0+UPL_1.0-green
[docs]: https://docs.oracle.com/en/database/oracle/agent-memory/index.html
