4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OpenAI Agents SDK その1 Memory

Last updated at Posted at 2025-10-25

自分の学びのために、小さなブログを書くことにしました。Open AI Agents SDK を理解してみようと思います。
初回は、Memory の機能に関して、書いてみます。今回はデフォルトの短期記憶の Session について記載しますが、次回は、長期記憶のサンプルを書いてみたいと思います。

Memory のフィーチャー

Agent で使えるメモリのフィーチャーは基本的に、長期記憶用ではなくて、短期のヒストリ用です。セッション履歴を保持します。一応公式ドキュメントはあるのですが、どっちかというと、公式のリポジトリのサンプルや、本体のコードから理解するほうがよさげです。(AIも古いサンプルを返しました)

他にも、ここで示した、インメモリの実装の他にも sqliteの実装がありますが、インターフェイスは単純なので、自分で実装できそうです。Sessionsを観ると定義が分かります。

class SessionABC(ABC):
    """Abstract base class for session implementations.

    Session stores conversation history for a specific session, allowing
    agents to maintain context without requiring explicit manual memory management.

    This ABC is intended for internal use and as a base class for concrete implementations.
    Third-party libraries should implement the Session protocol instead.
    """

    session_id: str

    @abstractmethod
    async def get_items(self, limit: int | None = None) -> list[TResponseInputItem]:
        """Retrieve the conversation history for this session.

        Args:
            limit: Maximum number of items to retrieve. If None, retrieves all items.
                   When specified, returns the latest N items in chronological order.

        Returns:
            List of input items representing the conversation history
        """
        ...

    @abstractmethod
    async def add_items(self, items: list[TResponseInputItem]) -> None:
        """Add new items to the conversation history.

        Args:
            items: List of input items to add to the history
        """
        ...

    @abstractmethod
    async def pop_item(self) -> TResponseInputItem | None:
        """Remove and return the most recent item from the session.

        Returns:
            The most recent item if it exists, None if the session is empty
        """
        ...

    @abstractmethod
    async def clear_session(self) -> None:
        """Clear all items for this session."""
        ...

この実装をどのように使うかというと、とても単純で

session = OpenAIConversationsSession()
agent = Agent(
    name="Assistant",
    instructions="Reply very concisely."
)
        result = await Runner.run(
            agent,
            user_input,
            session=session
        )

サンプル

もちろん先ほど示したメソッドを示すこともできます。一つ単純なサンプルを書いてみます。

app.py
import asyncio
from dotenv import load_dotenv
from agents import Agent, OpenAIConversationsSession, Runner

load_dotenv()
session = OpenAIConversationsSession()
agent = Agent(
    name="Assistant",
    instructions="Reply very concisely."
)

async def main():
    print("=== Simple ChatBot with Agent SDK Memory ===")
    print("type 'exit' to quit\n")

    while True:
        user_input=input("You: ")
        if user_input.lower() in ["exit", "quit"]:
            break

        if user_input.lower() in ["clear"]:
            session.clear_session()
            print("Chat history cleared.")
            continue
        
        result = await Runner.run(
            agent,
            user_input,
            session=session
        )
        print("Bot:", result.final_output)

        # Display session contents with color
        print("\n\033[36m" + "="*50)  # Cyan color
        print("Session Contents:")
        print("="*50)
        for idx, message in enumerate(await session.get_items(), 1):
            role = message.get('role', 'unknown')
            content = message.get('content', '')
            print(f"{idx}. [{role.upper()}]: {content}")
        print("="*50 + "\033[0m\n")  # Reset color
        

if __name__ == "__main__":
    asyncio.run(main())

実行したらヒストリが蓄積されているのが分かります。

実行結果
You: リトルウォルターはいつ生まれたのかと、代表曲を教えてください。
Bot: リトル・ウォルター(Little Walter)は、193051日生まれです。

代表曲:
- "Juke"
- "My Babe"
- "Mean Old World"
- "Blues with a Feeling"

==================================================
Session Contents:
==================================================
1. [USER]: [{'text': 'Deep Blues のアーティストを教えてください', 'type': 'input_text'}]
2. [ASSISTANT]: [{'annotations': [], 'text': 'Deep Blues のアーティストは、Cornelius(小山田圭吾)です。', 'type': 'output_text', 'logprobs': []}]
3. [USER]: [{'text': 'それではなくDelta blues や Deep な Chicago Blues のアーティストです', 'type': 'input_text'}]
4. [ASSISTANT]: [{'annotations': [], 'text': '代表的なDelta bluesアーティスト:\n- ロバート・ジョンソン (Robert Johnson)\n- サン・ハウス (Son House)\n- チャーリー・パットン (Charley Patton)\n- ミシシッピ・ジョン・ハート (Mississippi John Hurt)\n\n代表的なDeepなChicago Bluesアーティスト:\n- マディ・ウォーターズ (Muddy Waters)\n- ハウリン・ウルフ (Howlin’ Wolf)\n- オーティス・ラッシュ (Otis Rush)\n- バディ・ガイ (Buddy Guy)', 'type': 'output_text', 'logprobs': []}]
5. [USER]: [{'text': '代表的なハーププレイヤーを教えてください。', 'type': 'input_text'}]
6. [ASSISTANT]: [{'annotations': [], 'text': '代表的なブルース・ハープ(ハーモニカ)プレイヤー:\n\n- リトル・ウォルター (Little Walter)\n- ソニー・ボーイ・ウィリアムソン II (Sonny Boy Williamson II)\n- ジュニア・ウェルズ (Junior Wells)\n- ジェイムズ・コットン (James Cotton)\n- ビッグ・ウォルター・ホートン (Big Walter Horton)\n- ソニー・テリー (Sonny Terry)', 'type': 'output_text', 'logprobs': []}]
7. [USER]: [{'text': 'リトルウォルターはいつ生まれたのかと、代表曲を教えてください。', 'type': 'input_text'}]
8. [ASSISTANT]: [{'annotations': [], 'text': 'リトル・ウォルター(Little Walter)は、1930年5月1日生まれです。\n\n代表曲:\n- "Juke"\n- "My Babe"\n- "Mean Old World"\n- "Blues with a Feeling"', 'type': 'output_text', 'logprobs': []}]
==================================================

ヒストリの制限

簡単な例として、ヒストリを制限できないでしょうか?永遠とヒストリをキープしていると、LLMが混乱しますので、例えば、ラスト10のヒストリを有効にするとか、きっとオプションで…できなそう。

このようなケースでは、自分で実装すれば良さげです。

limited_session.py
from __future__ import annotations

from typing import Any, Dict, List

from agents import OpenAIConversationsSession

MAX_HISTORY_ITEMS = 10


class LimitedOpenAIConversationsSession(OpenAIConversationsSession):
    """Session wrapper that scopes retrieved history to the latest N items."""

    def __init__(self, *, max_history_items: int = MAX_HISTORY_ITEMS, **kwargs: Any) -> None:
        super().__init__(**kwargs)
        if max_history_items <= 0:
            raise ValueError("max_history_items must be a positive integer")
        self._max_history_items = max_history_items

    @property
    def max_history_items(self) -> int:
        return self._max_history_items

    async def get_items(self, limit: int | None = None) -> List[Dict[str, Any]]:
        """Return at most `max_history_items` conversation items in chronological order."""
        effective_limit = self._max_history_items if limit is None else min(limit, self._max_history_items)
        return await super().get_items(limit=effective_limit)

先ほどのサンプルを変更して、ヒストリの保持を3にしています。

app.py
import asyncio
from dotenv import load_dotenv
from agents import Agent, Runner

from limited_session import (
    LimitedOpenAIConversationsSession,
)

load_dotenv()
session = LimitedOpenAIConversationsSession(max_history_items=3)
agent = Agent(
    name="Assistant",
    instructions="Reply very concisely."
)

async def main():
    print("=== Simple ChatBot with Agent SDK Memory ===")
    print("type 'exit' to quit\n")

    while True:
        user_input=input("You: ")
        if user_input.lower() in ["exit", "quit"]:
            break

        if user_input.lower() in ["clear"]:
            session.clear_session()
            print("Chat history cleared.")
            continue
        
        result = await Runner.run(
            agent,
            user_input,
            session=session
        )
        print("Bot:", result.final_output)

        # Display session contents with color
        print("\n\033[36m" + "="*50)  # Cyan color
        print("Session Contents:")
        print("="*50)
        for idx, message in enumerate(await session.get_items(), 1):
            role = message.get('role', 'unknown')
            content = message.get('content', '')
            print(f"{idx}. [{role.upper()}]: {content}")
        print("="*50 + "\033[0m\n")  # Reset color
        

if __name__ == "__main__":
    asyncio.run(main())

実行したらしっかり鳥のように忘れていますね。

実行結果
(simple-chatbot) PS C:\repo\learning\memory\scoped-history-simple-chatbot> python app.py
=== Simple ChatBot with Agent SDK Memory ===
type 'exit' to quit

You: Deep Blues のアーティストについて教えてください。
Bot: Deep Blues」は、複数のアーティストやバンドによるアルバム・プロジェクト名や曲名として使われていますが、有名な例としては「Deep Blues: Original Motion Picture Soundtrack」があります。これは1991年の同名ドキュメンタリー映画のサウンドトラックで、Junior KimbroughR.L. BurnsideBig Jack JohnsonRoosevelt Barnes など、ミシシッピ・ブルースの名アーティストが参加しています。詳しいアーティスト名を指定していただければ、より深くお調べします。

==================================================
Session Contents:
==================================================
1. [USER]: [{'text': 'Deep Blues のアーティストについて教えてください。', 'type': 'input_text'}]
2. [ASSISTANT]: [{'annotations': [], 'text': '「Deep Blues」は、複数のアーティストやバンドによるアルバム・プロジェクト名や曲名として使われていますが、有名な例としては「Deep Blues: Original Motion Picture Soundtrack」があります。これは1991年の同名ドキュメンタリー映画のサウンドトラックで、Junior Kimbrough、R.L. Burnside、Big Jack Johnson、Roosevelt Barnes など、ミシシッピ・ブルースの名アーティストが参加しています。詳しいアーティスト名を指定していただければ、より深くお調べします。', 'type': 'output_text', 'logprobs': []}]
==================================================

You: R.L. Burnside について詳しく教えてください
Bot: R.L. BurnsideRural L. Burnside19261123 - 200591日)は、アメリカ合衆国ミシシッピ州出身のブルース・ミュージシャンです。ノース・ミシシッピ・ヒル・カントリー・ブルースの代表的存在で、粗削りなギターとディープなグルーヴが特徴です。1990年代にFat Possum Recordsからのアルバムリリースで再評価され、「It's Bad You Know」や「Let My Baby Ride」などが人気。ロック・ヒップホップともコラボし、ブルース・リバイバルの立役者となりました。

==================================================
Session Contents:
==================================================
1. [ASSISTANT]: [{'annotations': [], 'text': 'Deep Blues」は、複数のアーティストやバンドによるアルバム・プロジェクト名や曲名として使われていますが、有名な例としては「Deep Blues: Original Motion Picture Soundtrack」があります。これは1991年の同名ドキュメンタリー映画のサウンドトラックで、Junior KimbroughR.L. BurnsideBig Jack JohnsonRoosevelt Barnes など、ミシシッピ・ブルースの名アーティストが参加しています。詳しいアーティスト名を指定していただければ、より深くお調べします。', 'type': 'output_text', 'logprobs': []}]
2. [USER]: [{'text': 'R.L. Burnside について詳しく教えてください', 'type': 'input_text'}]
3. [ASSISTANT]: [{'annotations': [], 'text': "R.L. Burnside(Rural L. Burnside、1926年11月23日 - 2005年9月1日)は、アメリカ合衆国ミシシッピ州出身のブルース・ミュージシャンです。ノース・ミシシッピ・ヒル・カントリー・ブルースの代表的存在で、粗削りなギターとディープなグルーヴが特徴です。1990年代にFat Possum Recordsからのアルバムリリースで再評価され、「It's Bad You Know」や「Let My Baby Ride」などが人気。ロック・ヒップホップともコラボし、ブルース・リバイバルの立役者となりました。", 'type': 'output_text', 'logprobs': []}]
==================================================

You: 子供はいますか?
Bot: はい、R.L. Burnsideには複数の子供がいます。なかでも息子のCedric Burnside(セドリック・バーンサイド)はドラマーおよびブルース・ミュージシャンとして有名です。CedricはR.L.と一緒に演奏し、現在も活躍しています。

==================================================
Session Contents:
==================================================
1. [ASSISTANT]: [{'annotations': [], 'text': "R.L. BurnsideRural L. Burnside19261123 - 200591日)は、アメリカ合衆国ミシシッピ州出身のブルース・ミュージシャンです。ノース・ミシシッピ・ヒル・カントリー・ブルースの代表的存在で、粗削りなギターとディープなグルーヴが特徴です。1990年代にFat Possum Recordsからのアルバムリリースで再評価され、「It's Bad You Know」や「Let My Baby Ride」などが人気。ロック・ヒップホップともコラボし、ブルース・リバイバルの立役者となりました。", 'type': 'output_text', 'logprobs': []}]
2. [USER]: [{'text': '子供はいますか?', 'type': 'input_text'}]
3. [ASSISTANT]: [{'annotations': [], 'text': 'はい、R.L. Burnsideには複数の子供がいます。なかでも息子のCedric Burnside(セドリック・バーンサイド)はドラマーおよびブルース・ミュージシャンとして有名です。CedricR.L.と一緒に演奏し、現在も活躍しています。', 'type': 'output_text', 'logprobs': []}]
==================================================

You: Cedric について教えてください
Bot: Cedric Burnside(セドリック・バーンサイド、1978年8月26日生まれ)は、アメリカ・ミシシッピ州出身のブルース・ドラマー、ギタリスト、シンガーです。祖父R.L. Burnsideのバンドで10代からドラムを担当し、ノース・ミシシッピ・ヒル・カントリー・ブルースの重要な継承者とされています。

ソロ活動でも評価が高く、グラミー賞を受賞(2022年「I Be Trying」)しました。タフなビートと魂のこもった歌声が特徴です。

==================================================
Session Contents:
==================================================
1. [ASSISTANT]: [{'annotations': [], 'text': 'はい、R.L. Burnsideには複数の子供がいます。なかでも息子のCedric Burnside(セドリック・バーンサイド)はドラマーおよびブルース・ミュージシャンとして有名です。CedricR.L.と一緒に演奏し、現在も活躍しています。', 'type': 'output_text', 'logprobs': []}]
2. [USER]: [{'text': 'Cedric について教えてください', 'type': 'input_text'}]
3. [ASSISTANT]: [{'annotations': [], 'text': 'Cedric Burnside(セドリック・バーンサイド、1978826日生まれ)は、アメリカ・ミシシッピ州出身のブルース・ドラマー、ギタリスト、シンガーです。祖父R.L. Burnsideのバンドで10代からドラムを担当し、ノース・ミシシッピ・ヒル・カントリー・ブルースの重要な継承者とされています。\n\nソロ活動でも評価が高く、グラミー賞を受賞(2022年「I Be Trying」)しました。タフなビートと魂のこもった歌声が特徴です。', 'type': 'output_text', 'logprobs': []}]
==================================================

You: 私が最初にした質問は何ですか?
Bot: あなたが最初にした質問は「R.L. Burnsideの子供は?」です。

==================================================
Session Contents:
==================================================
1. [ASSISTANT]: [{'annotations': [], 'text': 'Cedric Burnside(セドリック・バーンサイド、1978826日生まれ)は、アメリカ・ミシシッピ州出身のブルース・ドラマー、ギタリスト、シンガーです。祖父R.L. Burnsideのバンドで10代からドラムを担当し、ノース・ミシシッピ・ヒル・カントリー・ブルースの重要な継承者とされています。\n\nソロ活動でも評価が高く、グラミー賞を受賞(2022年「I Be Trying」)しました。タフなビートと魂のこもった歌声が特徴です。', 'type': 'output_text', 'logprobs': []}]
2. [USER]: [{'text': '私が最初にした質問は何ですか?', 'type': 'input_text'}]
3. [ASSISTANT]: [{'annotations': [], 'text': 'あなたが最初にした質問は「R.L. Burnsideの子供は?」です。', 'type': 'output_text', 'logprobs': []}]
==================================================

次回

次回以降は、mem0 や、CosmosDB + Vector Search を使って、長期記憶の実装を試してみます。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?