WayFlow에서 에이전트 메모리 사용

이 문서에서는 에이전트가 세션 간에 영구 팩트를 재사용할 수 있도록 에이전트 메모리를 WayFlow 에이전트에 연결하는 방법에 대해 알아봅니다.

참고: 패키지 설정은 에이전트 메모리 시작하기를 참조하십시오. 이 예에 대한 로컬 Oracle AI Database가 필요한 경우 Run Oracle AI Database Locally를 참조하십시오. WayFlow에 대한 자세한 내용은 https://github.com/oracle/wayflow.를 참조하십시오.

에이전트 메모리 및 WayFlow 구성

사용자에 대한 에이전트 메모리 스레드를 생성하고, WayFlow에 search_memory 툴을 노출하고, OpenAIModel를 사용하여 WayFlow Agent를 구성합니다. search_memory 도구는 사용자 및 에이전트 ID별로 에이전트 메모리 API를 쿼리하므로 현재 스레드로 제한되는 대신 이전 세션에서 영구적인 팩트를 복구할 수 있습니다. 또한 에이전트 메모리 클라이언트는 자체 LLM을 사용하여 최근 스레드 메시지에서 영구 메모리를 주기적으로 추출하고, WayFlow Agent는 회신 및 도구 호출에 자체 OpenAIModel를 계속 사용합니다.

from oracleagentmemory.core.embedders.embedder import Embedder
from oracleagentmemory.core.llms.llm import Llm
from oracleagentmemory.core.oracleagentmemory import OracleAgentMemory
from wayflowcore.agent import Agent
from wayflowcore.models import OpenAIModel
from wayflowcore.tools import tool

embedder = Embedder(
    model="YOUR_EMBEDDING_MODEL",
    api_base="YOUR_EMBEDDING_API_BASE",
    api_key="YOUR_EMBEDDING_API_KEY",
)
llm = Llm(
    model="gpt-4.1-mini",
    api_key="YOUR_OPENAI_API_KEY",
)
db_pool = ...  #an oracledb connection or connection pool
wayflow_llm = OpenAIModel(
    model_id="gpt-4.1-mini",
    api_key="YOUR_OPENAI_API_KEY",
)


#Keep these identifiers stable for the same assistant and end user so memory
#is scoped consistently across threads and sessions.
agent_id = "support_agent"
user_id = "user_123"
memory = OracleAgentMemory(
    connection=db_pool,
    embedder=embedder,
    llm=llm,
)
memory_thread = memory.create_thread(
    thread_id="wayflow_memory_demo",
    user_id=user_id,
    agent_id=agent_id,
)

from typing import Annotated


@tool
def search_memory(
    query: Annotated[str, "Question to search in Oracle Agent Memory"],
) -> Annotated[str, "Top matching memory content"]:
    """Search Oracle Agent Memory for durable user facts relevant to the current request."""
    results = memory.search(
        query=query,
        user_id=user_id,
        agent_id=agent_id,
        max_results=1,
        record_types=["memory"],
    )
    if not results:
        return "No relevant memory found."
    return results[0].content

assistant = Agent(
    llm=wayflow_llm,
    agent_id=agent_id,
    custom_instruction=(
        "You are a support agent. When the user asks about durable facts from "
        "prior sessions, call the search_memory tool before answering."
    ),
    tools=[search_memory],
)

세션 후 사용자 컨텍스트 유지

각 WayFlow 세션 후에 교환된 메시지를 에이전트 메모리에 추가하고 나중에 재사용해야 하는 영구적인 사실을 저장합니다.

session_1 = assistant.start_conversation()
user_message = (
    "I am John, a Python developer and I need help debugging a payment service."
)
session_1.append_user_message(user_message)
session_1.execute()
assistant_reply = session_1.get_last_message().content

print(assistant_reply)
#I can help with that. What error are you seeing?

#add_messages will add messages to the DB and extract memories automatically
memory_thread.add_messages(
    [
        {"role": "user", "content": user_message},
        {"role": "assistant", "content": assistant_reply},
    ]
)
#add_memory adds memory to the DB
memory_thread.add_memory("The user is John, a Python developer.")

새 WayFlow 세션에서 메모리 재사용

이후 세션이 시작되면 동일한 에이전트 메모리 스레드를 다시 열고 WayFlow 에이전트가 search_memory를 호출하여 이전 사용자 컨텍스트를 복구하도록 합니다.

memory_thread = memory.get_thread("wayflow_memory_demo")
assistant = Agent(
    llm=wayflow_llm,
    agent_id=agent_id,
    custom_instruction=(
        "You are a support agent. When the user asks about durable facts from "
        "prior sessions, call the search_memory tool before answering."
    ),
    tools=[search_memory],
)

session_2 = assistant.start_conversation()
session_2.append_user_message("Who am I?")
session_2.execute()
remembered_reply = session_2.get_last_message().content

print(remembered_reply)

출력:

The user is John, a Python developer.

고급 사용

보다 긴밀한 통합을 위해 ConversationMessageAddedEvent` 항목을 버퍼링하고 실행 종료 시 에이전트 메모리에 기록하는 WayFlow 이벤트 리스너를 등록할 수 있습니다. 이렇게 하면 에이전트 메모리 업데이트 경로가 주 스레드 코드와 분리되어 유지되지만 마지막으로 교환된 메시지는 계속 유지됩니다.

from wayflowcore.events.event import ConversationMessageAddedEvent
from wayflowcore.events.eventlistener import GenericEventListener, register_event_listeners

pending_messages: list[dict[str, str]] = []


def _buffer_thread_message(event: ConversationMessageAddedEvent) -> None:
    if event.streamed:
        return
    pending_messages.append(
        {
            "role": event.message.role,
            "content": event.message.content,
        }
    )


message_listener = GenericEventListener(
    [ConversationMessageAddedEvent],
    _buffer_thread_message,
)

with register_event_listeners([message_listener]):
    session_3 = assistant.start_conversation()
    session_3.append_user_message("Please remember that I prefer concise code reviews.")
    session_3.execute()

if pending_messages:
    memory_thread.add_messages(pending_messages)

자동 추출 사용 안함

메시지를 지속하고 영구 메모리를 수동으로 추가하려면 extract_memories=False로 에이전트 메모리 클라이언트를 만들고 영구 메모리 행을 직접 삽입합니다.

manual_memory = OracleAgentMemory(
    connection=db_pool,
    embedder=embedder,
    extract_memories=False,
)
manual_memory_thread = manual_memory.create_thread(
    thread_id="wayflow_manual_memory_demo",
    user_id=user_id,
    agent_id=agent_id,
)
manual_memory_thread.add_messages(
    [
        {
            "role": "user",
            "content": "Please remember that I prefer concise code reviews.",
        },
        {
            "role": "assistant",
            "content": "Understood. I will keep responses concise.",
        },
    ]
)
manual_memory_thread.add_memory("The user prefers concise code reviews.")

결론

이 문서에서는 에이전트 메모리를 WayFlow 에이전트에 연결하고, 각 세션 후에 교환된 메시지와 영구 메모리를 유지하고, 이후 실행에서 이전 사용자 컨텍스트를 재사용하는 방법을 배웠습니다.

참고: 에이전트 메모리를 WayFlow와 통합하는 방법을 배웠을 때 에이전트 메모리를 LangGraph와 통합에도 관심이 있을 수 있습니다.

전체 코드

#Copyright © 2026 Oracle and/or its affiliates.
#isort:skip_file
#fmt: off
#Agent Memory Code Example - Integration with WayFlow
#-----------------------------------------------------

#How to use:
#Create a new Python virtual environment and install the latest oracleagentmemory version.

#You can now run the script
#1. As a Python file:
#```bash
#python integration_with_wayflow.py
#```
#2. As a Notebook (in VSCode):
#When viewing the file,
#- press the keys Ctrl + Enter to run the selected cell
#- or Shift + Enter to run the selected cell and move to the cell below


##Configure Oracle Memory and WayFlow

#%%
from oracleagentmemory.core.embedders.embedder import Embedder
from oracleagentmemory.core.llms.llm import Llm
from oracleagentmemory.core.oracleagentmemory import OracleAgentMemory
from wayflowcore.agent import Agent
from wayflowcore.models import OpenAIModel
from wayflowcore.tools import tool

embedder = Embedder(
    model="YOUR_EMBEDDING_MODEL",
    api_base="YOUR_EMBEDDING_API_BASE",
    api_key="YOUR_EMBEDDING_API_KEY",
)
llm = Llm(
    model="gpt-4.1-mini",
    api_key="YOUR_OPENAI_API_KEY",
)
db_pool = ...  #an oracledb connection or connection pool
wayflow_llm = OpenAIModel(
    model_id="gpt-4.1-mini",
    api_key="YOUR_OPENAI_API_KEY",
)

#Keep these identifiers stable for the same assistant and end user so memory
#is scoped consistently across threads and sessions.
agent_id = "support_agent"
user_id = "user_123"
memory = OracleAgentMemory(
    connection=db_pool,
    embedder=embedder,
    llm=llm,
)
memory_thread = memory.create_thread(
    thread_id="wayflow_memory_demo",
    user_id=user_id,
    agent_id=agent_id,
)

from typing import Annotated


@tool
def search_memory(
    query: Annotated[str, "Question to search in Oracle Agent Memory"],
) -> Annotated[str, "Top matching memory content"]:
    """Search Oracle Agent Memory for durable user facts relevant to the current request."""
    results = memory.search(
        query=query,
        user_id=user_id,
        agent_id=agent_id,
        max_results=1,
        record_types=["memory"],
    )
    if not results:
        return "No relevant memory found."
    return results[0].content

assistant = Agent(
    llm=wayflow_llm,
    agent_id=agent_id,
    custom_instruction=(
        "You are a support agent. When the user asks about durable facts from "
        "prior sessions, call the search_memory tool before answering."
    ),
    tools=[search_memory],
)


##Persist user context after a session

#%%
session_1 = assistant.start_conversation()
user_message = (
    "I am John, a Python developer and I need help debugging a payment service."
)
session_1.append_user_message(user_message)
session_1.execute()
assistant_reply = session_1.get_last_message().content

print(assistant_reply)
#I can help with that. What error are you seeing?

memory_thread.add_messages(
    [
        {"role": "user", "content": user_message},
        {"role": "assistant", "content": assistant_reply},
    ]
)
memory_thread.add_memory("The user is John, a Python developer.")


##Reuse memory in a new WayFlow session

#%%
memory_thread = memory.get_thread("wayflow_memory_demo")
assistant = Agent(
    llm=wayflow_llm,
    agent_id=agent_id,
    custom_instruction=(
        "You are a support agent. When the user asks about durable facts from "
        "prior sessions, call the search_memory tool before answering."
    ),
    tools=[search_memory],
)

session_2 = assistant.start_conversation()
session_2.append_user_message("Who am I?")
session_2.execute()
remembered_reply = session_2.get_last_message().content

print(remembered_reply)
#The user is John, a Python developer.


##Advanced use event listeners

#%%
from wayflowcore.events.event import ConversationMessageAddedEvent
from wayflowcore.events.eventlistener import GenericEventListener, register_event_listeners

pending_messages: list[dict[str, str]] = []


def _buffer_thread_message(event: ConversationMessageAddedEvent) -> None:
    if event.streamed:
        return
    pending_messages.append(
        {
            "role": event.message.role,
            "content": event.message.content,
        }
    )


message_listener = GenericEventListener(
    [ConversationMessageAddedEvent],
    _buffer_thread_message,
)

with register_event_listeners([message_listener]):
    session_3 = assistant.start_conversation()
    session_3.append_user_message("Please remember that I prefer concise code reviews.")
    session_3.execute()

if pending_messages:
    memory_thread.add_messages(pending_messages)


##Disable automatic memory extraction

#%%
manual_memory = OracleAgentMemory(
    connection=db_pool,
    embedder=embedder,
    extract_memories=False,
)
manual_memory_thread = manual_memory.create_thread(
    thread_id="wayflow_manual_memory_demo",
    user_id=user_id,
    agent_id=agent_id,
)
manual_memory_thread.add_messages(
    [
        {
            "role": "user",
            "content": "Please remember that I prefer concise code reviews.",
        },
        {
            "role": "assistant",
            "content": "Understood. I will keep responses concise.",
        },
    ]
)
manual_memory_thread.add_memory("The user prefers concise code reviews.")