クイック参照コード・サンプル

この記事では、一般的なエージェント・メモリー設定およびAPIライフサイクル操作について、焦点を絞った小さな例を収集します。

LLM/埋込み設定

次の例では、LLMと埋込みモデルの両方にLiteLLMを使用します。

LLMの構成

from oracleagentmemory.core.llms.llm import Llm

llm = Llm(
    model="YOUR_LLM_MODEL",
    api_base="YOUR_LLM_API_BASE",
    api_key="YOUR_LLM_API_KEY",
)

response = llm.generate("What is 2+2?")
print(response.text)

出力:

2+2 is equal to 4

埋込みモデルの構成

from oracleagentmemory.core.embedders.embedder import Embedder

embedder = Embedder(
    model="YOUR_EMBEDDING_MODEL",
    api_base="YOUR_EMBEDDING_API_BASE",
    api_key="YOUR_EMBEDDING_API_KEY",
)

embedding_matrix = embedder.embed(["The quick brown fox jumps over the lazy dog"])
print(embedding_matrix.shape)

出力:

(1, embedding_dimension)

API設定

エージェント・メモリー・コンポーネントの構成

これにより、Oracle DB接続またはプールが埋込みモデルおよびオプションのLLMとともに使用され、自動メモリー抽出が行われます。

import oracledb

from oracleagentmemory.core.oracleagentmemory import OracleAgentMemory

db_pool = oracledb.SessionPool(
    user="YOUR DB USER",
    password="YOUR DB PASSWORD",
    dsn="YOUR DB CONNECT STRING",
)
memory = OracleAgentMemory(
    connection=db_pool,
    embedder=embedder,
    llm=llm,  # optional: enables automatic memory extraction during add_messages()
)

Oracle DBメモリー・コンポーネントの構成

このバリアントは、Oracle DB接続またはプールを使用し、スキーマ・ポリシーおよび表名の接頭辞を設定する方法を示します。

import oracledb

from oracleagentmemory.core import SchemaPolicy
from oracleagentmemory.core.oracleagentmemory import OracleAgentMemory

db_pool = oracledb.SessionPool(
    user="YOUR DB USER",
    password="YOUR DB PASSWORD",
    dsn="YOUR DB CONNECT STRING",
)
db_memory = OracleAgentMemory(
    connection=db_pool,
    embedder=embedder,
    llm=llm,  # optional
    schema_policy=SchemaPolicy.CREATE_IF_NECESSARY,
    memory_store_id="DEV_",
)

Oracle Hybrid DBメモリー・コンポーネントの構成

このバリアントは、格納された検索テキストに対するOracle管理のハイブリッド検索を有効にし、管理対象の検索索引同期モードを選択する方法を示します。

SearchStrategy.HYBRIDは、Oracleのマネージド・ハイブリッド・ベクトル索引を作成または検証し、マネージド索引が埋込み者のデータベース内モデルを使用するように、メイン・エンベダーをOracleDBEmbedderにする必要があります。SearchStrategy.KEYWORDはテキストのみで、格納された検索テキストでランク付けされ、埋込みは必要ありません。キーワード・スキーマは、ローカル・ベクトル・ストレージなしで作成できるため、最初にスキーマを再作成するか埋め込みをバックフィルしないかぎり、SearchStrategy.VECTORを使用してキーワード・スキーマを再オープンしないでください。Oracleのマネージド・ハイブリッド索引はストアド・サーチ・テキストから構築されるため、OracleDBEmbedderを使用してハイブリッド検索にアップグレードすることもできます。

警告:ハイブリッド索引が既存のデータに対して最初に作成されると、Oracleは格納された検索テキストをスキャンし、スキーマ設定時に管理対象索引の状態を構築します。SchemaPolicy.CREATE_IF_NECESSARYには時間がかかる場合があり、大規模なスキーマのデータベース移行のように計画する必要があります。

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

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

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

APIのライフサイクル

スレッドの作成

オプションのスレッドID、ユーザーID、およびエージェントIDを持つスレッドを作成します。

thread = memory.create_thread(
    thread_id="thread_create_123",  # optional
    user_id="user_123",             # optional
    agent_id="agent_456",           # optional
)

print(thread.thread_id)

出力:

thread_create_123

既存のスレッドの再オープン

thread = memory.create_thread(
    thread_id="thread_reopen_123",
    user_id="user_123",
    agent_id="agent_456",
)

same_thread = memory.get_thread("thread_reopen_123")
print(same_thread.thread_id)

出力:

thread_reopen_123

既存のスレッドの更新

update_thread()を使用して、スレッド・メタデータまたは永続ランタイム構成の変更を永続化します。get_thread()に渡されたオーバーライドは、明示的に永続化されるまで、再オープンされたハンドルにのみ影響します。

thread = memory.create_thread(
    thread_id="thread_update_123",
    user_id="user_123",
    agent_id="agent_456",
)

loaded_thread = memory.get_thread(
    "thread_update_123",
    max_message_token_length=8_000,
)
print(loaded_thread.max_message_token_length)

updated_thread = memory.update_thread(
    "thread_update_123",
    metadata={"source": "support", "flags": {"vip": True}},
    max_message_token_length=8_000,
)
persisted_thread = memory.get_thread("thread_update_123")

print(updated_thread.metadata["flags"]["vip"])
print(persisted_thread.max_message_token_length)

出力:

8000
True
8000

get_thread()に渡されるオーバーライドは一時的なものです。update_thread()をコールして、スレッド・メタデータまたは永続ランタイム構成の変更を永続化します。

スレッドの削除

この操作は、スレッド・スコープのカスケード・クリーン・アップが必要な場合に使用します。これによって、SDKによって管理される関連メッセージ、永続メモリーおよびバッキング取得データとともにスレッドが削除されます。

thread = memory.create_thread(thread_id="thread_delete_123")

deleted = memory.delete_thread("thread_delete_123")
print(deleted)

出力:

1

スレッド・スコープのカスケード・クリーンアップが必要な場合は、スレッド削除を使用します。SDKによって管理されるメッセージ、メモリーおよびバッキング取得データとともにスレッドが削除されます。

ユーザー・プロファイルの追加

user_profile_id = memory.add_user(
    "user_123",
    "The user prefers concise answers and works mostly with Python.",
)

print(user_profile_id)

出力:

user_123

エージェント・プロファイルの追加

agent_profile_id = memory.add_agent(
    "agent_456",
    "A coding assistant specialized in debugging and code review.",
)

print(agent_profile_id)

出力:

agent_456

メモリーAPIからのグローバル・メモリーの追加

thread_idを省略すると、メモリーは特定のスレッドに関連付けられません。戻り値はメモリー識別子です。

memory_id = memory.add_memory(
    "The user prefers short, bullet-point answers.",
    memory_type="preference",
    user_id="user_123",
    agent_id="agent_456",
)

print(memory_id)

出力:

mem:1

メモリーAPIからのスコープ付きメモリーの追加

戻り値はメモリー識別子です。

thread = memory.create_thread(
    thread_id="thread_scoped_123",
    user_id="user_123",
    agent_id="agent_456",
)

memory_id = memory.add_memory(
    "The user is planning a trip to Kyoto next month.",
    memory_type="fact",
    user_id="user_123",
    agent_id="agent_456",
    thread_id=thread.thread_id,
)

print(memory_id)

出力:

mem:2

メモリーAPIからのメモリーの更新

update_memory()を使用して、既存のメモリーに似たレコードの格納済コンテンツまたはメタデータを識別子で置き換えます。

thread = memory.create_thread(
    thread_id="thread_update_memory_api_123",
    user_id="user_123",
    agent_id="agent_456",
)
memory_id = memory.add_memory(
    "The user likes short status updates.",
    user_id=thread.user_id,
    agent_id=thread.agent_id,
    thread_id=thread.thread_id,
    metadata={"source": "chat"},
)

updated_memory_id = memory.update_memory(
    memory_id,
    content="The user prefers short status updates.",
    metadata={"source": "support"},
)

print(updated_memory_id)

出力:

mem:3

カスタムIDを使用したメモリーの追加

戻り値は、コール元提供のメモリー識別子です。

memory_id = memory.add_memory(
    "The user prefers aisle seats on flights.",
    user_id="user_123",
    agent_id="agent_456",
    memory_id="travel_pref_001",
)

print(memory_id)

出力:

travel_pref_001

スレッドの基本

スレッドへのメッセージの追加

メッセージは、ディクショナリとして、またはMessageオブジェクトとして渡すことができます。オプションのメッセージID、タイムスタンプおよびメタデータをそれらとともに格納できます。

from oracleagentmemory.apis import Message

thread = memory.create_thread(
    thread_id="thread_messages_123",
    user_id="user_123",
    agent_id="agent_456",
)

message_ids = thread.add_messages(
    [
        Message(
            id="msg_user_001",
            role="user",
            content="I prefer window seats on flights.",
            timestamp="2026-03-27T09:00:00Z",
            metadata={"source": "chat", "channel": "web"},
        ),
        {
            "id": "msg_assistant_001",
            "role": "assistant",
            "content": "Noted. I will keep that in mind.",
            "timestamp": "2026-03-27T09:00:05Z",
            "metadata": {"source": "assistant"},
        },
    ]
)

print(message_ids)

出力:

['msg_user_001', 'msg_assistant_001']

スレッド・メッセージの読取り

格納されているすべてのメッセージまたはスライスは、startおよびendを使用して読み取ることができます。

thread = memory.create_thread(thread_id="thread_read_messages_123")
thread.add_messages(
    [
        {"role": "user", "content": "Message 1"},
        {"role": "assistant", "content": "Message 2"},
        {"role": "user", "content": "Message 3"},
    ]
)

default_messages = thread.get_messages()
all_messages = thread.get_messages(end=None)
middle_messages = thread.get_messages(start=1, end=3)

print([message.content for message in default_messages])

print([message.content for message in all_messages])

print([message.content for message in middle_messages])

出力:

短いスレッドでは、バインドされたデフォルトが引き続きすべてのメッセージを返します。

['Message 1', 'Message 2', 'Message 3']

['Message 1', 'Message 2', 'Message 3']

['Message 2', 'Message 3']

IDによる現在のスレッドからのメッセージの削除

メッセージを削除すると、現在のスレッドからRAWメッセージ行のみが削除されます。そのメッセージから作成された派生メモリーまたはその他のダウンストリーム・アーティファクトは、検索可能なままになり、コンテキスト・カード出力に影響する場合があります。スレッドを関連するメッセージおよびメモリーとともに削除する必要がある場合は、かわりにdelete_thread()を使用します。別のスレッドから識別子を渡しても、0が返されます。

thread = memory.create_thread(thread_id="thread_delete_message_123")
message_ids = thread.add_messages(
    [
        {"role": "user", "content": "Message to delete"},
    ]
)

deleted = thread.delete_message(message_ids[0])
print(deleted)

出力:

1

これにより、現在のスレッドからRAWメッセージ行のみが削除されます。そのメッセージから作成された派生メモリーまたはその他のダウンストリーム・アーティファクトは、自動的に削除されず、検索可能なままになるか、コンテキスト・カード出力に表示される場合があります。memory.delete_thread(thread.thread_id)を使用して、スレッドを関連するメッセージおよびメモリーとともに削除します。メッセージの削除では、別のスレッドが所有するIDに対して0が返されます。

IDによる現在のスレッドからのメッセージの更新

スレッド・スコープのメッセージ更新は、現在のスレッドが所有するRAWメッセージにのみ影響します。ストアド・ロールおよびタイムスタンプ値は保持され、自動抽出が有効な場合、メッセージ・コンテンツを編集すると、add_messages()と同じ履歴ウィンドウ・ルールを使用して、編集されたメッセージの抽出がただちに再実行されます。サポート・コンテキストとして使用できるのは、以前のスレッド履歴のみです。後のメッセージは、その即時パス中に無視され、同じリフレッシュによって、既存の導出されたメモリーが維持され、編集されたコンテンツから新しいメモリーが追加されます。

thread = memory.create_thread(thread_id="thread_update_message_123")
thread.add_messages(
    [
        {
            "id": "msg_update_001",
            "role": "user",
            "content": "Original message text.",
            "timestamp": "2026-03-27T10:00:00Z",
            "metadata": {"source": "chat"},
        }
    ]
)

updated_message_id = thread.update_message(
    "msg_update_001",
    content="Edited message text.",
    metadata={"source": "support"},
)
print(updated_message_id)

出力:

msg_update_001

メッセージ更新では、格納されているロールおよびタイムスタンプ値が保持されます。自動抽出が有効な場合、コンテンツ編集は、add_messages()と同じ履歴ウィンドウ・ルールを使用して、編集したメッセージの抽出をすぐに再実行します。後のメッセージは、その即時パス中に無視されます。既存の派生した記憶はそのまま残りますが、新しい編集内容の記憶はそのリフレッシュ中に追加されます。

スレッド・ハンドルからのメモリーの追加

戻り値はメモリー識別子です。

thread = memory.create_thread(
    thread_id="thread_add_memory_123",
    user_id="user_123",
    agent_id="agent_456",
)

memory_id = thread.add_memory(
    "Use pytest for this repository's test suite.",
    memory_type="guideline",
)
print(memory_id)

出力:

mem:4

IDによる現在のスレッドからのメモリーの更新

スレッド・スコープの更新は、現在のスレッドが所有するメモリーに似たレコードにのみ影響します。別のスレッドから識別子を渡すと、KeyErrorが発生します。

thread = memory.create_thread(
    thread_id="thread_update_memory_123",
    user_id="user_123",
    agent_id="agent_456",
)
memory_id = thread.add_memory(
    "The user likes jasmine tea.",
    metadata={"source": "survey"},
)

updated_memory_id = thread.update_memory(
    memory_id,
    content="The user likes jasmine tea in the afternoon.",
    metadata={"source": "support"},
)
print(updated_memory_id)

出力:

mem:5

スレッド更新は、現在のスレッドにスコープ指定され、別のスレッドが所有するIDまたはIDがない場合にKeyErrorが呼び出されます。

IDによる現在のスレッドからのメモリーの削除

スレッド削除は、現在のスレッドにスコープ指定されます。別のスレッドから識別子を渡すと、0が返されます。

thread = memory.create_thread(thread_id="thread_delete_memory_123")
memory_id = thread.add_memory("Temporary memory to delete.")

deleted = thread.delete_memory(memory_id)
print(deleted)

出力:

1

スレッド削除は現在のスレッドにスコープ指定され、別のスレッドが所有するIDの場合は0を返します。

コンテキスト・カードの作成

thread = memory.create_thread(thread_id="thread_context_card_123")
thread.add_messages(
    [
        {"role": "user", "content": "I am planning a trip to Kyoto next spring."},
    ]
)
thread.add_memory("The user is planning a trip to Kyoto.")

context_card = thread.get_context_card()
print(context_card.content)

出力:

<context_card>
    The user is planning a trip to Kyoto.
</context_card>

スレッド・サマリーの作成

thread = memory.create_thread(thread_id="thread_summary_123")
thread.add_messages(
    [
        {"role": "user", "content": "Hello"},
        {"role": "assistant", "content": "Hi, how can I help?"},
        {"role": "user", "content": "Please summarize this thread."},
    ]
)

summary = thread.get_summary()
print(summary.content)

出力:

user (-): Hello
- assistant (-): Hi, how can I help?
- user (-): Please summarize this thread.

最後のNメッセージを除くサマリーの作成

thread = memory.create_thread(thread_id="thread_summary_except_last_123")
thread.add_messages(
    [
        {"role": "user", "content": "First message"},
        {"role": "assistant", "content": "Second message"},
        {"role": "user", "content": "Third message"},
    ]
)

summary = thread.get_summary(except_last=1)
print(summary.content)

出力:

user (-): First message
- assistant (-): Second message

トークン予算を使用した要約の作成

thread = memory.create_thread(thread_id="thread_summary_budget_123")
thread.add_messages(
    [
        {"role": "user", "content": "Message 1"},
        {"role": "assistant", "content": "Message 2"},
        {"role": "user", "content": "Message 3"},
        {"role": "assistant", "content": "Message 4"},
    ]
)

summary = thread.get_summary(token_budget=20)
print(summary.content)

出力:

(truncated)
user (-): Message 1
...

検索

明示的な範囲指定のないスレッドからの検索

スレッド・レベルの検索では、明示的なスコープを渡さない場合、スレッドのデフォルトが使用されます。

thread = memory.create_thread(
    thread_id="thread_search_default_123",
    user_id="user_123",
    agent_id="agent_456",
)
thread.add_memory("The user likes pizza.")
thread.add_memory("The user likes cats.")

results = thread.search("pizza", max_results=5)
print([result.content for result in results])

出力:

['The user likes pizza.']

スコーピングを使用したメモリーAPIからの検索

APIレベルでは、user_idagent_idおよびthread_idからSearchScopeを使用して、取得の範囲を指定できます。最上位のクライアント検索の場合は、明示的なユーザー・スコープを指定します。user_id=Noneは、スコープなしレコードを意図的に使用する場合にのみ使用します。省略された値、明示的なNoneおよび完全一致フラグが各APIレイヤーでどのように解決されるかの概要は、スコープ解決を参照してください。

from oracleagentmemory.apis.searchscope import SearchScope

thread = memory.create_thread(
    thread_id="thread_memory_search_123",
    user_id="user_123",
    agent_id="agent_456",
)
thread.add_memory("The user likes hiking in the Alps.")

results = memory.search(
    "hiking",
    scope=SearchScope(
        user_id="user_123",
        agent_id="agent_456",
        thread_id="thread_memory_search_123",
        exact_thread_match=True,
    ),
    max_results=5,
)

print([result.content for result in results])

出力:

['The user likes hiking in the Alps.']

メタデータ・フィルタリングによる検索

metadata_filterは、リクエストされた部分マッピングが格納されたメタデータを含むレコードのみを検索で考慮する必要がある場合に使用します。複数のフィルタ・キーはANDセマンティクスと組み合され、ネストされたディクショナリはネストされたメタデータ・フィールドに一致し、ベア・リスト値は完全に一致する必要があります。配列メンバーシップをテストするには、{"tags": {"$array_contains": "outdoor"}}などのフィールド・レベルの演算子ディクショナリを使用します。リストを含む"$array_contains"にはすべてのリストされた値が必要であり、"$array_contains_any"には少なくとも1つのリストされた値が必要であり、"$not"は、演算子ディクショナリまたはRAW完全一致値を含む同じフィールドでの別のフィールド・レベルの式を否定します。否定された式は、欠落フィールドを含む正の式が失敗した場合にも一致します。否定された配列メンバーシップも、配列以外のフィールドと一致します。

from oracleagentmemory.apis.searchscope import SearchScope

thread = memory.create_thread(
    thread_id="thread_metadata_filter_123",
    user_id="user_123",
    agent_id="agent_456",
)
thread.add_memory(
    "The user likes alpine hiking.",
    metadata={"source": "survey", "category": {"kind": "travel"}, "tags": ["outdoor"]},
)
thread.add_memory(
    "The user likes indoor climbing.",
    metadata={"source": "chat", "category": {"kind": "sports"}, "tags": ["indoor"]},
)

results = memory.search(
    "hiking",
    scope=SearchScope(user_id="user_123"),
    max_results=5,
    record_types=["memory"],
    metadata_filter={"source": "survey"},
)

print([result.content for result in results])

outdoor_results = memory.search(
    "hiking",
    scope=SearchScope(user_id="user_123"),
    max_results=5,
    record_types=["memory"],
    metadata_filter={
        "source": "survey",
        "tags": {"$array_contains": "outdoor"},
    },
)

print([result.content for result in outdoor_results])

出力:

['The user likes alpine hiking.']

['The user likes alpine hiking.']

メモのみまたはメッセージのみを検索

record_typesを使用して、検索結果を特定のストアド・レコード・タイプに制限します。

thread = memory.create_thread(thread_id="thread_entity_type_search_123")
thread.add_messages(
    [
        {"role": "user", "content": "I mentioned pizza in a message."},
    ]
)
thread.add_memory("The user likes pizza.")

memory_results = thread.search("pizza", max_results=5, record_types=["memory"])
message_results = thread.search("pizza", max_results=5, record_types=["message"])

print([result.content for result in memory_results])

print([result.content for result in message_results])

出力:

['The user likes pizza.']

['I mentioned pizza in a message.']

完全コード

#Copyright © 2026 Oracle and/or its affiliates.
#This software is under the Apache License 2.0
#(LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License
#(UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option.

#Oracle Agent Memory Code Example - Reference Sheet
#--------------------------------------------------

##Configure a LiteLLM LLM

from oracleagentmemory.core.llms.llm import Llm

llm = Llm(
    model="YOUR_LLM_MODEL",
    api_base="YOUR_LLM_API_BASE",
    api_key="YOUR_LLM_API_KEY",
)

response = llm.generate("What is 2+2?")
print(response.text)
#2+2 is equal to 4


##Configure a LiteLLM embedding model

from oracleagentmemory.core.embedders.embedder import Embedder

embedder = Embedder(
    model="YOUR_EMBEDDING_MODEL",
    api_base="YOUR_EMBEDDING_API_BASE",
    api_key="YOUR_EMBEDDING_API_KEY",
)

embedding_matrix = embedder.embed(["The quick brown fox jumps over the lazy dog"])
print(embedding_matrix.shape)
#(1, embedding_dimension)


##Configure an Oracle Memory component

import oracledb

from oracleagentmemory.core.oracleagentmemory import OracleAgentMemory

db_pool = oracledb.SessionPool(
    user="YOUR DB USER",
    password="YOUR DB PASSWORD",
    dsn="YOUR DB CONNECT STRING",
)

memory = OracleAgentMemory(
    connection=db_pool,
    embedder=embedder,
    llm=llm,  # optional: enables automatic memory extraction during add_messages()
)


##Configure an Oracle DB component

import oracledb

from oracleagentmemory.core import SchemaPolicy
from oracleagentmemory.core.oracleagentmemory import OracleAgentMemory

db_pool = oracledb.SessionPool(
    user="YOUR DB USER",
    password="YOUR DB PASSWORD",
    dsn="YOUR DB CONNECT STRING",
)

db_memory = OracleAgentMemory(
    connection=db_pool,
    embedder=embedder,
    llm=llm,  # optional
    schema_policy=SchemaPolicy.CREATE_IF_NECESSARY,
    memory_store_id="DEV_",
)


##Configure an Oracle Hybrid DB component

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

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

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


##Create a thread

thread = memory.create_thread(
    thread_id="thread_create_123",  # optional
    user_id="user_123",          # optional
    agent_id="agent_456",        # optional
)

print(thread.thread_id)
#thread_create_123


##Re open an existing thread

thread = memory.create_thread(
    thread_id="thread_reopen_123",
    user_id="user_123",
    agent_id="agent_456",
)

same_thread = memory.get_thread("thread_reopen_123")
print(same_thread.thread_id)
#thread_reopen_123


##Update an existing thread

thread = memory.create_thread(
    thread_id="thread_update_123",
    user_id="user_123",
    agent_id="agent_456",
)

loaded_thread = memory.get_thread(
    "thread_update_123",
    max_message_token_length=8_000,
)
print(loaded_thread.max_message_token_length)
#8000

updated_thread = memory.update_thread(
    "thread_update_123",
    metadata={"source": "support", "flags": {"vip": True}},
    max_message_token_length=8_000,
)
persisted_thread = memory.get_thread("thread_update_123")

print(updated_thread.metadata["flags"]["vip"])
#True
print(persisted_thread.max_message_token_length)
#8000
#Overrides passed to get_thread() are temporary. Call update_thread()
#to persist thread metadata or durable runtime-config changes.


##Delete a thread

thread = memory.create_thread(thread_id="thread_delete_123")

deleted = memory.delete_thread("thread_delete_123")
print(deleted)
#1
#Use thread deletion when you need thread-scoped cascading cleanup.
#It removes the thread together with its messages, memories,
#and backing retrieval data managed by the SDK.


##Add a user profile

user_profile_id = memory.add_user(
    "user_123",
    "The user prefers concise answers and works mostly with Python.",
)

print(user_profile_id)
#user_123


##Add an agent profile

agent_profile_id = memory.add_agent(
    "agent_456",
    "A coding assistant specialized in debugging and code review.",
)

print(agent_profile_id)
#agent_456


##Add a global memory from the memory API

memory_id = memory.add_memory(
    "The user prefers short, bullet-point answers.",
    user_id="user_123",
    agent_id="agent_456",
)

print(memory_id)
#mem:1


##Add a scoped memory from the memory API

thread = memory.create_thread(
    thread_id="thread_scoped_123",
    user_id="user_123",
    agent_id="agent_456",
)

memory_id = memory.add_memory(
    "The user is planning a trip to Kyoto next month.",
    user_id="user_123",
    agent_id="agent_456",
    thread_id=thread.thread_id,
)

print(memory_id)
#mem:2


##Update a memory from the memory API

thread = memory.create_thread(
    thread_id="thread_update_memory_api_123",
    user_id="user_123",
    agent_id="agent_456",
)
memory_id = memory.add_memory(
    "The user likes short status updates.",
    user_id=thread.user_id,
    agent_id=thread.agent_id,
    thread_id=thread.thread_id,
    metadata={"source": "chat"},
)

updated_memory_id = memory.update_memory(
    memory_id,
    content="The user prefers short status updates.",
    metadata={"source": "support"},
)

print(updated_memory_id)
#mem:3


##Add a memory with a custom ID

memory_id = memory.add_memory(
    "The user prefers aisle seats on flights.",
    user_id="user_123",
    agent_id="agent_456",
    memory_id="travel_pref_001",
)

print(memory_id)
#travel_pref_001


##Add messages to a thread

from oracleagentmemory.apis import Message

thread = memory.create_thread(
    thread_id="thread_messages_123",
    user_id="user_123",
    agent_id="agent_456",
)

message_ids = thread.add_messages(
    [
        Message(
            id="msg_user_001",
            role="user",
            content="I prefer window seats on flights.",
            timestamp="2026-03-27T09:00:00Z",
            metadata={"source": "chat", "channel": "web"},
        ),
        {
            "id": "msg_assistant_001",
            "role": "assistant",
            "content": "Noted. I will keep that in mind.",
            "timestamp": "2026-03-27T09:00:05Z",
            "metadata": {"source": "assistant"},
        },
    ]
)

print(message_ids)
#['msg_user_001', 'msg_assistant_001']


##Read back thread messages

thread = memory.create_thread(thread_id="thread_read_messages_123")
thread.add_messages(
    [
        {"role": "user", "content": "Message 1"},
        {"role": "assistant", "content": "Message 2"},
        {"role": "user", "content": "Message 3"},
    ]
)

default_messages = thread.get_messages()
all_messages = thread.get_messages(end=None)
middle_messages = thread.get_messages(start=1, end=3)

print([message.content for message in default_messages])
#On short threads, the bounded default still returns all messages.
#['Message 1', 'Message 2', 'Message 3']
print([message.content for message in all_messages])
#['Message 1', 'Message 2', 'Message 3']
print([message.content for message in middle_messages])
#['Message 2', 'Message 3']


##Delete a message from the current thread by ID

thread = memory.create_thread(thread_id="thread_delete_message_123")
message_ids = thread.add_messages(
    [
        {"role": "user", "content": "Message to delete"},
    ]
)

deleted = thread.delete_message(message_ids[0])
print(deleted)
#1
#This removes only the raw message row from the current thread.
#Derived memories or other downstream artifacts created from that message
#are not deleted automatically and may remain searchable or appear in
#context-card output. Use memory.delete_thread(thread.thread_id) to delete
#the thread together with its associated messages and memories.
#Message deletes return 0 for IDs owned by another thread.


##Update a message from the current thread by ID

thread = memory.create_thread(thread_id="thread_update_message_123")
thread.add_messages(
    [
        {
            "id": "msg_update_001",
            "role": "user",
            "content": "Original message text.",
            "timestamp": "2026-03-27T10:00:00Z",
            "metadata": {"source": "chat"},
        }
    ]
)

updated_message_id = thread.update_message(
    "msg_update_001",
    content="Edited message text.",
    metadata={"source": "support"},
)
print(updated_message_id)
#msg_update_001
#Message updates preserve stored role and timestamp values.
#When automatic extraction is enabled, content edits immediately rerun
#extraction for the edited message using the same history-window
#rules as add_messages().
#Later messages are ignored during that immediate pass.
#Existing derived memories stay in place while new edited-content
#memories are added during that refresh.


##Add a memory from a thread handle

thread = memory.create_thread(
    thread_id="thread_add_memory_123",
    user_id="user_123",
    agent_id="agent_456",
)

memory_id = thread.add_memory("The user likes jasmine tea.")
print(memory_id)
#mem:4


##Update a memory from the current thread by ID

thread = memory.create_thread(
    thread_id="thread_update_memory_123",
    user_id="user_123",
    agent_id="agent_456",
)
memory_id = thread.add_memory(
    "The user likes jasmine tea.",
    metadata={"source": "survey"},
)

updated_memory_id = thread.update_memory(
    memory_id,
    content="The user likes jasmine tea in the afternoon.",
    metadata={"source": "support"},
)
print(updated_memory_id)
#mem:5
#Thread updates are scoped to the current thread and raise KeyError
#for missing IDs or IDs owned by another thread.


##Delete a memory from the current thread by ID

thread = memory.create_thread(thread_id="thread_delete_memory_123")
memory_id = thread.add_memory("Temporary memory to delete.")

deleted = thread.delete_memory(memory_id)
print(deleted)
#1
#Thread deletes are scoped to the current thread and return 0 for IDs owned by another thread.


##Build a context card

thread = memory.create_thread(thread_id="thread_context_card_123")
thread.add_messages(
    [
        {"role": "user", "content": "I am planning a trip to Kyoto next spring."},
    ]
)
thread.add_memory("The user is planning a trip to Kyoto.")

context_card = thread.get_context_card()
print(context_card.content)
#<context_card>
#The user is planning a trip to Kyoto.
#</context_card>


##Build a thread summary

thread = memory.create_thread(thread_id="thread_summary_123")
thread.add_messages(
    [
        {"role": "user", "content": "Hello"},
        {"role": "assistant", "content": "Hi, how can I help?"},
        {"role": "user", "content": "Please summarize this thread."},
    ]
)

summary = thread.get_summary()
print(summary.content)
#user (-): Hello
#- assistant (-): Hi, how can I help?
#- user (-): Please summarize this thread.


##Build a summary excluding the last N messages

thread = memory.create_thread(thread_id="thread_summary_except_last_123")
thread.add_messages(
    [
        {"role": "user", "content": "First message"},
        {"role": "assistant", "content": "Second message"},
        {"role": "user", "content": "Third message"},
    ]
)

summary = thread.get_summary(except_last=1)
print(summary.content)
#user (-): First message
#- assistant (-): Second message


##Build a summary with a token budget

thread = memory.create_thread(thread_id="thread_summary_budget_123")
thread.add_messages(
    [
        {"role": "user", "content": "Message 1"},
        {"role": "assistant", "content": "Message 2"},
        {"role": "user", "content": "Message 3"},
        {"role": "assistant", "content": "Message 4"},
    ]
)

summary = thread.get_summary(token_budget=20)
print(summary.content)
#(truncated)
#user (-): Message 1
#...


##Search from a thread with no explicit scoping

thread = memory.create_thread(
    thread_id="thread_search_default_123",
    user_id="user_123",
    agent_id="agent_456",
)
thread.add_memory("The user likes pizza.")
thread.add_memory("The user likes cats.")

results = thread.search("pizza", max_results=5)
print([result.content for result in results])
#['The user likes pizza.']


##Search from the memory API with scoping

from oracleagentmemory.apis.searchscope import SearchScope

thread = memory.create_thread(
    thread_id="thread_memory_search_123",
    user_id="user_123",
    agent_id="agent_456",
)
thread.add_memory("The user likes hiking in the Alps.")

results = memory.search(
    "hiking",
    scope=SearchScope(
        user_id="user_123",
        agent_id="agent_456",
        thread_id="thread_memory_search_123",
        exact_thread_match=True,
    ),
    max_results=5,
)

print([result.content for result in results])
#['The user likes hiking in the Alps.']


##Search with metadata filtering

from oracleagentmemory.apis.searchscope import SearchScope

thread = memory.create_thread(
    thread_id="thread_metadata_filter_123",
    user_id="user_123",
    agent_id="agent_456",
)
thread.add_memory(
    "The user likes alpine hiking.",
    metadata={"source": "survey", "category": {"kind": "travel"}, "tags": ["outdoor"]},
)
thread.add_memory(
    "The user likes indoor climbing.",
    metadata={"source": "chat", "category": {"kind": "sports"}, "tags": ["indoor"]},
)

results = memory.search(
    "hiking",
    scope=SearchScope(user_id="user_123"),
    max_results=5,
    record_types=["memory"],
    metadata_filter={"source": "survey"},
)

print([result.content for result in results])
#['The user likes alpine hiking.']

outdoor_results = memory.search(
    "hiking",
    scope=SearchScope(user_id="user_123"),
    max_results=5,
    record_types=["memory"],
    metadata_filter={
        "source": "survey",
        "tags": {"$array_contains": "outdoor"},
    },
)

print([result.content for result in outdoor_results])
#['The user likes alpine hiking.']


##Search only memories or messages

thread = memory.create_thread(thread_id="thread_entity_type_search_123")
thread.add_messages(
    [
        {"role": "user", "content": "I mentioned pizza in a message."},
    ]
)
thread.add_memory("The user likes pizza.")

memory_results = thread.search("pizza", max_results=5, record_types=["memory"])
message_results = thread.search("pizza", max_results=5, record_types=["message"])

print([result.content for result in memory_results])
#['The user likes pizza.']
print([result.content for result in message_results])
#['I mentioned pizza in a message.']