{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Deep Research Agent with Oracle AI Agent Memory\n", "\n", "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/oracle-devrel/oracle-ai-developer-hub/blob/main/notebooks/agent_memory/01_deep_research_openai_agents.ipynb) [![Documentation](https://img.shields.io/badge/Documentation-Oracle%20AI%20Agent%20Memory-red?style=flat-square)](https://www.oracle.com/database/ai-agent-memory/)\n", "\n", "\n", "**Framework:** OpenAI Agents SDK ยท **Web search:** Tavily ยท **Memory:** Oracle AI Agent Memory on Oracle AI Database\n", "\n", "This notebook walks through building a **deep research agent** for human genome exploration. The agent uses Tavily for live web research, and stores its running conversation and durable findings in Oracle AI Database via the `oracleagentmemory` package.\n", "\n", "---\n", "\n", "## Application Modes in Agent Applications\n", "\n", "AI agent applications generally fall into three operational modes:\n", "\n", "| Mode | Shape | Typical use |\n", "|---|---|---|\n", "| **Assistant** | Turn-by-turn conversational | Customer support, coding copilot, chat UIs |\n", "| **Deep Research** | Multi-step autonomous investigation | Literature review, market research, technical scoping |\n", "| **Workflow** | Predetermined sequence of steps, often with conditional branches | Approval pipelines, compliance checks, structured triage |\n", "\n", "> **๐Ÿ“Œ This notebook focuses on the Deep Research mode.**\n", ">\n", "> A deep-research agent plans, retrieves, synthesises, and accumulates findings over long-horizon investigations. Memory is central โ€” without durable memory, every session restarts from zero and the agent cannot build on prior research." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## What You'll Learn\n", "\n", "- How to implement the **OpenAI Agents SDK `Session` protocol** against a custom backend (Oracle AI Agent Memory)\n", "- How to wrap **Tavily** as a `function_tool` the agent can call\n", "- How to store long-lived research findings as durable **memories** (separate from short-term conversation history)\n", "- How to verify memory continuity across sessions โ€” the agent can pick up where it left off\n", "\n", "> **๐Ÿ’ก Key insight:** Short-term memory (conversation history for the current run) and long-term memory (durable findings across runs) are different access patterns over the same store. We use `Session` for the former and `add_memory()` for the latter." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Prerequisites\n", "\n", "- **Oracle AI Database** running locally (Docker container) or reachable over the network\n", "- **`OPENAI_API_KEY`** for the agent's LLM and embeddings\n", "- **`TAVILY_API_KEY`** for web search (free tier available at [tavily.com](https://tavily.com))\n", "- The `oracleagentmemory` wheel installed in the active kernel's environment" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. Install dependencies\n", "\n", "We need four packages: `oracleagentmemory[litellm]` (memory + embeddings), `openai-agents` (agent framework), `tavily-python` (web search), and `nest_asyncio` (so `Runner.run` works cleanly inside a Jupyter event loop)." ] }, { "cell_type": "code", "execution_count": 1, "id": "bd4064d5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Note: you may need to restart the kernel to use updated packages.\n" ] } ], "source": [ "%pip install -q \"oracleagentmemory[litellm]\" openai-agents tavily-python nest_asyncio" ] }, { "cell_type": "markdown", "id": "4a1dacfb", "metadata": {}, "source": [ "## 2. Configure API keys and Oracle connection\n", "\n", "Set environment variables for OpenAI, Tavily, and the Oracle database. We use `os.environ.setdefault` so shell or `.env` values still win if you've set them elsewhere." ] }, { "cell_type": "code", "execution_count": null, "id": "3b121af1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Environment configured.\n" ] } ], "source": [ "import os\n", "\n", "# LLM + embedding provider (used by both the agent and OAMP)\n", "os.environ.setdefault(\"OPENAI_API_KEY\", \"sk-\")\n", "\n", "# Tavily for web search\n", "os.environ.setdefault(\"TAVILY_API_KEY\", \"tvly-\")\n", "\n", "# Oracle AI Database connection\n", "os.environ.setdefault(\"DB_USER\", \"VECTOR\")\n", "os.environ.setdefault(\"DB_PASSWORD\", \"VectorPwd_2025\")\n", "os.environ.setdefault(\"DB_CONNECT_STRING\", \"localhost:1521/FREEPDB1\")\n", "\n", "# Jupyter runs an async event loop already โ€” this lets us call async SDK methods cleanly\n", "import nest_asyncio\n", "nest_asyncio.apply()\n", "\n", "print(\"Environment configured.\")" ] }, { "cell_type": "markdown", "id": "50dbf9fa", "metadata": {}, "source": [ "## 3. Connect to Oracle AI Database and initialise the memory client\n", "\n", "`OracleAgentMemory` is the governed memory client. With `extract_memories=True` and an `llm` attached, the client will automatically extract durable memories from messages added to a thread. We use `text-embedding-3-small` for semantic search over the memory store.\n", "\n", "> **๐Ÿ’ก Key insight:** `schema_policy` controls how the library interacts with the DB on startup. `REQUIRE_EXISTING` (default) never issues DDL โ€” safe for production. `CREATE_IF_NECESSARY` fills in missing objects โ€” safe for dev. `RECREATE` drops and rebuilds โ€” useful when you've changed embedding dimensions." ] }, { "cell_type": "code", "execution_count": 3, "id": "5af41055", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Connected to Oracle AI Database: 23.26.0.0.0\n", "Memory client ready.\n" ] } ], "source": [ "import oracledb\n", "from oracleagentmemory.core import OracleAgentMemory\n", "from oracleagentmemory.core.llms import Llm\n", "\n", "connection = oracledb.connect(\n", " user=os.environ[\"DB_USER\"],\n", " password=os.environ[\"DB_PASSWORD\"],\n", " dsn=os.environ[\"DB_CONNECT_STRING\"],\n", ")\n", "print(\"Connected to Oracle AI Database:\", connection.version)\n", "\n", "# The LLM the extraction pipeline will use to turn raw messages into durable memories\n", "extraction_llm = Llm(\"gpt-4o-mini\", temperature=0.2)\n", "\n", "memory_client = OracleAgentMemory(\n", " connection=connection,\n", " embedder=\"text-embedding-3-small\", # OpenAI-compatible; 1536 dims\n", " llm=extraction_llm, # enables automatic memory extraction\n", " extract_memories=True,\n", " schema_policy=\"recreate\",\n", " table_name_prefix=\"genome_\", # isolates this example's tables from others\n", ")\n", "print(\"Memory client ready.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4. Register the research user and agent\n", "\n", "Oracle AI Agent Memory scopes every record by `user_id` and `agent_id`. Registering them up-front gives the store a stable identity to hang memories on and lets us enforce tenant-style isolation across multiple users.\n", "\n", "> **๐Ÿ“Œ Scoping matters for production.** In a multi-user deployment, `user_id` should match your application's authenticated user. The memory client's `search()` method requires a concrete `user_id` on every call โ€” an intentional guardrail against cross-tenant leaks." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Registered: genome-researcher-1\n", "Registered: deep-research-agent\n" ] } ], "source": [ "USER_ID = \"genome-researcher-1\"\n", "AGENT_ID = \"deep-research-agent\"\n", "\n", "for create_fn, eid, info in [\n", " (memory_client.add_user, USER_ID, \"Genomics researcher exploring human disease associations.\"),\n", " (memory_client.add_agent, AGENT_ID, \"Deep-research agent with web search and long-term memory.\"),\n", "]:\n", " try:\n", " create_fn(eid, info)\n", " print(f\"Registered: {eid}\")\n", " except ValueError:\n", " print(f\"Already exists: {eid}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5. Implement the `Session` protocol on top of Oracle AI Agent Memory\n", "\n", "The OpenAI Agents SDK defines a `Session` protocol with four async methods:\n", "\n", "| Method | Purpose |\n", "|---|---|\n", "| `get_items(limit)` | Return the conversation history the runner should inject |\n", "| `add_items(items)` | Persist new items the runner produced during a run |\n", "| `pop_item()` | Remove and return the most recent item (for corrections) |\n", "| `clear_session()` | Drop everything for this session |\n", "\n", "Implementing this protocol against Oracle AI Agent Memory gives us **exact-resumption** short-term memory โ€” the next time this session runs, the agent receives the full prior conversation without any manual wiring.\n", "\n", "> **๐Ÿ’ก Key insight:** The `Session` protocol handles *short-term* memory (the items the runner replays each turn). Long-term memory (durable facts the agent should remember across sessions) is a separate concern that we handle with `add_memory()` below." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "OracleAgentMemorySession implemented.\n" ] } ], "source": [ "import json\n", "from typing import Optional\n", "from agents.memory.session import SessionABC\n", "\n", "\n", "class OracleAgentMemorySession(SessionABC):\n", " \"\"\"Session backend that persists OpenAI Agents SDK items in Oracle AI Agent Memory.\n", "\n", " Each item is serialised to JSON and stored as a memory record tagged with the\n", " session's thread_id. Ordering is preserved by the store's insertion timestamp.\n", " \"\"\"\n", "\n", " def __init__(self, session_id: str, client: OracleAgentMemory, user_id: str, agent_id: str):\n", " self.session_id = session_id\n", " self._client = client\n", " self._store = client._store\n", " self._user_id = user_id\n", " self._agent_id = agent_id\n", " # Ensure the underlying thread exists so memories can attach to it\n", " try:\n", " self._client.create_thread(\n", " thread_id=session_id, user_id=user_id, agent_id=agent_id,\n", " )\n", " except ValueError:\n", " pass # thread already exists\n", "\n", " async def get_items(self, limit: Optional[int] = None) -> list:\n", " records = self._store.list(\n", " \"memory\",\n", " thread_id=self.session_id,\n", " user_id=self._user_id,\n", " agent_id=self._agent_id,\n", " limit=limit if limit else 10_000,\n", " metadata_filter={\"session_item\": True},\n", " )\n", " items = [json.loads(r.content) for r in records]\n", " return items[-limit:] if limit else items\n", "\n", " async def add_items(self, items: list) -> None:\n", " if not items:\n", " return\n", " for item in items:\n", " self._client.add_memory(\n", " json.dumps(item),\n", " user_id=self._user_id,\n", " agent_id=self._agent_id,\n", " thread_id=self.session_id,\n", " metadata={\"session_item\": True},\n", " )\n", "\n", " async def pop_item(self) -> Optional[dict]:\n", " records = self._store.list(\n", " \"memory\",\n", " thread_id=self.session_id,\n", " user_id=self._user_id,\n", " agent_id=self._agent_id,\n", " limit=1,\n", " metadata_filter={\"session_item\": True},\n", " )\n", " if not records:\n", " return None\n", " # Records come back newest-first when limit=1 is applied; delete and return\n", " last = records[-1]\n", " self._store.delete(\"memory\", last.id)\n", " return json.loads(last.content)\n", "\n", " async def clear_session(self) -> None:\n", " records = self._store.list(\n", " \"memory\",\n", " thread_id=self.session_id,\n", " user_id=self._user_id,\n", " agent_id=self._agent_id,\n", " limit=10_000,\n", " metadata_filter={\"session_item\": True},\n", " )\n", " for r in records:\n", " self._store.delete(\"memory\", r.id)\n", "\n", "\n", "print(\"OracleAgentMemorySession implemented.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 6. Define the agent's tools\n", "\n", "The agent needs three tools:\n", "\n", "1. **`tavily_search`** โ€” live web search for up-to-date genomics sources\n", "2. **`save_research_finding`** โ€” persist a durable research note the agent can recall in future sessions\n", "3. **`recall_research_findings`** โ€” search the long-term memory for prior findings on a topic\n", "\n", "Tools 2 and 3 are how the agent manages its **long-term** memory. They're distinct from the `Session` machinery, which handles short-term conversation history automatically.\n", "\n", "> **๐Ÿ“Œ The `@function_tool` decorator** auto-generates the tool's JSON schema from Python type hints and parses the docstring for the description the LLM sees. Write informative docstrings โ€” the LLM reads them." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tools defined: tavily_search, save_research_finding, recall_research_findings\n" ] } ], "source": [ "from agents import function_tool\n", "from tavily import TavilyClient\n", "\n", "_tavily = TavilyClient(api_key=os.environ[\"TAVILY_API_KEY\"])\n", "\n", "@function_tool\n", "def tavily_search(query: str, max_results: int = 5) -> str:\n", " \"\"\"Search the live web for recent, authoritative genomics sources.\n", "\n", " Use this to pull current information from NCBI, OMIM, peer-reviewed journals,\n", " and other scientific sources. Prefer this over relying on model-internal knowledge\n", " for facts about specific genes, mutations, or recent studies.\n", "\n", " Args:\n", " query: Natural-language search query.\n", " max_results: How many results to return (1-10).\n", " \"\"\"\n", " resp = _tavily.search(\n", " query=query, max_results=max_results,\n", " search_depth=\"advanced\", include_answer=True,\n", " )\n", " lines = [f\"Answer: {resp.get('answer', '')}\"]\n", " for r in resp.get(\"results\", []):\n", " lines.append(f\"- {r['title']} ({r['url']})\\n {r['content'][:300]}\")\n", " return \"\\n\".join(lines)\n", "\n", "\n", "@function_tool\n", "def save_research_finding(topic: str, finding: str) -> str:\n", " \"\"\"Persist a durable research finding the agent should recall in future sessions.\n", "\n", " Use this for claims worth remembering across sessions โ€” e.g. \"BRCA1 mutations\n", " are associated with 45-85% lifetime breast cancer risk in women.\" Do not use\n", " this for conversational acknowledgements or speculation.\n", "\n", " Args:\n", " topic: Short topic tag (e.g. 'BRCA1', 'TP53 mutations').\n", " finding: The finding to remember, ideally one sentence.\n", " \"\"\"\n", " memory_id = memory_client.add_memory(\n", " f\"[{topic}] {finding}\",\n", " user_id=USER_ID,\n", " agent_id=AGENT_ID,\n", " metadata={\"topic\": topic, \"kind\": \"research_finding\"},\n", " )\n", " return f\"Saved finding (id={memory_id}).\"\n", "\n", "\n", "@function_tool\n", "def recall_research_findings(query: str, max_results: int = 5) -> str:\n", " \"\"\"Search prior research findings for information relevant to a query.\n", "\n", " Use this at the start of a research task to check what is already known.\n", " Results are ranked by semantic similarity.\n", "\n", " Args:\n", " query: Natural-language query describing what you want to recall.\n", " max_results: How many findings to return.\n", " \"\"\"\n", " results = memory_client.search(\n", " query, user_id=USER_ID, agent_id=AGENT_ID, max_results=max_results,\n", " )\n", " if not results:\n", " return \"(no prior findings)\"\n", " return \"\\n\".join(\n", " f\"- {r.content} [distance={r.distance:.3f}]\" for r in results\n", " )\n", "\n", "\n", "print(\"Tools defined: tavily_search, save_research_finding, recall_research_findings\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 7. Construct the research agent\n", "\n", "The agent's `instructions` are its system prompt โ€” the place to encode the behaviour you want. For a deep-research agent, the instructions should emphasise:\n", "\n", "1. **Recall before research** โ€” check long-term memory before hitting the web\n", "2. **Cite sources** โ€” so findings are traceable\n", "3. **Save what's worth remembering** โ€” commit durable conclusions explicitly\n", "\n", "> **๐Ÿ’ก Key insight:** A deep-research agent's output quality is largely determined by how well its instructions distinguish *research* (retrieve + synthesise) from *conversation* (respond + acknowledge). Encode that distinction in the system prompt." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Agent created: GenomeDeepResearcher\n" ] } ], "source": [ "from agents import Agent, Runner\n", "\n", "INSTRUCTIONS = \"\"\"You are a deep-research agent specialising in human genome exploration.\n", "\n", "For every research question:\n", "1. FIRST call `recall_research_findings` to check what is already known from prior sessions.\n", "2. If the prior findings are insufficient or outdated, call `tavily_search` for current sources.\n", "3. Synthesise a clear, cited answer. Prefer authoritative sources (NCBI, OMIM, PubMed).\n", "4. Call `save_research_finding` for each durable conclusion worth remembering across sessions.\n", " Save one finding per call; keep findings atomic and one sentence long.\n", "5. Present the final answer to the user with inline citations (URLs).\n", "\n", "Do not save conversational acknowledgements as findings. Only save factual conclusions.\n", "\"\"\"\n", "\n", "research_agent = Agent(\n", " name=\"GenomeDeepResearcher\",\n", " instructions=INSTRUCTIONS,\n", " tools=[tavily_search, save_research_finding, recall_research_findings],\n", " model=\"gpt-5.4\",\n", ")\n", "print(f\"Agent created: {research_agent.name}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 8. Run a research session\n", "\n", "We create a session (tied to a `thread_id` in the memory store) and run the agent over a sequence of research questions. Because we pass `session=session`, the SDK will automatically inject prior conversation items at the start of each turn and persist new items at the end.\n", "\n", "> **๐Ÿ“Œ Separation of concerns.**\n", "> - The `Session` persists the **raw conversation** (working memory).\n", "> - The agent's `save_research_finding` tool persists **durable findings** (long-term memory).\n", "> Both live in the same Oracle database but are accessed through different interfaces." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "======================================================================\n", "Q1: What is BRCA1 and what is its primary function in DNA repair?\n", "======================================================================\n", "BRCA1 is a human **tumor suppressor gene** that encodes a nuclear phosphoprotein involved in maintaining **genomic stability**. It works with other proteins in the cellular response to DNA damage and is best known for its role in hereditary breast and ovarian cancer when mutated ([NCBI Gene](https://www.ncbi.nlm.nih.gov/datasets/gene/672/), [MedlinePlus Genetics](https://medlineplus.gov/genetics/gene/brca1/)).\n", "\n", "Its **primary function in DNA repair** is to help repair **DNA double-strand breaks** through **homologous recombination**, a high-fidelity repair pathway that uses an intact sister chromatid as a template. In short, BRCA1 helps cells repair dangerous DNA breaks accurately rather than leaving them to be repaired by more error-prone mechanisms ([NCBI Gene](https://www.ncbi.nlm.nih.gov/datasets/gene/672/), [MedlinePlus Genetics](https://medlineplus.gov/genetics/gene/brca1/), [PMC review](https://pmc.ncbi.nlm.nih.gov/articles/PMC4382744/)).\n", "\n", "If you want, I can also explain **how BRCA1 differs from BRCA2** in DNA repair.\n", "\n", "======================================================================\n", "Q2: What is the typical lifetime breast cancer risk associated with pathogenic BRCA1 variants?\n", "======================================================================\n", "Women with a **pathogenic BRCA1 variant** have a **substantially elevated lifetime breast cancer risk**, typically estimated at **over 60%**. A commonly cited range is about **55%โ€“65% by age 70โ€“80**, depending on the study and population examined ([NCI BRCA Fact Sheet](https://www.cancer.gov/about-cancer/causes-prevention/genetics/brca-fact-sheet), [NCI PDQ BRCA1/2 summary](https://www.cancer.gov/publications/pdq/information-summaries/genetics/brca-genes-hp-pdq)).\n", "\n", "A concise way to state it is:\n", "\n", "- **Typical lifetime risk:** about **60%โ€“65%**\n", "- **Compared with the general population:** about **13%** lifetime risk for women overall ([NCI BRCA Fact Sheet](https://www.cancer.gov/about-cancer/causes-prevention/genetics/brca-fact-sheet))\n", "\n", "Risk can vary by **specific variant**, **family history**, **ancestry**, and whether the estimate is given **to age 70** or **to age 80**.\n", "\n", "======================================================================\n", "Q3: How does BRCA1 interact with BRCA2 in homologous recombination?\n", "======================================================================\n", "BRCA1 and BRCA2 work in the **same homologous recombination (HR) pathway**, but they act at **different steps**.\n", "\n", "- **BRCA1 acts upstream**: after a DNA double-strand break, BRCA1 helps promote **DNA end resection**, which creates the single-stranded DNA needed for HR. BRCA1 also helps recruit **PALB2**, which serves as a physical and functional bridge to BRCA2 ([PMC review](https://pmc.ncbi.nlm.nih.gov/articles/PMC4382744/), [PMC article on BRCA1-PALB2-BRCA2-RAD51](https://pmc.ncbi.nlm.nih.gov/articles/PMC9481714/)).\n", "- **PALB2 links BRCA1 to BRCA2**: PALB2 binds both proteins and helps localize the **BRCA2 complex** to sites of DNA damage ([PMC 2022 review](https://pmc.ncbi.nlm.nih.gov/articles/PMC9481714/)).\n", "- **BRCA2 acts downstream**: once recruited, BRCA2 helps load **RAD51** onto the single-stranded DNA. RAD51 then forms the nucleoprotein filament that carries out **homology search and strand invasion**, the central catalytic step of HR ([PMC review](https://pmc.ncbi.nlm.nih.gov/articles/PMC4382744/), [BRCA2 and homologous recombination](https://pmc.ncbi.nlm.nih.gov/articles/PMC138691/)).\n", "\n", "So, in simple terms: **BRCA1 helps prepare the break and recruit the repair machinery; BRCA2 helps activate RAD51 to execute the repair** ([PMC review](https://pmc.ncbi.nlm.nih.gov/articles/PMC4382744/), [PMC 2022 review](https://pmc.ncbi.nlm.nih.gov/articles/PMC9481714/)).\n", "\n", "If you'd like, I can turn this into a **step-by-step pathway diagram in words**.\n" ] } ], "source": [ "SESSION_ID = \"genome-session-001\"\n", "session = OracleAgentMemorySession(\n", " session_id=SESSION_ID, \n", " client=memory_client,\n", " user_id=USER_ID, \n", " agent_id=AGENT_ID,\n", ")\n", "\n", "research_questions = [\n", " \"What is BRCA1 and what is its primary function in DNA repair?\",\n", " \"What is the typical lifetime breast cancer risk associated with pathogenic BRCA1 variants?\",\n", " \"How does BRCA1 interact with BRCA2 in homologous recombination?\",\n", "]\n", "\n", "for i, q in enumerate(research_questions, 1):\n", " print(f\"\\n{'=' * 70}\\nQ{i}: {q}\\n{'=' * 70}\")\n", " result = await Runner.run(research_agent, q, session=session)\n", " print(result.final_output)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 9. Inspect what the agent remembered\n", "\n", "At this point the agent has accumulated both short-term conversation items (via the session) and long-term research findings (via `save_research_finding`). Let's inspect both." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Session items: 28\n", " - {'content': 'What is BRCA1 and what is its primary function in DNA repair?', 'role': 'user'}...\n", " - {'arguments': '{\"query\":\"BRCA1 gene primary function in DNA repair\", \"max_results\": 5}', 'call_id': 'call_h7T59GMFF87r0g...\n", " - {'call_id': 'call_h7T59GMFF87r0g2JshWq81nF', 'output': '- {\"content\": \"What is BRCA1 and what is its primary function in...\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/Users/richmondalake/Desktop/projects/OAMP/.venv313/lib/python3.13/site-packages/oracleagentmemory/core/oracleagentmemory.py:698: UserWarning: You are calling an asynchronous method in a synchronous method from an asynchronous context. This is highly discouraged because it can lead to deadlocks. Please use the asynchronous method equivalent: \n", " return run_async_in_sync(self._do_search_async, query, scope, max_results, record_types)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n", "Durable research findings: 10\n", " - [BRCA1] BRCA1 encodes a tumor-suppressor protein that helps maintain genomic stability by coordinating the cellular response to DNA damage. [distance=0.275]\n", " - {\"call_id\": \"call_hpWi8B9FcRzWOF8FZiFcapAh\", \"output\": \"Answer: The BRCA1 gene's primary function is DNA repair via homologous recombination, which helps maintain genomic stability and prevent tumor development. Mutations in BRCA1 lead to impaired DNA repair, increasing cancer risk. BRCA1 also plays a role in transcription regulation and cell signaling.\\n- What is the Role of BRCA1 in Normal Cells? (https://www.news-medical.net/health/What-is-the-Role-of-BRCA1-in-Normal-Cells.aspx)\\n ## DNA repair and recombination\\n\\nThe BRCA1 protein is an E3 uniquitin-protein ligase that regulates the creation of Lys-6-linked polyubiquitin chains and makes an important contribution toward DNA repair by enabling cells to respond to DNA damage.\\n\\nThis maintenance of the DNA is a crucial part of BR\\n- BRCA1 DNA repair associated (https://www.ncbi.nlm.nih.gov/datasets/gene/672/)\\n This gene encodes a 190 kD nuclear phosphoprotein that plays a role in maintaining genomic stability, and it also acts as a tumor suppressor. The BRCA1 gene contains 22 exons spanning about 110 kb of DNA. The encoded protein combines with other tumor suppressors, DNA damage sensors, and signal trans\\n- The Roles of BRCA1, BRCA2, and Associated Proteins - PMC - NIH (https://pmc.ncbi.nlm.nih.gov/articles/PMC4382744/)\\n BRCA1 functions independently of homologous recombination in DNA interstrand crosslink repair. Mol Cell 46: 125\\u2013135. [DOI] [PMC free article] [PubMed]\\n- BRCA1 gene: MedlinePlus Genetics (https://medlineplus.gov/genetics/gene/brca1/)\\n The BRCA1 protein is involved in repairing damaged DNA. In the nucleus of many types of normal cells, the BRCA1 protein interacts with several other proteins to mend breaks in DNA. These breaks can be caused by natural and medical radiation or other environmental exposures, and they also occur when \\n- BRCA1 Functions Independently of Homologous Recombination in DNA Interstrand Crosslink Repair - ScienceDirect (https://www.sciencedirect.com/science/article/pii/S1097276512001748)\\n Elsevier logo\\nMolecular Cell\\n\\n## Molecular Cell\\n\\nSociety Logo\\n\\n# Article BRCA1 Functions Independently of Homologous Recombination in DNA Interstrand Crosslink Repair\\n\\n## Summary\\n\\n### Graphical Abstract\\n\\n### Highlights\\n\\n## Cited by (0)\\n\\n## Recommended articles\\n\\nElsevier logo with wordmark\\n\\nAll conte\", \"type\": \"function_call_output\"} [distance=0.291]\n", " - [BRCA1 DNA repair] BRCA1โ€™s primary DNA repair role is to promote accurate repair of DNA double-strand breaks through homologous recombination. [distance=0.313]\n", " - {\"call_id\": \"call_xXv8AB7VcBC9lREKo60oz7SR\", \"output\": \"Answer: Women with a BRCA1 pathogenic variant have up to a 65% lifetime risk of breast cancer and a 40-45% risk of ovarian cancer. These risks are higher than those in the general population.\\n- BRCA1 and BRCA2 (PDQ\\u00ae) - NCI (https://www.cancer.gov/publications/pdq/information-summaries/genetics/brca-genes-hp-pdq)\\n risk of 0.5% by age 70 years in the general population. A large, single-institution study of more than 1,000 carriers of pathogenic variants found a 21-fold increased risk of pancreatic cancer among _BRCA2_ carriers and a 4.7-fold increased risk among carriers of _BRCA1_ pathogenic variants, compare\\n- BRCA Gene Changes: Cancer Risk and Genetic Testing Fact Sheet (https://www.cancer.gov/about-cancer/causes-prevention/genetics/brca-fact-sheet)\\n Female breast cancer:More than 60% of women who inherit a harmful change in _BRCA1_ or _BRCA2_ will develop breast cancer during their lifetime (2). By contrast, about 13% of women in the general population will develop breast cancer during their lifetime. [...] Among women who have been diagnosed w\\n- BRCA1 Gene Mutation Risk Test | Myriad Genetics (https://myriad.com/gene-results/BRCA1/1/)\\n - Yadav S, et al. Contralateral Breast Cancer Risk Among Carriers of Germline Pathogenic Variants in ATM, BRCA1, BRCA2, CHEK2, and PALB2. J Clin Oncol. 2023 Mar 20;41(9):1703-1713. PMID: 36623243.\\n\\n- Engel C, et al. Breast cancer risk in BRCA1/2 mutation carriers and noncarriers under prospective in\\n- BRCA1 \\u2013 Inherited Cancer Registry (ICARE) (https://inheritedcancer.net/gene/brca1/)\\n #### Reduced Penetrance BRCA1/2 Pathogenic Variants\\n\\nCheck out our recently published study that brings attention to \\u201creduced penetrance\\u201d BRCA1 and BRCA2 (BRCA) pathogenic variants, which impart LOWER breast cancer risks than \\u2018typical\\u2019 BRCA mutations. Specifically, lifetime breast cancer risks for t\\n- What Is BRCA1? About the BRCA1 Mutation and More | BCRF (https://www.bcrf.org/about-breast-cancer/brca1/)\\n PARP inhibitors, antibody-drug conjugates, and immunotherapies are just a few examples of how BCRF investigators are seeking to improve treatment options and breast cancer management for BRCA1 mutation carriers. Leading research into BRCA1 pathogenic mutations and TNBC from so many angles, our inves\", \"type\": \"function_call_output\"} [distance=0.321]\n", " - [BRCA1 breast cancer risk] Women with a pathogenic BRCA1 variant have a lifetime breast cancer risk typically estimated at over 60%, with many sources citing about 55% to 65% by age 70 to 80. [distance=0.329]\n", " - [BRCA2 RAD51] BRCA2 functions downstream of BRCA1 in homologous recombination by loading RAD51 onto single-stranded DNA to enable homology search and strand invasion. [distance=0.344]\n", " - {\"call_id\": \"call_Udh8KmLhLfP6NbrrvVcPIYLL\", \"output\": \"Answer: BRCA1 interacts with BRCA2 and RAD51 to facilitate homologous recombination repair. PALB2 assists BRCA2 in recruiting RAD51. Mutations in BRCA1, BRCA2, or PALB2 disrupt DNA repair, increasing cancer risk.\\n- BRCA1-dependent and independent recruitment of PALB2-BRCA2-RAD51 in the DNA damage response and cancer - PMC (https://pmc.ncbi.nlm.nih.gov/articles/PMC9481714/)\\n The BRCA1-PALB2-BRCA2 axis plays essential roles in the cellular response to DNA double strand breaks (DSB), maintenance of genome integrity, and suppression of cancer development. Upon DNA damage, BRCA1 is recruited to DSBs, where it facilitates end resection and recruits PALB2 and its associated B\\n- Compromised BRCA1-PALB2 interaction is associated with breast cancer risk - PMC (https://pmc.ncbi.nlm.nih.gov/articles/PMC5519427/)\\n to be hypomorphic as the protein was able to support RAD51 foci formation but the foci were evidently smaller and also modestly fewer in number (Fig. 3c). Normal RAD51 foci formation was observed in cells expressing PALB2-K18R and R37H (data not shown). These observations demonstrate the important r\\n- Homologous Recombination and Human Health: The Roles of BRCA1, BRCA2, and Associated Proteins - PMC (https://pmc.ncbi.nlm.nih.gov/articles/PMC4382744/)\\n Homologous recombination (HR) is a major pathway for the repair of DNA double-strand breaks in mammalian cells, the defining step of which is homologous strand exchange directed by the RAD51 protein. The physiological importance of HR is underscored by the observation of genomic instability in HR-de\\n- BRCA2 and homologous recombination - PMC (https://pmc.ncbi.nlm.nih.gov/articles/PMC138691/)\\n Following the landmark discovery by Scully et al that the homologous recombinase RAD51 colocalizes at subnuclear sites with BRCA1 , a number of additional results have provided evidence that both BRCA1 and BRCA2 are involved in recombinational repair of DNA damage. BRCA1 and BRCA2 form discrete nucl\\n- Reviewing the characteristics of BRCA and PALB2-related cancers in the precision medicine era - PMC (https://pmc.ncbi.nlm.nih.gov/articles/PMC6687356/)\\n Keywords: BRCA1, BRCA2, homologous recombination, cancer predisposition, PARP inhibitors\\n\\n## BRCA1, BRCA2 and PALB2 genes: mutations and associated phenotypes [...] breaks and BRCA deficiency. Lower expression of RAD51 and\\nBARD1, two key components of DNA damage repair by HR, were also found in BRCA\", \"type\": \"function_call_output\"} [distance=0.347]\n", " - [BRCA1 BRCA2 homologous recombination] In homologous recombination, BRCA1 acts upstream of BRCA2 by promoting DNA end resection and helping recruit the PALB2-BRCA2 complex to DNA double-strand breaks. [distance=0.354]\n", " - {\"content\": \"What is BRCA1 and what is its primary function in DNA repair?\", \"role\": \"user\"} [distance=0.365]\n", " - {\"call_id\": \"call_w552NP5FljYZ7P5dHhYiijrJ\", \"output\": \"- {\\\"content\\\": \\\"What is the typical lifetime breast cancer risk associated with pathogenic BRCA1 variants?\\\", \\\"role\\\": \\\"user\\\"} [distance=0.241]\\n- {\\\"call_id\\\": \\\"call_hpWi8B9FcRzWOF8FZiFcapAh\\\", \\\"output\\\": \\\"Answer: The BRCA1 gene's primary function is DNA repair via homologous recombination, which helps maintain genomic stability and prevent tumor development. Mutations in BRCA1 lead to impaired DNA repair, increasing cancer risk. BRCA1 also plays a role in transcription regulation and cell signaling.\\\\n- What is the Role of BRCA1 in Normal Cells? (https://www.news-medical.net/health/What-is-the-Role-of-BRCA1-in-Normal-Cells.aspx)\\\\n ## DNA repair and recombination\\\\n\\\\nThe BRCA1 protein is an E3 uniquitin-protein ligase that regulates the creation of Lys-6-linked polyubiquitin chains and makes an important contribution toward DNA repair by enabling cells to respond to DNA damage.\\\\n\\\\nThis maintenance of the DNA is a crucial part of BR\\\\n- BRCA1 DNA repair associated (https://www.ncbi.nlm.nih.gov/datasets/gene/672/)\\\\n This gene encodes a 190 kD nuclear phosphoprotein that plays a role in maintaining genomic stability, and it also acts as a tumor suppressor. The BRCA1 gene contains 22 exons spanning about 110 kb of DNA. The encoded protein combines with other tumor suppressors, DNA damage sensors, and signal trans\\\\n- The Roles of BRCA1, BRCA2, and Associated Proteins - PMC - NIH (https://pmc.ncbi.nlm.nih.gov/articles/PMC4382744/)\\\\n BRCA1 functions independently of homologous recombination in DNA interstrand crosslink repair. Mol Cell 46: 125\\\\u2013135. [DOI] [PMC free article] [PubMed]\\\\n- BRCA1 gene: MedlinePlus Genetics (https://medlineplus.gov/genetics/gene/brca1/)\\\\n The BRCA1 protein is involved in repairing damaged DNA. In the nucleus of many types of normal cells, the BRCA1 protein interacts with several other proteins to mend breaks in DNA. These breaks can be caused by natural and medical radiation or other environmental exposures, and they also occur when \\\\n- BRCA1 Functions Independently of Homologous Recombination in DNA Interstrand Crosslink Repair - ScienceDirect (https://www.sciencedirect.com/science/article/pii/S1097276512001748)\\\\n Elsevier logo\\\\nMolecular Cell\\\\n\\\\n## Molecular Cell\\\\n\\\\nSociety Logo\\\\n\\\\n# Article BRCA1 Functions Independently of Homologous Recombination in DNA Interstrand Crosslink Repair\\\\n\\\\n## Summary\\\\n\\\\n### Graphical Abstract\\\\n\\\\n### Highlights\\\\n\\\\n## Cited by (0)\\\\n\\\\n## Recommended articles\\\\n\\\\nElsevier logo with wordmark\\\\n\\\\nAll conte\\\", \\\"type\\\": \\\"function_call_output\\\"} [distance=0.481]\\n- [BRCA1] BRCA1 encodes a tumor-suppressor protein that helps maintain genomic stability by coordinating the cellular response to DNA damage. [distance=0.503]\\n- {\\\"id\\\": \\\"msg_0e48048923170fb70069f3b455b304819480ab9e70a1b372e7\\\", \\\"content\\\": [{\\\"annotations\\\": [], \\\"text\\\": \\\"BRCA1 is a human **tumor suppressor gene** that encodes a nuclear phosphoprotein involved in maintaining **genomic stability**. It works with other proteins in the cellular response to DNA damage and is best known for its role in hereditary breast and ovarian cancer when mutated ([NCBI Gene](https://www.ncbi.nlm.nih.gov/datasets/gene/672/), [MedlinePlus Genetics](https://medlineplus.gov/genetics/gene/brca1/)).\\\\n\\\\nIts **primary function in DNA repair** is to help repair **DNA double-strand breaks** through **homologous recombination**, a high-fidelity repair pathway that uses an intact sister chromatid as a template. In short, BRCA1 helps cells repair dangerous DNA breaks accurately rather than leaving them to be repaired by more error-prone mechanisms ([NCBI Gene](https://www.ncbi.nlm.nih.gov/datasets/gene/672/), [MedlinePlus Genetics](https://medlineplus.gov/genetics/gene/brca1/), [PMC review](https://pmc.ncbi.nlm.nih.gov/articles/PMC4382744/)).\\\\n\\\\nIf you want, I can also explain **how BRCA1 differs from BRCA2** in DNA repair.\\\", \\\"type\\\": \\\"output_text\\\", \\\"logprobs\\\": []}], \\\"role\\\": \\\"assistant\\\", \\\"status\\\": \\\"completed\\\", \\\"type\\\": \\\"message\\\", \\\"phase\\\": \\\"final_answer\\\"} [distance=0.521]\\n- [BRCA1 DNA repair] BRCA1\\u2019s primary DNA repair role is to promote accurate repair of DNA double-strand breaks through homologous recombination. [distance=0.539]\\n- {\\\"content\\\": \\\"What is BRCA1 and what is its primary function in DNA repair?\\\", \\\"role\\\": \\\"user\\\"} [distance=0.546]\\n- {\\\"arguments\\\": \\\"{\\\\\\\"query\\\\\\\":\\\\\\\"BRCA1 gene primary function in DNA repair\\\\\\\", \\\\\\\"max_results\\\\\\\": 5}\\\", \\\"call_id\\\": \\\"call_h7T59GMFF87r0g2JshWq81nF\\\", \\\"name\\\": \\\"recall_research_findings\\\", \\\"type\\\": \\\"function_call\\\", \\\"id\\\": \\\"fc_0e48048923170fb70069f3b447e48081949dc9cd90426de6d4\\\", \\\"status\\\": \\\"completed\\\"} [distance=0.611]\\n- {\\\"call_id\\\": \\\"call_h7T59GMFF87r0g2JshWq81nF\\\", \\\"output\\\": \\\"- {\\\\\\\"content\\\\\\\": \\\\\\\"What is BRCA1 and what is its primary function in DNA repair?\\\\\\\", \\\\\\\"role\\\\\\\": \\\\\\\"user\\\\\\\"} [distance=0.316]\\\", \\\"type\\\": \\\"function_call_output\\\"} [distance=0.622]\\n- {\\\"arguments\\\": \\\"{\\\\\\\"topic\\\\\\\":\\\\\\\"BRCA1\\\\\\\",\\\\\\\"finding\\\\\\\":\\\\\\\"BRCA1 encodes a tumor-suppressor protein that helps maintain genomic stability by coordinating the cellular response to DNA damage.\\\\\\\"}\\\", \\\"call_id\\\": \\\"call_nUIlN62wBbxWktdLCjvXhWbW\\\", \\\"name\\\": \\\"save_research_finding\\\", \\\"type\\\": \\\"function_call\\\", \\\"id\\\": \\\"fc_0e48048923170fb70069f3b452d3008194985be6128b22ea4c\\\", \\\"status\\\": \\\"completed\\\"} [distance=0.630]\\n- {\\\"arguments\\\": \\\"{\\\\\\\"topic\\\\\\\":\\\\\\\"BRCA1 DNA repair\\\\\\\",\\\\\\\"finding\\\\\\\":\\\\\\\"BRCA1\\\\u2019s primary DNA repair role is to promote accurate repair of DNA double-strand breaks through homologous recombination.\\\\\\\"}\\\", \\\"call_id\\\": \\\"call_Zx3ZgxZ8UhJnjaFSHX1WAhzv\\\", \\\"name\\\": \\\"save_research_finding\\\", \\\"type\\\": \\\"function_call\\\", \\\"id\\\": \\\"fc_0e48048923170fb70069f3b452d30c819485e7db6c46558413\\\", \\\"status\\\": \\\"completed\\\"} [distance=0.640]\", \"type\": \"function_call_output\"} [distance=0.396]\n" ] } ], "source": [ "# Short-term: conversation items replayed each turn\n", "session_items = await session.get_items()\n", "print(f\"Session items: {len(session_items)}\")\n", "for it in session_items[:3]:\n", " print(f\" - {str(it)[:120]}...\")\n", "\n", "# Long-term: durable findings the agent chose to save\n", "findings = memory_client.search(\n", " \"BRCA1 function and risk\", user_id=USER_ID, agent_id=AGENT_ID, max_results=10,\n", ")\n", "print(f\"\\nDurable research findings: {len(findings)}\")\n", "for r in findings:\n", " print(f\" - {r.content} [distance={r.distance:.3f}]\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 10. Verify continuity โ€” resume a fresh session with the same memory store\n", "\n", "The real test of a memory-aware agent is whether it can pick up where a prior session left off. Let's create a *new* session (simulating a separate process or later day) and ask a question that builds on prior findings.\n", "\n", "If the agent recalls BRCA1 findings from the previous run without re-searching, we've demonstrated end-to-end memory continuity." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "FRESH SESSION โ€” Q: Based on what you already know about BRCA1, explain how a patient with a pathogenic BRCA1 variant might be counselled about screening.\n", "\n", "A patient with a **pathogenic BRCA1 variant** would usually be counselled that screening needs to start **earlier and be more intensive** than for the general population, because BRCA1 is associated with a markedly increased lifetime risk of **breast cancer** and a substantial risk of **ovarian cancer** ([NCI BRCA fact sheet](https://www.cancer.gov/about-cancer/causes-prevention/genetics/brca-fact-sheet), [NCI PDQ](https://www.cancer.gov/publications/pdq/information-summaries/genetics/brca-genes-hp-pdq)).\n", "\n", "### Breast screening\n", "Counselling would typically include:\n", "\n", "- **Annual breast MRI starting around age 25**\n", "- **Annual mammography added at age 30**\n", "- Ongoing **clinical breast awareness** and prompt assessment of any new breast symptoms\n", "\n", "This approach is used because MRI is more sensitive in younger high-risk women, and current high-risk guidance for BRCA1/2 carriers supports annual MRI first, then combined MRI plus mammography from age 30 onward ([NCCN patient guidelines](https://www.nccn.org/patients/guidelines/content/PDF/genetics-patient.pdf), [DenseBreast-info summary of NCCN-based guidance](https://densebreast-info.org/providers-faqs/what-is-the-screening-management-for-various-other-mutation-carriers/)).\n", "\n", "You could explain it to a patient in plain language like this: \n", "**โ€œBecause your BRCA1 variant raises your breast cancer risk, we recommend screening that starts younger and uses MRI every year, with mammograms added later, to improve the chance of finding cancer early.โ€**\n", "\n", "### Ovarian cancer screening\n", "Counselling should also make clear that **ovarian cancer screening is much less effective** than breast screening. Unlike breast MRI, there is **no screening strategy proven to reliably detect ovarian cancer early enough to prevent deaths** in BRCA1 carriers. Therefore, patients are often told that screening with tests such as **transvaginal ultrasound or CA-125** is not a dependable substitute for prevention ([NCI PDQ](https://www.cancer.gov/publications/pdq/information-summaries/genetics/brca-genes-hp-pdq), [NCI BRCA fact sheet](https://www.cancer.gov/about-cancer/causes-prevention/genetics/brca-fact-sheet)).\n", "\n", "So counselling usually shifts toward **risk-reducing salpingo-oophorectomy** after childbearing is complete, rather than relying on screening alone ([NCCN patient guidelines](https://www.nccn.org/patients/guidelines/content/PDF/genetics-patient.pdf)).\n", "\n", "### Framing the counselling discussion\n", "A good counselling conversation would usually emphasize that:\n", "\n", "- **Screening reduces risk of late detection; it does not prevent cancer**\n", "- **Breast screening is effective enough to be a core part of management**\n", "- **Ovarian screening is limited**, so prevention strategies are often discussed earlier\n", "- The exact plan depends on **age, prior cancers, family history, reproductive plans, and whether risk-reducing surgery is being considered**\n", "\n", "### Reassurance and shared decision-making\n", "It is also reasonable to reassure the patient that there is evidence that following recommended BRCA-focused surveillance and preventive strategies is associated with **better outcomes**, including lower mortality in recent large studies highlighted by NCI ([NCI Cancer Currents, 2024](https://www.cancer.gov/news-events/cancer-currents-blog/2024/brca-breast-ovarian-cancer-mri-surgery-fewer-deaths)).\n", "\n", "In short, a patient with a pathogenic **BRCA1** variant would generally be counselled that:\n", "\n", "- **Breast screening starts early and includes annual MRI**\n", "- **Mammography is added from age 30**\n", "- **Ovarian screening is limited**\n", "- **Risk-reducing surgery is often part of the discussion**, especially for ovarian cancer risk\n", "\n", "If you want, I can also turn this into a **short clinic-style counselling script** or a **patient-friendly explanation**.\n" ] } ], "source": [ "# Simulate a fresh session (new session_id, but same user/agent)\n", "FRESH_SESSION_ID = \"genome-session-002\"\n", "fresh_session = OracleAgentMemorySession(\n", " session_id=FRESH_SESSION_ID, client=memory_client,\n", " user_id=USER_ID, agent_id=AGENT_ID,\n", ")\n", "\n", "followup = \"Based on what you already know about BRCA1, explain how a patient with a pathogenic BRCA1 variant might be counselled about screening.\"\n", "\n", "print(f\"FRESH SESSION โ€” Q: {followup}\\n\")\n", "result = await Runner.run(research_agent, followup, session=fresh_session)\n", "print(result.final_output)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 11. Cleanup (optional)\n", "\n", "Uncomment the cell below to clear all session items and findings for this example. Leave it commented to keep the data for subsequent runs โ€” that's often the point." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Connection closed.\n" ] } ], "source": [ "# await session.clear_session()\n", "# await fresh_session.clear_session()\n", "# for r in memory_client.search(\"BRCA\", user_id=USER_ID, agent_id=AGENT_ID, max_results=100):\n", "# memory_client.delete_memory(r.record.id)\n", "# print(\"Cleaned up.\")\n", "\n", "connection.close()\n", "print(\"Connection closed.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Key Takeaways\n", "\n", "> **๐ŸŽฏ 1. The `Session` protocol is the clean integration point.** Four async methods (`get_items`, `add_items`, `pop_item`, `clear_session`) is all the OpenAI Agents SDK needs to plug a custom memory backend in. You don't have to modify the runner โ€” you implement the protocol and pass an instance via `session=`.\n", "\n", "> **๐ŸŽฏ 2. Separate short-term and long-term memory concerns.** The session handles conversation replay for the current agent loop. Durable findings (the ones worth recalling in a future session) should be written through tools the agent calls deliberately, not dumped into the conversation log.\n", "\n", "> **๐ŸŽฏ 3. Instructions steer memory usage.** A deep-research agent must be explicitly told to *recall before researching* and *save durable conclusions*. Otherwise the LLM will treat memory as optional decoration and the store will fill up with nothing useful.\n", "\n", "> **๐ŸŽฏ 4. Oracle AI Database gives you one substrate for both tiers.** Short-term items, long-term findings, and any structured business data the agent needs to reference all live in one governed backend โ€” one pool, one backup, one compliance review.\n", "\n", "> **๐ŸŽฏ 5. Continuity is testable.** A new `session_id` with the same `user_id` / `agent_id` should produce an agent that reasons over prior long-term findings. That's the simplest end-to-end test of a memory-aware agent." ] } ], "metadata": { "kernelspec": { "display_name": ".venv313 (3.13.9)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.9" } }, "nbformat": 4, "nbformat_minor": 5 }